softpipe: document MAX_QUADS
[mesa.git] / src / gallium / drivers / softpipe / sp_setup.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * \brief Primitive rasterization/rendering (points, lines, triangles)
30 *
31 * \author Keith Whitwell <keith@tungstengraphics.com>
32 * \author Brian Paul
33 */
34
35 #include "sp_context.h"
36 #include "sp_quad.h"
37 #include "sp_quad_pipe.h"
38 #include "sp_setup.h"
39 #include "sp_state.h"
40 #include "draw/draw_context.h"
41 #include "draw/draw_vertex.h"
42 #include "pipe/p_shader_tokens.h"
43 #include "util/u_math.h"
44 #include "util/u_memory.h"
45
46
47 #define DEBUG_VERTS 0
48 #define DEBUG_FRAGS 0
49
50 /**
51 * Triangle edge info
52 */
53 struct edge {
54 float dx; /**< X(v1) - X(v0), used only during setup */
55 float dy; /**< Y(v1) - Y(v0), used only during setup */
56 float dxdy; /**< dx/dy */
57 float sx, sy; /**< first sample point coord */
58 int lines; /**< number of lines on this edge */
59 };
60
61
62 /**
63 * Max number of quads (2x2 pixel blocks) to process per batch.
64 * This can't be arbitrarily increased since we depend on some 32-bit
65 * bitmasks (two bits per quad).
66 */
67 #define MAX_QUADS 16
68
69
70 /**
71 * Triangle setup info (derived from draw_stage).
72 * Also used for line drawing (taking some liberties).
73 */
74 struct setup_context {
75 struct softpipe_context *softpipe;
76
77 /* Vertices are just an array of floats making up each attribute in
78 * turn. Currently fixed at 4 floats, but should change in time.
79 * Codegen will help cope with this.
80 */
81 const float (*vmax)[4];
82 const float (*vmid)[4];
83 const float (*vmin)[4];
84 const float (*vprovoke)[4];
85
86 struct edge ebot;
87 struct edge etop;
88 struct edge emaj;
89
90 float oneoverarea;
91 int facing;
92
93 float pixel_offset;
94
95 struct quad_header quad[MAX_QUADS];
96 struct quad_header *quad_ptrs[MAX_QUADS];
97 unsigned count;
98
99 struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
100 struct tgsi_interp_coef posCoef; /* For Z, W */
101
102 struct {
103 int left[2]; /**< [0] = row0, [1] = row1 */
104 int right[2];
105 int y;
106 } span;
107
108 #if DEBUG_FRAGS
109 uint numFragsEmitted; /**< per primitive */
110 uint numFragsWritten; /**< per primitive */
111 #endif
112
113 unsigned winding; /* which winding to cull */
114 unsigned nr_vertex_attrs;
115 };
116
117
118
119
120 /**
121 * Do triangle cull test using tri determinant (sign indicates orientation)
122 * \return true if triangle is to be culled.
123 */
124 static INLINE boolean
125 cull_tri(const struct setup_context *setup, float det)
126 {
127 if (det != 0) {
128 /* if (det < 0 then Z points toward camera and triangle is
129 * counter-clockwise winding.
130 */
131 unsigned winding = (det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW;
132
133 if ((winding & setup->winding) == 0)
134 return FALSE;
135 }
136
137 /* Culled:
138 */
139 return TRUE;
140 }
141
142
143
144 /**
145 * Clip setup->quad against the scissor/surface bounds.
146 */
147 static INLINE void
148 quad_clip( struct setup_context *setup, struct quad_header *quad )
149 {
150 const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
151 const int minx = (int) cliprect->minx;
152 const int maxx = (int) cliprect->maxx;
153 const int miny = (int) cliprect->miny;
154 const int maxy = (int) cliprect->maxy;
155
156 if (quad->input.x0 >= maxx ||
157 quad->input.y0 >= maxy ||
158 quad->input.x0 + 1 < minx ||
159 quad->input.y0 + 1 < miny) {
160 /* totally clipped */
161 quad->inout.mask = 0x0;
162 return;
163 }
164 if (quad->input.x0 < minx)
165 quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
166 if (quad->input.y0 < miny)
167 quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
168 if (quad->input.x0 == maxx - 1)
169 quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
170 if (quad->input.y0 == maxy - 1)
171 quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
172 }
173
174
175 /**
176 * Emit a quad (pass to next stage) with clipping.
177 */
178 static INLINE void
179 clip_emit_quad( struct setup_context *setup, struct quad_header *quad )
180 {
181 quad_clip( setup, quad );
182
183 if (quad->inout.mask) {
184 struct softpipe_context *sp = setup->softpipe;
185
186 sp->quad.first->run( sp->quad.first, &quad, 1 );
187 }
188 }
189
190
191
192 /**
193 * Given an X or Y coordinate, return the block/quad coordinate that it
194 * belongs to.
195 */
196 static INLINE int block( int x )
197 {
198 return x & ~(2-1);
199 }
200
201 static INLINE int block_x( int x )
202 {
203 return x & ~(16-1);
204 }
205
206
207 /**
208 * Render a horizontal span of quads
209 */
210 static void flush_spans( struct setup_context *setup )
211 {
212 const int step = MAX_QUADS;
213 const int xleft0 = setup->span.left[0];
214 const int xleft1 = setup->span.left[1];
215 const int xright0 = setup->span.right[0];
216 const int xright1 = setup->span.right[1];
217 struct quad_stage *pipe = setup->softpipe->quad.first;
218
219 const int minleft = block_x(MIN2(xleft0, xleft1));
220 const int maxright = MAX2(xright0, xright1);
221 int x;
222
223 /* process quads in horizontal chunks of 16 */
224 for (x = minleft; x < maxright; x += step) {
225 unsigned skip_left0 = CLAMP(xleft0 - x, 0, step);
226 unsigned skip_left1 = CLAMP(xleft1 - x, 0, step);
227 unsigned skip_right0 = CLAMP(x + step - xright0, 0, step);
228 unsigned skip_right1 = CLAMP(x + step - xright1, 0, step);
229 unsigned lx = x;
230 unsigned q = 0;
231
232 unsigned skipmask_left0 = (1U << skip_left0) - 1U;
233 unsigned skipmask_left1 = (1U << skip_left1) - 1U;
234
235 /* These calculations fail when step == 32 and skip_right == 0.
236 */
237 unsigned skipmask_right0 = ~0U << (unsigned)(step - skip_right0);
238 unsigned skipmask_right1 = ~0U << (unsigned)(step - skip_right1);
239
240 unsigned mask0 = ~skipmask_left0 & ~skipmask_right0;
241 unsigned mask1 = ~skipmask_left1 & ~skipmask_right1;
242
243 if (mask0 | mask1) {
244 do {
245 unsigned quadmask = (mask0 & 3) | ((mask1 & 3) << 2);
246 if (quadmask) {
247 setup->quad[q].input.x0 = lx;
248 setup->quad[q].input.y0 = setup->span.y;
249 setup->quad[q].input.facing = setup->facing;
250 setup->quad[q].inout.mask = quadmask;
251 setup->quad_ptrs[q] = &setup->quad[q];
252 q++;
253 }
254 mask0 >>= 2;
255 mask1 >>= 2;
256 lx += 2;
257 } while (mask0 | mask1);
258
259 pipe->run( pipe, setup->quad_ptrs, q );
260 }
261 }
262
263
264 setup->span.y = 0;
265 setup->span.right[0] = 0;
266 setup->span.right[1] = 0;
267 setup->span.left[0] = 1000000; /* greater than right[0] */
268 setup->span.left[1] = 1000000; /* greater than right[1] */
269 }
270
271
272 #if DEBUG_VERTS
273 static void print_vertex(const struct setup_context *setup,
274 const float (*v)[4])
275 {
276 int i;
277 debug_printf(" Vertex: (%p)\n", (void *) v);
278 for (i = 0; i < setup->nr_vertex_attrs; i++) {
279 debug_printf(" %d: %f %f %f %f\n", i,
280 v[i][0], v[i][1], v[i][2], v[i][3]);
281 if (util_is_inf_or_nan(v[i][0])) {
282 debug_printf(" NaN!\n");
283 }
284 }
285 }
286 #endif
287
288 /**
289 * Sort the vertices from top to bottom order, setting up the triangle
290 * edge fields (ebot, emaj, etop).
291 * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
292 */
293 static boolean setup_sort_vertices( struct setup_context *setup,
294 float det,
295 const float (*v0)[4],
296 const float (*v1)[4],
297 const float (*v2)[4] )
298 {
299 setup->vprovoke = v2;
300
301 /* determine bottom to top order of vertices */
302 {
303 float y0 = v0[0][1];
304 float y1 = v1[0][1];
305 float y2 = v2[0][1];
306 if (y0 <= y1) {
307 if (y1 <= y2) {
308 /* y0<=y1<=y2 */
309 setup->vmin = v0;
310 setup->vmid = v1;
311 setup->vmax = v2;
312 }
313 else if (y2 <= y0) {
314 /* y2<=y0<=y1 */
315 setup->vmin = v2;
316 setup->vmid = v0;
317 setup->vmax = v1;
318 }
319 else {
320 /* y0<=y2<=y1 */
321 setup->vmin = v0;
322 setup->vmid = v2;
323 setup->vmax = v1;
324 }
325 }
326 else {
327 if (y0 <= y2) {
328 /* y1<=y0<=y2 */
329 setup->vmin = v1;
330 setup->vmid = v0;
331 setup->vmax = v2;
332 }
333 else if (y2 <= y1) {
334 /* y2<=y1<=y0 */
335 setup->vmin = v2;
336 setup->vmid = v1;
337 setup->vmax = v0;
338 }
339 else {
340 /* y1<=y2<=y0 */
341 setup->vmin = v1;
342 setup->vmid = v2;
343 setup->vmax = v0;
344 }
345 }
346 }
347
348 setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0];
349 setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1];
350 setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
351 setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
352 setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0];
353 setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1];
354
355 /*
356 * Compute triangle's area. Use 1/area to compute partial
357 * derivatives of attributes later.
358 *
359 * The area will be the same as prim->det, but the sign may be
360 * different depending on how the vertices get sorted above.
361 *
362 * To determine whether the primitive is front or back facing we
363 * use the prim->det value because its sign is correct.
364 */
365 {
366 const float area = (setup->emaj.dx * setup->ebot.dy -
367 setup->ebot.dx * setup->emaj.dy);
368
369 setup->oneoverarea = 1.0f / area;
370
371 /*
372 debug_printf("%s one-over-area %f area %f det %f\n",
373 __FUNCTION__, setup->oneoverarea, area, det );
374 */
375 if (util_is_inf_or_nan(setup->oneoverarea))
376 return FALSE;
377 }
378
379 /* We need to know if this is a front or back-facing triangle for:
380 * - the GLSL gl_FrontFacing fragment attribute (bool)
381 * - two-sided stencil test
382 */
383 setup->facing =
384 ((det > 0.0) ^
385 (setup->softpipe->rasterizer->front_winding == PIPE_WINDING_CW));
386
387 /* Prepare pixel offset for rasterisation:
388 * - pixel center (0.5, 0.5) for GL, or
389 * - assume (0.0, 0.0) for other APIs.
390 */
391 if (setup->softpipe->rasterizer->gl_rasterization_rules) {
392 setup->pixel_offset = 0.5f;
393 } else {
394 setup->pixel_offset = 0.0f;
395 }
396
397 return TRUE;
398 }
399
400
401 /* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
402 * Input coordinates must be in [0, 1] range, otherwise results are undefined.
403 * Some combinations of coordinates produce invalid results,
404 * but this behaviour is acceptable.
405 */
406 static void
407 tri_apply_cylindrical_wrap(float v0,
408 float v1,
409 float v2,
410 uint cylindrical_wrap,
411 float output[3])
412 {
413 if (cylindrical_wrap) {
414 float delta;
415
416 delta = v1 - v0;
417 if (delta > 0.5f) {
418 v0 += 1.0f;
419 }
420 else if (delta < -0.5f) {
421 v1 += 1.0f;
422 }
423
424 delta = v2 - v1;
425 if (delta > 0.5f) {
426 v1 += 1.0f;
427 }
428 else if (delta < -0.5f) {
429 v2 += 1.0f;
430 }
431
432 delta = v0 - v2;
433 if (delta > 0.5f) {
434 v2 += 1.0f;
435 }
436 else if (delta < -0.5f) {
437 v0 += 1.0f;
438 }
439 }
440
441 output[0] = v0;
442 output[1] = v1;
443 output[2] = v2;
444 }
445
446
447 /**
448 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
449 * The value value comes from vertex[slot][i].
450 * The result will be put into setup->coef[slot].a0[i].
451 * \param slot which attribute slot
452 * \param i which component of the slot (0..3)
453 */
454 static void const_coeff( struct setup_context *setup,
455 struct tgsi_interp_coef *coef,
456 uint vertSlot, uint i)
457 {
458 assert(i <= 3);
459
460 coef->dadx[i] = 0;
461 coef->dady[i] = 0;
462
463 /* need provoking vertex info!
464 */
465 coef->a0[i] = setup->vprovoke[vertSlot][i];
466 }
467
468
469 /**
470 * Compute a0, dadx and dady for a linearly interpolated coefficient,
471 * for a triangle.
472 * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
473 */
474 static void
475 tri_linear_coeff(struct setup_context *setup,
476 struct tgsi_interp_coef *coef,
477 uint i,
478 const float v[3])
479 {
480 float botda = v[1] - v[0];
481 float majda = v[2] - v[0];
482 float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
483 float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
484 float dadx = a * setup->oneoverarea;
485 float dady = b * setup->oneoverarea;
486
487 assert(i <= 3);
488
489 coef->dadx[i] = dadx;
490 coef->dady[i] = dady;
491
492 /* calculate a0 as the value which would be sampled for the
493 * fragment at (0,0), taking into account that we want to sample at
494 * pixel centers, in other words (pixel_offset, pixel_offset).
495 *
496 * this is neat but unfortunately not a good way to do things for
497 * triangles with very large values of dadx or dady as it will
498 * result in the subtraction and re-addition from a0 of a very
499 * large number, which means we'll end up loosing a lot of the
500 * fractional bits and precision from a0. the way to fix this is
501 * to define a0 as the sample at a pixel center somewhere near vmin
502 * instead - i'll switch to this later.
503 */
504 coef->a0[i] = (v[0] -
505 (dadx * (setup->vmin[0][0] - setup->pixel_offset) +
506 dady * (setup->vmin[0][1] - setup->pixel_offset)));
507
508 /*
509 debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
510 slot, "xyzw"[i],
511 setup->coef[slot].a0[i],
512 setup->coef[slot].dadx[i],
513 setup->coef[slot].dady[i]);
514 */
515 }
516
517
518 /**
519 * Compute a0, dadx and dady for a perspective-corrected interpolant,
520 * for a triangle.
521 * We basically multiply the vertex value by 1/w before computing
522 * the plane coefficients (a0, dadx, dady).
523 * Later, when we compute the value at a particular fragment position we'll
524 * divide the interpolated value by the interpolated W at that fragment.
525 * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
526 */
527 static void
528 tri_persp_coeff(struct setup_context *setup,
529 struct tgsi_interp_coef *coef,
530 uint i,
531 const float v[3])
532 {
533 /* premultiply by 1/w (v[0][3] is always W):
534 */
535 float mina = v[0] * setup->vmin[0][3];
536 float mida = v[1] * setup->vmid[0][3];
537 float maxa = v[2] * setup->vmax[0][3];
538 float botda = mida - mina;
539 float majda = maxa - mina;
540 float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
541 float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
542 float dadx = a * setup->oneoverarea;
543 float dady = b * setup->oneoverarea;
544
545 /*
546 debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
547 setup->vmin[vertSlot][i],
548 setup->vmid[vertSlot][i],
549 setup->vmax[vertSlot][i]
550 );
551 */
552 assert(i <= 3);
553
554 coef->dadx[i] = dadx;
555 coef->dady[i] = dady;
556 coef->a0[i] = (mina -
557 (dadx * (setup->vmin[0][0] - setup->pixel_offset) +
558 dady * (setup->vmin[0][1] - setup->pixel_offset)));
559 }
560
561
562 /**
563 * Special coefficient setup for gl_FragCoord.
564 * X and Y are trivial, though Y may have to be inverted for OpenGL.
565 * Z and W are copied from posCoef which should have already been computed.
566 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
567 */
568 static void
569 setup_fragcoord_coeff(struct setup_context *setup, uint slot)
570 {
571 struct sp_fragment_shader* spfs = setup->softpipe->fs;
572 /*X*/
573 setup->coef[slot].a0[0] = spfs->pixel_center_integer ? 0.0 : 0.5;
574 setup->coef[slot].dadx[0] = 1.0;
575 setup->coef[slot].dady[0] = 0.0;
576 /*Y*/
577 setup->coef[slot].a0[1] =
578 (spfs->origin_lower_left ? setup->softpipe->framebuffer.height : 0)
579 + (spfs->pixel_center_integer ? 0.0 : 0.5);
580 setup->coef[slot].dadx[1] = 0.0;
581 setup->coef[slot].dady[1] = spfs->origin_lower_left ? -1.0 : 1.0;
582 /*Z*/
583 setup->coef[slot].a0[2] = setup->posCoef.a0[2];
584 setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
585 setup->coef[slot].dady[2] = setup->posCoef.dady[2];
586 /*W*/
587 setup->coef[slot].a0[3] = setup->posCoef.a0[3];
588 setup->coef[slot].dadx[3] = setup->posCoef.dadx[3];
589 setup->coef[slot].dady[3] = setup->posCoef.dady[3];
590 }
591
592
593
594 /**
595 * Compute the setup->coef[] array dadx, dady, a0 values.
596 * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
597 */
598 static void setup_tri_coefficients( struct setup_context *setup )
599 {
600 struct softpipe_context *softpipe = setup->softpipe;
601 const struct sp_fragment_shader *spfs = softpipe->fs;
602 const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
603 uint fragSlot;
604 float v[3];
605
606 /* z and w are done by linear interpolation:
607 */
608 v[0] = setup->vmin[0][2];
609 v[1] = setup->vmid[0][2];
610 v[2] = setup->vmax[0][2];
611 tri_linear_coeff(setup, &setup->posCoef, 2, v);
612
613 v[0] = setup->vmin[0][3];
614 v[1] = setup->vmid[0][3];
615 v[2] = setup->vmax[0][3];
616 tri_linear_coeff(setup, &setup->posCoef, 3, v);
617
618 /* setup interpolation for all the remaining attributes:
619 */
620 for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
621 const uint vertSlot = vinfo->attrib[fragSlot].src_index;
622 uint j;
623
624 switch (vinfo->attrib[fragSlot].interp_mode) {
625 case INTERP_CONSTANT:
626 for (j = 0; j < NUM_CHANNELS; j++)
627 const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
628 break;
629 case INTERP_LINEAR:
630 for (j = 0; j < NUM_CHANNELS; j++) {
631 tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
632 setup->vmid[vertSlot][j],
633 setup->vmax[vertSlot][j],
634 spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
635 v);
636 tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
637 }
638 break;
639 case INTERP_PERSPECTIVE:
640 for (j = 0; j < NUM_CHANNELS; j++) {
641 tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
642 setup->vmid[vertSlot][j],
643 setup->vmax[vertSlot][j],
644 spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
645 v);
646 tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
647 }
648 break;
649 case INTERP_POS:
650 setup_fragcoord_coeff(setup, fragSlot);
651 break;
652 default:
653 assert(0);
654 }
655
656 if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
657 setup->coef[fragSlot].a0[0] = 1.0f - setup->facing;
658 setup->coef[fragSlot].dadx[0] = 0.0;
659 setup->coef[fragSlot].dady[0] = 0.0;
660 }
661 }
662 }
663
664
665
666 static void setup_tri_edges( struct setup_context *setup )
667 {
668 float vmin_x = setup->vmin[0][0] + setup->pixel_offset;
669 float vmid_x = setup->vmid[0][0] + setup->pixel_offset;
670
671 float vmin_y = setup->vmin[0][1] - setup->pixel_offset;
672 float vmid_y = setup->vmid[0][1] - setup->pixel_offset;
673 float vmax_y = setup->vmax[0][1] - setup->pixel_offset;
674
675 setup->emaj.sy = ceilf(vmin_y);
676 setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
677 setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
678 setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
679
680 setup->etop.sy = ceilf(vmid_y);
681 setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
682 setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
683 setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
684
685 setup->ebot.sy = ceilf(vmin_y);
686 setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
687 setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
688 setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
689 }
690
691
692 /**
693 * Render the upper or lower half of a triangle.
694 * Scissoring/cliprect is applied here too.
695 */
696 static void subtriangle( struct setup_context *setup,
697 struct edge *eleft,
698 struct edge *eright,
699 int lines )
700 {
701 const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
702 const int minx = (int) cliprect->minx;
703 const int maxx = (int) cliprect->maxx;
704 const int miny = (int) cliprect->miny;
705 const int maxy = (int) cliprect->maxy;
706 int y, start_y, finish_y;
707 int sy = (int)eleft->sy;
708
709 assert((int)eleft->sy == (int) eright->sy);
710 assert(lines >= 0);
711
712 /* clip top/bottom */
713 start_y = sy;
714 if (start_y < miny)
715 start_y = miny;
716
717 finish_y = sy + lines;
718 if (finish_y > maxy)
719 finish_y = maxy;
720
721 start_y -= sy;
722 finish_y -= sy;
723
724 /*
725 debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
726 */
727
728 for (y = start_y; y < finish_y; y++) {
729
730 /* avoid accumulating adds as floats don't have the precision to
731 * accurately iterate large triangle edges that way. luckily we
732 * can just multiply these days.
733 *
734 * this is all drowned out by the attribute interpolation anyway.
735 */
736 int left = (int)(eleft->sx + y * eleft->dxdy);
737 int right = (int)(eright->sx + y * eright->dxdy);
738
739 /* clip left/right */
740 if (left < minx)
741 left = minx;
742 if (right > maxx)
743 right = maxx;
744
745 if (left < right) {
746 int _y = sy + y;
747 if (block(_y) != setup->span.y) {
748 flush_spans(setup);
749 setup->span.y = block(_y);
750 }
751
752 setup->span.left[_y&1] = left;
753 setup->span.right[_y&1] = right;
754 }
755 }
756
757
758 /* save the values so that emaj can be restarted:
759 */
760 eleft->sx += lines * eleft->dxdy;
761 eright->sx += lines * eright->dxdy;
762 eleft->sy += lines;
763 eright->sy += lines;
764 }
765
766
767 /**
768 * Recalculate prim's determinant. This is needed as we don't have
769 * get this information through the vbuf_render interface & we must
770 * calculate it here.
771 */
772 static float
773 calc_det( const float (*v0)[4],
774 const float (*v1)[4],
775 const float (*v2)[4] )
776 {
777 /* edge vectors e = v0 - v2, f = v1 - v2 */
778 const float ex = v0[0][0] - v2[0][0];
779 const float ey = v0[0][1] - v2[0][1];
780 const float fx = v1[0][0] - v2[0][0];
781 const float fy = v1[0][1] - v2[0][1];
782
783 /* det = cross(e,f).z */
784 return ex * fy - ey * fx;
785 }
786
787
788 /**
789 * Do setup for triangle rasterization, then render the triangle.
790 */
791 void sp_setup_tri( struct setup_context *setup,
792 const float (*v0)[4],
793 const float (*v1)[4],
794 const float (*v2)[4] )
795 {
796 float det;
797
798 #if DEBUG_VERTS
799 debug_printf("Setup triangle:\n");
800 print_vertex(setup, v0);
801 print_vertex(setup, v1);
802 print_vertex(setup, v2);
803 #endif
804
805 if (setup->softpipe->no_rast)
806 return;
807
808 det = calc_det(v0, v1, v2);
809 /*
810 debug_printf("%s\n", __FUNCTION__ );
811 */
812
813 #if DEBUG_FRAGS
814 setup->numFragsEmitted = 0;
815 setup->numFragsWritten = 0;
816 #endif
817
818 if (cull_tri( setup, det ))
819 return;
820
821 if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
822 return;
823 setup_tri_coefficients( setup );
824 setup_tri_edges( setup );
825
826 assert(setup->softpipe->reduced_prim == PIPE_PRIM_TRIANGLES);
827
828 setup->span.y = 0;
829 setup->span.right[0] = 0;
830 setup->span.right[1] = 0;
831 /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
832
833 /* init_constant_attribs( setup ); */
834
835 if (setup->oneoverarea < 0.0) {
836 /* emaj on left:
837 */
838 subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
839 subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
840 }
841 else {
842 /* emaj on right:
843 */
844 subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
845 subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
846 }
847
848 flush_spans( setup );
849
850 #if DEBUG_FRAGS
851 printf("Tri: %u frags emitted, %u written\n",
852 setup->numFragsEmitted,
853 setup->numFragsWritten);
854 #endif
855 }
856
857
858 /* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
859 * Input coordinates must be in [0, 1] range, otherwise results are undefined.
860 */
861 static void
862 line_apply_cylindrical_wrap(float v0,
863 float v1,
864 uint cylindrical_wrap,
865 float output[2])
866 {
867 if (cylindrical_wrap) {
868 float delta;
869
870 delta = v1 - v0;
871 if (delta > 0.5f) {
872 v0 += 1.0f;
873 }
874 else if (delta < -0.5f) {
875 v1 += 1.0f;
876 }
877 }
878
879 output[0] = v0;
880 output[1] = v1;
881 }
882
883
884 /**
885 * Compute a0, dadx and dady for a linearly interpolated coefficient,
886 * for a line.
887 * v[0] and v[1] are vmin and vmax, respectively.
888 */
889 static void
890 line_linear_coeff(const struct setup_context *setup,
891 struct tgsi_interp_coef *coef,
892 uint i,
893 const float v[2])
894 {
895 const float da = v[1] - v[0];
896 const float dadx = da * setup->emaj.dx * setup->oneoverarea;
897 const float dady = da * setup->emaj.dy * setup->oneoverarea;
898 coef->dadx[i] = dadx;
899 coef->dady[i] = dady;
900 coef->a0[i] = (v[0] -
901 (dadx * (setup->vmin[0][0] - setup->pixel_offset) +
902 dady * (setup->vmin[0][1] - setup->pixel_offset)));
903 }
904
905
906 /**
907 * Compute a0, dadx and dady for a perspective-corrected interpolant,
908 * for a line.
909 * v[0] and v[1] are vmin and vmax, respectively.
910 */
911 static void
912 line_persp_coeff(const struct setup_context *setup,
913 struct tgsi_interp_coef *coef,
914 uint i,
915 const float v[2])
916 {
917 const float a0 = v[0] * setup->vmin[0][3];
918 const float a1 = v[1] * setup->vmax[0][3];
919 const float da = a1 - a0;
920 const float dadx = da * setup->emaj.dx * setup->oneoverarea;
921 const float dady = da * setup->emaj.dy * setup->oneoverarea;
922 coef->dadx[i] = dadx;
923 coef->dady[i] = dady;
924 coef->a0[i] = (a0 -
925 (dadx * (setup->vmin[0][0] - setup->pixel_offset) +
926 dady * (setup->vmin[0][1] - setup->pixel_offset)));
927 }
928
929
930 /**
931 * Compute the setup->coef[] array dadx, dady, a0 values.
932 * Must be called after setup->vmin,vmax are initialized.
933 */
934 static INLINE boolean
935 setup_line_coefficients(struct setup_context *setup,
936 const float (*v0)[4],
937 const float (*v1)[4])
938 {
939 struct softpipe_context *softpipe = setup->softpipe;
940 const struct sp_fragment_shader *spfs = softpipe->fs;
941 const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
942 uint fragSlot;
943 float area;
944 float v[2];
945
946 /* use setup->vmin, vmax to point to vertices */
947 if (softpipe->rasterizer->flatshade_first)
948 setup->vprovoke = v0;
949 else
950 setup->vprovoke = v1;
951 setup->vmin = v0;
952 setup->vmax = v1;
953
954 setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
955 setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
956
957 /* NOTE: this is not really area but something proportional to it */
958 area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy;
959 if (area == 0.0f || util_is_inf_or_nan(area))
960 return FALSE;
961 setup->oneoverarea = 1.0f / area;
962
963 /* z and w are done by linear interpolation:
964 */
965 v[0] = setup->vmin[0][2];
966 v[1] = setup->vmax[0][2];
967 line_linear_coeff(setup, &setup->posCoef, 2, v);
968
969 v[0] = setup->vmin[0][3];
970 v[1] = setup->vmax[0][3];
971 line_linear_coeff(setup, &setup->posCoef, 3, v);
972
973 /* setup interpolation for all the remaining attributes:
974 */
975 for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
976 const uint vertSlot = vinfo->attrib[fragSlot].src_index;
977 uint j;
978
979 switch (vinfo->attrib[fragSlot].interp_mode) {
980 case INTERP_CONSTANT:
981 for (j = 0; j < NUM_CHANNELS; j++)
982 const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
983 break;
984 case INTERP_LINEAR:
985 for (j = 0; j < NUM_CHANNELS; j++) {
986 line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
987 setup->vmax[vertSlot][j],
988 spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
989 v);
990 line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
991 }
992 break;
993 case INTERP_PERSPECTIVE:
994 for (j = 0; j < NUM_CHANNELS; j++) {
995 line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
996 setup->vmax[vertSlot][j],
997 spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
998 v);
999 line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
1000 }
1001 break;
1002 case INTERP_POS:
1003 setup_fragcoord_coeff(setup, fragSlot);
1004 break;
1005 default:
1006 assert(0);
1007 }
1008
1009 if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
1010 setup->coef[fragSlot].a0[0] = 1.0f - setup->facing;
1011 setup->coef[fragSlot].dadx[0] = 0.0;
1012 setup->coef[fragSlot].dady[0] = 0.0;
1013 }
1014 }
1015 return TRUE;
1016 }
1017
1018
1019 /**
1020 * Plot a pixel in a line segment.
1021 */
1022 static INLINE void
1023 plot(struct setup_context *setup, int x, int y)
1024 {
1025 const int iy = y & 1;
1026 const int ix = x & 1;
1027 const int quadX = x - ix;
1028 const int quadY = y - iy;
1029 const int mask = (1 << ix) << (2 * iy);
1030
1031 if (quadX != setup->quad[0].input.x0 ||
1032 quadY != setup->quad[0].input.y0)
1033 {
1034 /* flush prev quad, start new quad */
1035
1036 if (setup->quad[0].input.x0 != -1)
1037 clip_emit_quad( setup, &setup->quad[0] );
1038
1039 setup->quad[0].input.x0 = quadX;
1040 setup->quad[0].input.y0 = quadY;
1041 setup->quad[0].inout.mask = 0x0;
1042 }
1043
1044 setup->quad[0].inout.mask |= mask;
1045 }
1046
1047
1048 /**
1049 * Do setup for line rasterization, then render the line.
1050 * Single-pixel width, no stipple, etc. We rely on the 'draw' module
1051 * to handle stippling and wide lines.
1052 */
1053 void
1054 sp_setup_line(struct setup_context *setup,
1055 const float (*v0)[4],
1056 const float (*v1)[4])
1057 {
1058 int x0 = (int) v0[0][0];
1059 int x1 = (int) v1[0][0];
1060 int y0 = (int) v0[0][1];
1061 int y1 = (int) v1[0][1];
1062 int dx = x1 - x0;
1063 int dy = y1 - y0;
1064 int xstep, ystep;
1065
1066 #if DEBUG_VERTS
1067 debug_printf("Setup line:\n");
1068 print_vertex(setup, v0);
1069 print_vertex(setup, v1);
1070 #endif
1071
1072 if (setup->softpipe->no_rast)
1073 return;
1074
1075 if (dx == 0 && dy == 0)
1076 return;
1077
1078 if (!setup_line_coefficients(setup, v0, v1))
1079 return;
1080
1081 assert(v0[0][0] < 1.0e9);
1082 assert(v0[0][1] < 1.0e9);
1083 assert(v1[0][0] < 1.0e9);
1084 assert(v1[0][1] < 1.0e9);
1085
1086 if (dx < 0) {
1087 dx = -dx; /* make positive */
1088 xstep = -1;
1089 }
1090 else {
1091 xstep = 1;
1092 }
1093
1094 if (dy < 0) {
1095 dy = -dy; /* make positive */
1096 ystep = -1;
1097 }
1098 else {
1099 ystep = 1;
1100 }
1101
1102 assert(dx >= 0);
1103 assert(dy >= 0);
1104 assert(setup->softpipe->reduced_prim == PIPE_PRIM_LINES);
1105
1106 setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1;
1107 setup->quad[0].inout.mask = 0x0;
1108
1109 /* XXX temporary: set coverage to 1.0 so the line appears
1110 * if AA mode happens to be enabled.
1111 */
1112 setup->quad[0].input.coverage[0] =
1113 setup->quad[0].input.coverage[1] =
1114 setup->quad[0].input.coverage[2] =
1115 setup->quad[0].input.coverage[3] = 1.0;
1116
1117 if (dx > dy) {
1118 /*** X-major line ***/
1119 int i;
1120 const int errorInc = dy + dy;
1121 int error = errorInc - dx;
1122 const int errorDec = error - dx;
1123
1124 for (i = 0; i < dx; i++) {
1125 plot(setup, x0, y0);
1126
1127 x0 += xstep;
1128 if (error < 0) {
1129 error += errorInc;
1130 }
1131 else {
1132 error += errorDec;
1133 y0 += ystep;
1134 }
1135 }
1136 }
1137 else {
1138 /*** Y-major line ***/
1139 int i;
1140 const int errorInc = dx + dx;
1141 int error = errorInc - dy;
1142 const int errorDec = error - dy;
1143
1144 for (i = 0; i < dy; i++) {
1145 plot(setup, x0, y0);
1146
1147 y0 += ystep;
1148 if (error < 0) {
1149 error += errorInc;
1150 }
1151 else {
1152 error += errorDec;
1153 x0 += xstep;
1154 }
1155 }
1156 }
1157
1158 /* draw final quad */
1159 if (setup->quad[0].inout.mask) {
1160 clip_emit_quad( setup, &setup->quad[0] );
1161 }
1162 }
1163
1164
1165 static void
1166 point_persp_coeff(const struct setup_context *setup,
1167 const float (*vert)[4],
1168 struct tgsi_interp_coef *coef,
1169 uint vertSlot, uint i)
1170 {
1171 assert(i <= 3);
1172 coef->dadx[i] = 0.0F;
1173 coef->dady[i] = 0.0F;
1174 coef->a0[i] = vert[vertSlot][i] * vert[0][3];
1175 }
1176
1177
1178 /**
1179 * Do setup for point rasterization, then render the point.
1180 * Round or square points...
1181 * XXX could optimize a lot for 1-pixel points.
1182 */
1183 void
1184 sp_setup_point( struct setup_context *setup,
1185 const float (*v0)[4] )
1186 {
1187 struct softpipe_context *softpipe = setup->softpipe;
1188 const struct sp_fragment_shader *spfs = softpipe->fs;
1189 const int sizeAttr = setup->softpipe->psize_slot;
1190 const float size
1191 = sizeAttr > 0 ? v0[sizeAttr][0]
1192 : setup->softpipe->rasterizer->point_size;
1193 const float halfSize = 0.5F * size;
1194 const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth;
1195 const float x = v0[0][0]; /* Note: data[0] is always position */
1196 const float y = v0[0][1];
1197 const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
1198 uint fragSlot;
1199
1200 #if DEBUG_VERTS
1201 debug_printf("Setup point:\n");
1202 print_vertex(setup, v0);
1203 #endif
1204
1205 if (softpipe->no_rast)
1206 return;
1207
1208 assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS);
1209
1210 /* For points, all interpolants are constant-valued.
1211 * However, for point sprites, we'll need to setup texcoords appropriately.
1212 * XXX: which coefficients are the texcoords???
1213 * We may do point sprites as textured quads...
1214 *
1215 * KW: We don't know which coefficients are texcoords - ultimately
1216 * the choice of what interpolation mode to use for each attribute
1217 * should be determined by the fragment program, using
1218 * per-attribute declaration statements that include interpolation
1219 * mode as a parameter. So either the fragment program will have
1220 * to be adjusted for pointsprite vs normal point behaviour, or
1221 * otherwise a special interpolation mode will have to be defined
1222 * which matches the required behaviour for point sprites. But -
1223 * the latter is not a feature of normal hardware, and as such
1224 * probably should be ruled out on that basis.
1225 */
1226 setup->vprovoke = v0;
1227
1228 /* setup Z, W */
1229 const_coeff(setup, &setup->posCoef, 0, 2);
1230 const_coeff(setup, &setup->posCoef, 0, 3);
1231
1232 for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
1233 const uint vertSlot = vinfo->attrib[fragSlot].src_index;
1234 uint j;
1235
1236 switch (vinfo->attrib[fragSlot].interp_mode) {
1237 case INTERP_CONSTANT:
1238 /* fall-through */
1239 case INTERP_LINEAR:
1240 for (j = 0; j < NUM_CHANNELS; j++)
1241 const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
1242 break;
1243 case INTERP_PERSPECTIVE:
1244 for (j = 0; j < NUM_CHANNELS; j++)
1245 point_persp_coeff(setup, setup->vprovoke,
1246 &setup->coef[fragSlot], vertSlot, j);
1247 break;
1248 case INTERP_POS:
1249 setup_fragcoord_coeff(setup, fragSlot);
1250 break;
1251 default:
1252 assert(0);
1253 }
1254
1255 if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
1256 setup->coef[fragSlot].a0[0] = 1.0f - setup->facing;
1257 setup->coef[fragSlot].dadx[0] = 0.0;
1258 setup->coef[fragSlot].dady[0] = 0.0;
1259 }
1260 }
1261
1262
1263 if (halfSize <= 0.5 && !round) {
1264 /* special case for 1-pixel points */
1265 const int ix = ((int) x) & 1;
1266 const int iy = ((int) y) & 1;
1267 setup->quad[0].input.x0 = (int) x - ix;
1268 setup->quad[0].input.y0 = (int) y - iy;
1269 setup->quad[0].inout.mask = (1 << ix) << (2 * iy);
1270 clip_emit_quad( setup, &setup->quad[0] );
1271 }
1272 else {
1273 if (round) {
1274 /* rounded points */
1275 const int ixmin = block((int) (x - halfSize));
1276 const int ixmax = block((int) (x + halfSize));
1277 const int iymin = block((int) (y - halfSize));
1278 const int iymax = block((int) (y + halfSize));
1279 const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
1280 const float rmax = halfSize + 0.7071F;
1281 const float rmin2 = MAX2(0.0F, rmin * rmin);
1282 const float rmax2 = rmax * rmax;
1283 const float cscale = 1.0F / (rmax2 - rmin2);
1284 int ix, iy;
1285
1286 for (iy = iymin; iy <= iymax; iy += 2) {
1287 for (ix = ixmin; ix <= ixmax; ix += 2) {
1288 float dx, dy, dist2, cover;
1289
1290 setup->quad[0].inout.mask = 0x0;
1291
1292 dx = (ix + 0.5f) - x;
1293 dy = (iy + 0.5f) - y;
1294 dist2 = dx * dx + dy * dy;
1295 if (dist2 <= rmax2) {
1296 cover = 1.0F - (dist2 - rmin2) * cscale;
1297 setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
1298 setup->quad[0].inout.mask |= MASK_TOP_LEFT;
1299 }
1300
1301 dx = (ix + 1.5f) - x;
1302 dy = (iy + 0.5f) - y;
1303 dist2 = dx * dx + dy * dy;
1304 if (dist2 <= rmax2) {
1305 cover = 1.0F - (dist2 - rmin2) * cscale;
1306 setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
1307 setup->quad[0].inout.mask |= MASK_TOP_RIGHT;
1308 }
1309
1310 dx = (ix + 0.5f) - x;
1311 dy = (iy + 1.5f) - y;
1312 dist2 = dx * dx + dy * dy;
1313 if (dist2 <= rmax2) {
1314 cover = 1.0F - (dist2 - rmin2) * cscale;
1315 setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
1316 setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT;
1317 }
1318
1319 dx = (ix + 1.5f) - x;
1320 dy = (iy + 1.5f) - y;
1321 dist2 = dx * dx + dy * dy;
1322 if (dist2 <= rmax2) {
1323 cover = 1.0F - (dist2 - rmin2) * cscale;
1324 setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
1325 setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT;
1326 }
1327
1328 if (setup->quad[0].inout.mask) {
1329 setup->quad[0].input.x0 = ix;
1330 setup->quad[0].input.y0 = iy;
1331 clip_emit_quad( setup, &setup->quad[0] );
1332 }
1333 }
1334 }
1335 }
1336 else {
1337 /* square points */
1338 const int xmin = (int) (x + 0.75 - halfSize);
1339 const int ymin = (int) (y + 0.25 - halfSize);
1340 const int xmax = xmin + (int) size;
1341 const int ymax = ymin + (int) size;
1342 /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
1343 const int ixmin = block(xmin);
1344 const int ixmax = block(xmax - 1);
1345 const int iymin = block(ymin);
1346 const int iymax = block(ymax - 1);
1347 int ix, iy;
1348
1349 /*
1350 debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
1351 */
1352 for (iy = iymin; iy <= iymax; iy += 2) {
1353 uint rowMask = 0xf;
1354 if (iy < ymin) {
1355 /* above the top edge */
1356 rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
1357 }
1358 if (iy + 1 >= ymax) {
1359 /* below the bottom edge */
1360 rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
1361 }
1362
1363 for (ix = ixmin; ix <= ixmax; ix += 2) {
1364 uint mask = rowMask;
1365
1366 if (ix < xmin) {
1367 /* fragment is past left edge of point, turn off left bits */
1368 mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
1369 }
1370 if (ix + 1 >= xmax) {
1371 /* past the right edge */
1372 mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
1373 }
1374
1375 setup->quad[0].inout.mask = mask;
1376 setup->quad[0].input.x0 = ix;
1377 setup->quad[0].input.y0 = iy;
1378 clip_emit_quad( setup, &setup->quad[0] );
1379 }
1380 }
1381 }
1382 }
1383 }
1384
1385 void sp_setup_prepare( struct setup_context *setup )
1386 {
1387 struct softpipe_context *sp = setup->softpipe;
1388
1389 if (sp->dirty) {
1390 softpipe_update_derived(sp);
1391 }
1392
1393 /* Note: nr_attrs is only used for debugging (vertex printing) */
1394 setup->nr_vertex_attrs = draw_num_shader_outputs(sp->draw);
1395
1396 sp->quad.first->begin( sp->quad.first );
1397
1398 if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
1399 sp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL &&
1400 sp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) {
1401 /* we'll do culling */
1402 setup->winding = sp->rasterizer->cull_mode;
1403 }
1404 else {
1405 /* 'draw' will do culling */
1406 setup->winding = PIPE_WINDING_NONE;
1407 }
1408 }
1409
1410
1411
1412 void sp_setup_destroy_context( struct setup_context *setup )
1413 {
1414 FREE( setup );
1415 }
1416
1417
1418 /**
1419 * Create a new primitive setup/render stage.
1420 */
1421 struct setup_context *sp_setup_create_context( struct softpipe_context *softpipe )
1422 {
1423 struct setup_context *setup = CALLOC_STRUCT(setup_context);
1424 unsigned i;
1425
1426 setup->softpipe = softpipe;
1427
1428 for (i = 0; i < MAX_QUADS; i++) {
1429 setup->quad[i].coef = setup->coef;
1430 setup->quad[i].posCoef = &setup->posCoef;
1431 }
1432
1433 setup->span.left[0] = 1000000; /* greater than right[0] */
1434 setup->span.left[1] = 1000000; /* greater than right[1] */
1435
1436 return setup;
1437 }
1438