remove some of the #ifndef MESA stuff
[mesa.git] / src / mesa / pipe / softpipe / sp_prim_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
36 #include "sp_context.h"
37 #include "sp_headers.h"
38 #include "sp_quad.h"
39 #include "sp_prim_setup.h"
40 #include "pipe/draw/draw_private.h"
41 #include "pipe/p_util.h"
42
43
44 /** XXX remove */
45 #define FRAG_ATTRIB_WPOS 0
46 #define FRAG_ATTRIB_MAX 13
47
48
49 /**
50 * Triangle edge info
51 */
52 struct edge {
53 float dx; /**< X(v1) - X(v0), used only during setup */
54 float dy; /**< Y(v1) - Y(v0), used only during setup */
55 float dxdy; /**< dx/dy */
56 float sx, sy; /**< first sample point coord */
57 int lines; /**< number of lines on this edge */
58 };
59
60
61 /**
62 * Triangle setup info (derived from draw_stage).
63 * Also used for line drawing (taking some liberties).
64 */
65 struct setup_stage {
66 struct draw_stage stage; /**< This must be first (base class) */
67
68 struct softpipe_context *softpipe;
69
70 /* Vertices are just an array of floats making up each attribute in
71 * turn. Currently fixed at 4 floats, but should change in time.
72 * Codegen will help cope with this.
73 */
74 const struct vertex_header *vmax;
75 const struct vertex_header *vmid;
76 const struct vertex_header *vmin;
77 const struct vertex_header *vprovoke;
78
79 struct edge ebot;
80 struct edge etop;
81 struct edge emaj;
82
83 float oneoverarea;
84
85 struct tgsi_interp_coef coef[FRAG_ATTRIB_MAX];
86 struct quad_header quad;
87
88 struct {
89 int left[2]; /**< [0] = row0, [1] = row1 */
90 int right[2];
91 int y;
92 unsigned y_flags;
93 unsigned mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
94 } span;
95 };
96
97
98
99 /**
100 * Basically a cast wrapper.
101 */
102 static INLINE struct setup_stage *setup_stage( struct draw_stage *stage )
103 {
104 return (struct setup_stage *)stage;
105 }
106
107
108 /**
109 * Clip setup->quad against the scissor/surface bounds.
110 */
111 static INLINE void
112 quad_clip(struct setup_stage *setup)
113 {
114 const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
115 const int minx = (int) cliprect->minx;
116 const int maxx = (int) cliprect->maxx;
117 const int miny = (int) cliprect->miny;
118 const int maxy = (int) cliprect->maxy;
119
120 if (setup->quad.x0 >= maxx ||
121 setup->quad.y0 >= maxy ||
122 setup->quad.x0 + 1 < minx ||
123 setup->quad.y0 + 1 < miny) {
124 /* totally clipped */
125 setup->quad.mask = 0x0;
126 return;
127 }
128 if (setup->quad.x0 < minx)
129 setup->quad.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
130 if (setup->quad.y0 < miny)
131 setup->quad.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
132 if (setup->quad.x0 == maxx - 1)
133 setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
134 if (setup->quad.y0 == maxy - 1)
135 setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
136 }
137
138
139 /**
140 * Emit a quad (pass to next stage) with clipping.
141 */
142 static INLINE void
143 clip_emit_quad(struct setup_stage *setup)
144 {
145 quad_clip(setup);
146 if (setup->quad.mask) {
147 struct softpipe_context *sp = setup->softpipe;
148 sp->quad.first->run(sp->quad.first, &setup->quad);
149 }
150 }
151
152
153 /**
154 * Emit a quad (pass to next stage). No clipping is done.
155 */
156 static INLINE void
157 emit_quad( struct setup_stage *setup, int x, int y, unsigned mask )
158 {
159 struct softpipe_context *sp = setup->softpipe;
160 setup->quad.x0 = x;
161 setup->quad.y0 = y;
162 setup->quad.mask = mask;
163 sp->quad.first->run(sp->quad.first, &setup->quad);
164 }
165
166
167 /**
168 * Given an X or Y coordinate, return the block/quad coordinate that it
169 * belongs to.
170 */
171 static INLINE int block( int x )
172 {
173 return x & ~1;
174 }
175
176
177 /**
178 * Compute mask which indicates which pixels in the 2x2 quad are actually inside
179 * the triangle's bounds.
180 *
181 * this is pretty nasty... may need to rework flush_spans again to
182 * fix it, if possible.
183 */
184 static unsigned calculate_mask( struct setup_stage *setup,
185 int x )
186 {
187 unsigned mask = 0;
188
189 if (x >= setup->span.left[0] && x < setup->span.right[0])
190 mask |= MASK_BOTTOM_LEFT;
191
192 if (x >= setup->span.left[1] && x < setup->span.right[1])
193 mask |= MASK_TOP_LEFT;
194
195 if (x+1 >= setup->span.left[0] && x+1 < setup->span.right[0])
196 mask |= MASK_BOTTOM_RIGHT;
197
198 if (x+1 >= setup->span.left[1] && x+1 < setup->span.right[1])
199 mask |= MASK_TOP_RIGHT;
200
201 return mask;
202 }
203
204
205 /**
206 * Render a horizontal span of quads
207 */
208 static void flush_spans( struct setup_stage *setup )
209 {
210 int minleft, maxright;
211 int x;
212
213 switch (setup->span.y_flags) {
214 case 3:
215 minleft = MIN2(setup->span.left[0], setup->span.left[1]);
216 maxright = MAX2(setup->span.right[0], setup->span.right[1]);
217 break;
218
219 case 1:
220 minleft = setup->span.left[0];
221 maxright = setup->span.right[0];
222 break;
223
224 case 2:
225 minleft = setup->span.left[1];
226 maxright = setup->span.right[1];
227 break;
228
229 default:
230 return;
231 }
232
233
234 for (x = block(minleft); x <= block(maxright); )
235 {
236 emit_quad( setup, x, setup->span.y,
237 calculate_mask( setup, x ) );
238 x += 2;
239 }
240
241 setup->span.y = 0;
242 setup->span.y_flags = 0;
243 setup->span.right[0] = 0;
244 setup->span.right[1] = 0;
245 }
246
247 #if 0
248 static void print_vertex(const struct setup_stage *setup,
249 const struct vertex_header *v)
250 {
251 int i;
252 printf("Vertex:\n");
253 for (i = 0; i < setup->softpipe->nr_attrs; i++) {
254 printf(" %d: %f %f %f\n", i,
255 v->data[i][0], v->data[i][1], v->data[i][2]);
256 }
257 }
258 #endif
259
260 static boolean setup_sort_vertices( struct setup_stage *setup,
261 const struct prim_header *prim )
262 {
263 const struct vertex_header *v0 = prim->v[0];
264 const struct vertex_header *v1 = prim->v[1];
265 const struct vertex_header *v2 = prim->v[2];
266
267 #if 0
268 printf("Triangle:\n");
269 print_vertex(setup, v0);
270 print_vertex(setup, v1);
271 print_vertex(setup, v2);
272 #endif
273
274 setup->vprovoke = v2;
275
276 /* determine bottom to top order of vertices */
277 {
278 float y0 = v0->data[0][1];
279 float y1 = v1->data[0][1];
280 float y2 = v2->data[0][1];
281 if (y0 <= y1) {
282 if (y1 <= y2) {
283 /* y0<=y1<=y2 */
284 setup->vmin = v0;
285 setup->vmid = v1;
286 setup->vmax = v2;
287 }
288 else if (y2 <= y0) {
289 /* y2<=y0<=y1 */
290 setup->vmin = v2;
291 setup->vmid = v0;
292 setup->vmax = v1;
293 }
294 else {
295 /* y0<=y2<=y1 */
296 setup->vmin = v0;
297 setup->vmid = v2;
298 setup->vmax = v1;
299 }
300 }
301 else {
302 if (y0 <= y2) {
303 /* y1<=y0<=y2 */
304 setup->vmin = v1;
305 setup->vmid = v0;
306 setup->vmax = v2;
307 }
308 else if (y2 <= y1) {
309 /* y2<=y1<=y0 */
310 setup->vmin = v2;
311 setup->vmid = v1;
312 setup->vmax = v0;
313 }
314 else {
315 /* y1<=y2<=y0 */
316 setup->vmin = v1;
317 setup->vmid = v2;
318 setup->vmax = v0;
319 }
320 }
321 }
322
323 setup->ebot.dx = setup->vmid->data[0][0] - setup->vmin->data[0][0];
324 setup->ebot.dy = setup->vmid->data[0][1] - setup->vmin->data[0][1];
325 setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
326 setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
327 setup->etop.dx = setup->vmax->data[0][0] - setup->vmid->data[0][0];
328 setup->etop.dy = setup->vmax->data[0][1] - setup->vmid->data[0][1];
329
330 /*
331 * Compute triangle's area. Use 1/area to compute partial
332 * derivatives of attributes later.
333 *
334 * The area will be the same as prim->det, but the sign may be
335 * different depending on how the vertices get sorted above.
336 *
337 * To determine whether the primitive is front or back facing we
338 * use the prim->det value because its sign is correct.
339 */
340 {
341 const float area = (setup->emaj.dx * setup->ebot.dy -
342 setup->ebot.dx * setup->emaj.dy);
343
344 setup->oneoverarea = 1.0f / area;
345 /*
346 _mesa_printf("%s one-over-area %f area %f det %f\n",
347 __FUNCTION__, setup->oneoverarea, area, prim->det );
348 */
349 }
350
351 /* We need to know if this is a front or back-facing triangle for:
352 * - the GLSL gl_FrontFacing fragment attribute (bool)
353 * - two-sided stencil test
354 */
355 setup->quad.facing = (prim->det > 0.0) ^ (setup->softpipe->setup.front_winding == PIPE_WINDING_CW);
356
357 return TRUE;
358 }
359
360
361 /**
362 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
363 * The value value comes from vertex->data[slot][i].
364 * The result will be put into setup->coef[slot].a0[i].
365 * \param slot which attribute slot
366 * \param i which component of the slot (0..3)
367 */
368 static void const_coeff( struct setup_stage *setup,
369 unsigned slot,
370 unsigned i )
371 {
372 assert(slot < FRAG_ATTRIB_MAX);
373 assert(i <= 3);
374
375 setup->coef[slot].dadx[i] = 0;
376 setup->coef[slot].dady[i] = 0;
377
378 /* need provoking vertex info!
379 */
380 setup->coef[slot].a0[i] = setup->vprovoke->data[slot][i];
381 }
382
383
384 /**
385 * Compute a0, dadx and dady for a linearly interpolated coefficient,
386 * for a triangle.
387 */
388 static void tri_linear_coeff( struct setup_stage *setup,
389 unsigned slot,
390 unsigned i)
391 {
392 float botda = setup->vmid->data[slot][i] - setup->vmin->data[slot][i];
393 float majda = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
394 float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
395 float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
396
397 assert(slot < FRAG_ATTRIB_MAX);
398 assert(i <= 3);
399
400 setup->coef[slot].dadx[i] = a * setup->oneoverarea;
401 setup->coef[slot].dady[i] = b * setup->oneoverarea;
402
403 /* calculate a0 as the value which would be sampled for the
404 * fragment at (0,0), taking into account that we want to sample at
405 * pixel centers, in other words (0.5, 0.5).
406 *
407 * this is neat but unfortunately not a good way to do things for
408 * triangles with very large values of dadx or dady as it will
409 * result in the subtraction and re-addition from a0 of a very
410 * large number, which means we'll end up loosing a lot of the
411 * fractional bits and precision from a0. the way to fix this is
412 * to define a0 as the sample at a pixel center somewhere near vmin
413 * instead - i'll switch to this later.
414 */
415 setup->coef[slot].a0[i] = (setup->vmin->data[slot][i] -
416 (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5f) +
417 setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5f)));
418
419 /*
420 _mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n",
421 slot, "xyzw"[i],
422 setup->coef[slot].a0[i],
423 setup->coef[slot].dadx[i],
424 setup->coef[slot].dady[i]);
425 */
426 }
427
428
429 /**
430 * Compute a0, dadx and dady for a perspective-corrected interpolant,
431 * for a triangle.
432 */
433 static void tri_persp_coeff( struct setup_stage *setup,
434 unsigned slot,
435 unsigned i )
436 {
437 /* premultiply by 1/w:
438 */
439 float mina = setup->vmin->data[slot][i] * setup->vmin->data[0][3];
440 float mida = setup->vmid->data[slot][i] * setup->vmid->data[0][3];
441 float maxa = setup->vmax->data[slot][i] * setup->vmax->data[0][3];
442
443 float botda = mida - mina;
444 float majda = maxa - mina;
445 float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
446 float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
447
448 assert(slot < FRAG_ATTRIB_MAX);
449 assert(i <= 3);
450
451 setup->coef[slot].dadx[i] = a * setup->oneoverarea;
452 setup->coef[slot].dady[i] = b * setup->oneoverarea;
453 setup->coef[slot].a0[i] = (mina -
454 (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5f) +
455 setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5f)));
456 }
457
458
459 /**
460 * Compute the setup->coef[] array dadx, dady, a0 values.
461 * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
462 */
463 static void setup_tri_coefficients( struct setup_stage *setup )
464 {
465 const enum interp_mode *interp = setup->softpipe->interp;
466 unsigned slot, j;
467
468 /* z and w are done by linear interpolation:
469 */
470 tri_linear_coeff(setup, 0, 2);
471 tri_linear_coeff(setup, 0, 3);
472
473 /* setup interpolation for all the remaining attributes:
474 */
475 for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
476 switch (interp[slot]) {
477 case INTERP_CONSTANT:
478 for (j = 0; j < NUM_CHANNELS; j++)
479 const_coeff(setup, slot, j);
480 break;
481
482 case INTERP_LINEAR:
483 for (j = 0; j < NUM_CHANNELS; j++)
484 tri_linear_coeff(setup, slot, j);
485 break;
486
487 case INTERP_PERSPECTIVE:
488 for (j = 0; j < NUM_CHANNELS; j++)
489 tri_persp_coeff(setup, slot, j);
490 break;
491 }
492 }
493 }
494
495
496
497 static void setup_tri_edges( struct setup_stage *setup )
498 {
499 float vmin_x = setup->vmin->data[0][0] + 0.5f;
500 float vmid_x = setup->vmid->data[0][0] + 0.5f;
501
502 float vmin_y = setup->vmin->data[0][1] - 0.5f;
503 float vmid_y = setup->vmid->data[0][1] - 0.5f;
504 float vmax_y = setup->vmax->data[0][1] - 0.5f;
505
506 setup->emaj.sy = ceilf(vmin_y);
507 setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
508 setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
509 setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
510
511 setup->etop.sy = ceilf(vmid_y);
512 setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
513 setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
514 setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
515
516 setup->ebot.sy = ceilf(vmin_y);
517 setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
518 setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
519 setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
520 }
521
522
523 /**
524 * Render the upper or lower half of a triangle.
525 * Scissoring/cliprect is applied here too.
526 */
527 static void subtriangle( struct setup_stage *setup,
528 struct edge *eleft,
529 struct edge *eright,
530 unsigned lines )
531 {
532 const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
533 const int minx = (int) cliprect->minx;
534 const int maxx = (int) cliprect->maxx;
535 const int miny = (int) cliprect->miny;
536 const int maxy = (int) cliprect->maxy;
537 int y, start_y, finish_y;
538 int sy = (int)eleft->sy;
539
540 assert((int)eleft->sy == (int) eright->sy);
541
542 /* clip top/bottom */
543 start_y = sy;
544 finish_y = sy + lines;
545
546 if (start_y < miny)
547 start_y = miny;
548
549 if (finish_y > maxy)
550 finish_y = maxy;
551
552 start_y -= sy;
553 finish_y -= sy;
554
555 /*
556 _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
557 */
558
559 for (y = start_y; y < finish_y; y++) {
560
561 /* avoid accumulating adds as floats don't have the precision to
562 * accurately iterate large triangle edges that way. luckily we
563 * can just multiply these days.
564 *
565 * this is all drowned out by the attribute interpolation anyway.
566 */
567 int left = (int)(eleft->sx + y * eleft->dxdy);
568 int right = (int)(eright->sx + y * eright->dxdy);
569
570 /* clip left/right */
571 if (left < minx)
572 left = minx;
573 if (right > maxx)
574 right = maxx;
575
576 if (left < right) {
577 int _y = sy + y;
578 if (block(_y) != setup->span.y) {
579 flush_spans(setup);
580 setup->span.y = block(_y);
581 }
582
583 setup->span.left[_y&1] = left;setup->span.right[_y&1] = right;
584 setup->span.y_flags |= 1<<(_y&1);
585 }
586 }
587
588
589 /* save the values so that emaj can be restarted:
590 */
591 eleft->sx += lines * eleft->dxdy;
592 eright->sx += lines * eright->dxdy;
593 eleft->sy += lines;
594 eright->sy += lines;
595 }
596
597
598 /**
599 * Do setup for triangle rasterization, then render the triangle.
600 */
601 static void setup_tri( struct draw_stage *stage,
602 struct prim_header *prim )
603 {
604 struct setup_stage *setup = setup_stage( stage );
605
606 /*
607 _mesa_printf("%s\n", __FUNCTION__ );
608 */
609
610 setup_sort_vertices( setup, prim );
611 setup_tri_coefficients( setup );
612 setup_tri_edges( setup );
613
614 setup->quad.prim = PRIM_TRI;
615
616 setup->span.y = 0;
617 setup->span.y_flags = 0;
618 setup->span.right[0] = 0;
619 setup->span.right[1] = 0;
620 /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
621
622 /* init_constant_attribs( setup ); */
623
624 if (setup->oneoverarea < 0.0) {
625 /* emaj on left:
626 */
627 subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
628 subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
629 }
630 else {
631 /* emaj on right:
632 */
633 subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
634 subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
635 }
636
637 flush_spans( setup );
638 }
639
640
641
642 /**
643 * Compute a0, dadx and dady for a linearly interpolated coefficient,
644 * for a line.
645 */
646 static void
647 line_linear_coeff(struct setup_stage *setup, unsigned slot, unsigned i)
648 {
649 const float dz = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
650 const float dadx = dz * setup->emaj.dx * setup->oneoverarea;
651 const float dady = dz * setup->emaj.dy * setup->oneoverarea;
652 setup->coef[slot].dadx[i] = dadx;
653 setup->coef[slot].dady[i] = dady;
654 setup->coef[slot].a0[i]
655 = (setup->vmin->data[slot][i] -
656 (dadx * (setup->vmin->data[0][0] - 0.5f) +
657 dady * (setup->vmin->data[0][1] - 0.5f)));
658 }
659
660
661 /**
662 * Compute a0, dadx and dady for a perspective-corrected interpolant,
663 * for a line.
664 */
665 static void
666 line_persp_coeff(struct setup_stage *setup, unsigned slot, unsigned i)
667 {
668 /* XXX to do */
669 line_linear_coeff(setup, slot, i); /* XXX temporary */
670 }
671
672
673 /**
674 * Compute the setup->coef[] array dadx, dady, a0 values.
675 * Must be called after setup->vmin,vmax are initialized.
676 */
677 static INLINE void
678 setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)
679 {
680 const enum interp_mode *interp = setup->softpipe->interp;
681 unsigned slot, j;
682
683 /* use setup->vmin, vmax to point to vertices */
684 setup->vprovoke = prim->v[1];
685 setup->vmin = prim->v[0];
686 setup->vmax = prim->v[1];
687
688 setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
689 setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
690 /* NOTE: this is not really 1/area */
691 setup->oneoverarea = 1.0f / (setup->emaj.dx * setup->emaj.dx +
692 setup->emaj.dy * setup->emaj.dy);
693
694 /* z and w are done by linear interpolation:
695 */
696 line_linear_coeff(setup, 0, 2);
697 line_linear_coeff(setup, 0, 3);
698
699 /* setup interpolation for all the remaining attributes:
700 */
701 for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
702 switch (interp[slot]) {
703 case INTERP_CONSTANT:
704 for (j = 0; j < NUM_CHANNELS; j++)
705 const_coeff(setup, slot, j);
706 break;
707
708 case INTERP_LINEAR:
709 for (j = 0; j < NUM_CHANNELS; j++)
710 line_linear_coeff(setup, slot, j);
711 break;
712
713 case INTERP_PERSPECTIVE:
714 for (j = 0; j < NUM_CHANNELS; j++)
715 line_persp_coeff(setup, slot, j);
716 break;
717 }
718 }
719 }
720
721
722 /**
723 * Plot a pixel in a line segment.
724 */
725 static INLINE void
726 plot(struct setup_stage *setup, int x, int y)
727 {
728 const int iy = y & 1;
729 const int ix = x & 1;
730 const int quadX = x - ix;
731 const int quadY = y - iy;
732 const int mask = (1 << ix) << (2 * iy);
733
734 if (quadX != setup->quad.x0 ||
735 quadY != setup->quad.y0)
736 {
737 /* flush prev quad, start new quad */
738
739 if (setup->quad.x0 != -1)
740 clip_emit_quad(setup);
741
742 setup->quad.x0 = quadX;
743 setup->quad.y0 = quadY;
744 setup->quad.mask = 0x0;
745 }
746
747 setup->quad.mask |= mask;
748 }
749
750
751 /**
752 * Determine whether or not to emit a line fragment by checking
753 * line stipple pattern.
754 */
755 static INLINE unsigned
756 stipple_test(int counter, ushort pattern, int factor)
757 {
758 int b = (counter / factor) & 0xf;
759 return (1 << b) & pattern;
760 }
761
762
763 /**
764 * Do setup for line rasterization, then render the line.
765 * XXX single-pixel width, no stipple, etc
766 */
767 static void
768 setup_line(struct draw_stage *stage, struct prim_header *prim)
769 {
770 const struct vertex_header *v0 = prim->v[0];
771 const struct vertex_header *v1 = prim->v[1];
772 struct setup_stage *setup = setup_stage( stage );
773 struct softpipe_context *sp = setup->softpipe;
774
775 int x0 = (int) v0->data[0][0];
776 int x1 = (int) v1->data[0][0];
777 int y0 = (int) v0->data[0][1];
778 int y1 = (int) v1->data[0][1];
779 int dx = x1 - x0;
780 int dy = y1 - y0;
781 int xstep, ystep;
782
783 if (dx == 0 && dy == 0)
784 return;
785
786 setup_line_coefficients(setup, prim);
787
788 if (dx < 0) {
789 dx = -dx; /* make positive */
790 xstep = -1;
791 }
792 else {
793 xstep = 1;
794 }
795
796 if (dy < 0) {
797 dy = -dy; /* make positive */
798 ystep = -1;
799 }
800 else {
801 ystep = 1;
802 }
803
804 assert(dx >= 0);
805 assert(dy >= 0);
806
807 setup->quad.x0 = setup->quad.y0 = -1;
808 setup->quad.mask = 0x0;
809 setup->quad.prim = PRIM_LINE;
810 /* XXX temporary: set coverage to 1.0 so the line appears
811 * if AA mode happens to be enabled.
812 */
813 setup->quad.coverage[0] =
814 setup->quad.coverage[1] =
815 setup->quad.coverage[2] =
816 setup->quad.coverage[3] = 1.0;
817
818 if (dx > dy) {
819 /*** X-major line ***/
820 int i;
821 const int errorInc = dy + dy;
822 int error = errorInc - dx;
823 const int errorDec = error - dx;
824
825 for (i = 0; i < dx; i++) {
826 if (!sp->setup.line_stipple_enable ||
827 stipple_test(sp->line_stipple_counter,
828 sp->setup.line_stipple_pattern,
829 sp->setup.line_stipple_factor + 1)) {
830 plot(setup, x0, y0);
831 }
832
833 x0 += xstep;
834 if (error < 0) {
835 error += errorInc;
836 }
837 else {
838 error += errorDec;
839 y0 += ystep;
840 }
841
842 sp->line_stipple_counter++;
843 }
844 }
845 else {
846 /*** Y-major line ***/
847 int i;
848 const int errorInc = dx + dx;
849 int error = errorInc - dy;
850 const int errorDec = error - dy;
851
852 for (i = 0; i < dy; i++) {
853 if (!sp->setup.line_stipple_enable ||
854 stipple_test(sp->line_stipple_counter,
855 sp->setup.line_stipple_pattern,
856 sp->setup.line_stipple_factor + 1)) {
857 plot(setup, x0, y0);
858 }
859
860 y0 += ystep;
861
862 if (error < 0) {
863 error += errorInc;
864 }
865 else {
866 error += errorDec;
867 x0 += xstep;
868 }
869
870 sp->line_stipple_counter++;
871 }
872 }
873
874 /* draw final quad */
875 if (setup->quad.mask) {
876 clip_emit_quad(setup);
877 }
878 }
879
880
881 /**
882 * Do setup for point rasterization, then render the point.
883 * Round or square points...
884 * XXX could optimize a lot for 1-pixel points.
885 */
886 static void
887 setup_point(struct draw_stage *stage, struct prim_header *prim)
888 {
889 struct setup_stage *setup = setup_stage( stage );
890 /*XXX this should be a vertex attrib! */
891 const float halfSize = 0.5f * setup->softpipe->setup.point_size;
892 const boolean round = setup->softpipe->setup.point_smooth;
893 const struct vertex_header *v0 = prim->v[0];
894 const float x = v0->data[FRAG_ATTRIB_WPOS][0];
895 const float y = v0->data[FRAG_ATTRIB_WPOS][1];
896 unsigned slot, j;
897
898 /* For points, all interpolants are constant-valued.
899 * However, for point sprites, we'll need to setup texcoords appropriately.
900 * XXX: which coefficients are the texcoords???
901 * We may do point sprites as textured quads...
902 *
903 * KW: We don't know which coefficients are texcoords - ultimately
904 * the choice of what interpolation mode to use for each attribute
905 * should be determined by the fragment program, using
906 * per-attribute declaration statements that include interpolation
907 * mode as a parameter. So either the fragment program will have
908 * to be adjusted for pointsprite vs normal point behaviour, or
909 * otherwise a special interpolation mode will have to be defined
910 * which matches the required behaviour for point sprites. But -
911 * the latter is not a feature of normal hardware, and as such
912 * probably should be ruled out on that basis.
913 */
914 setup->vprovoke = prim->v[0];
915 const_coeff(setup, 0, 2);
916 const_coeff(setup, 0, 3);
917 for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
918 for (j = 0; j < NUM_CHANNELS; j++)
919 const_coeff(setup, slot, j);
920 }
921
922 setup->quad.prim = PRIM_POINT;
923
924 if (halfSize <= 0.5 && !round) {
925 /* special case for 1-pixel points */
926 const int ix = ((int) x) & 1;
927 const int iy = ((int) y) & 1;
928 setup->quad.x0 = (int) x - ix;
929 setup->quad.y0 = (int) y - iy;
930 setup->quad.mask = (1 << ix) << (2 * iy);
931 clip_emit_quad(setup);
932 }
933 else {
934 const int ixmin = block((int) (x - halfSize));
935 const int ixmax = block((int) (x + halfSize));
936 const int iymin = block((int) (y - halfSize));
937 const int iymax = block((int) (y + halfSize));
938 int ix, iy;
939
940 if (round) {
941 /* rounded points */
942 const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
943 const float rmax = halfSize + 0.7071F;
944 const float rmin2 = MAX2(0.0F, rmin * rmin);
945 const float rmax2 = rmax * rmax;
946 const float cscale = 1.0F / (rmax2 - rmin2);
947
948 for (iy = iymin; iy <= iymax; iy += 2) {
949 for (ix = ixmin; ix <= ixmax; ix += 2) {
950 float dx, dy, dist2, cover;
951
952 setup->quad.mask = 0x0;
953
954 dx = (ix + 0.5f) - x;
955 dy = (iy + 0.5f) - y;
956 dist2 = dx * dx + dy * dy;
957 if (dist2 <= rmax2) {
958 cover = 1.0F - (dist2 - rmin2) * cscale;
959 setup->quad.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
960 setup->quad.mask |= MASK_BOTTOM_LEFT;
961 }
962
963 dx = (ix + 1.5f) - x;
964 dy = (iy + 0.5f) - y;
965 dist2 = dx * dx + dy * dy;
966 if (dist2 <= rmax2) {
967 cover = 1.0F - (dist2 - rmin2) * cscale;
968 setup->quad.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
969 setup->quad.mask |= MASK_BOTTOM_RIGHT;
970 }
971
972 dx = (ix + 0.5f) - x;
973 dy = (iy + 1.5f) - y;
974 dist2 = dx * dx + dy * dy;
975 if (dist2 <= rmax2) {
976 cover = 1.0F - (dist2 - rmin2) * cscale;
977 setup->quad.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
978 setup->quad.mask |= MASK_TOP_LEFT;
979 }
980
981 dx = (ix + 1.5f) - x;
982 dy = (iy + 1.5f) - y;
983 dist2 = dx * dx + dy * dy;
984 if (dist2 <= rmax2) {
985 cover = 1.0F - (dist2 - rmin2) * cscale;
986 setup->quad.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
987 setup->quad.mask |= MASK_TOP_RIGHT;
988 }
989
990 if (setup->quad.mask) {
991 setup->quad.x0 = ix;
992 setup->quad.y0 = iy;
993 clip_emit_quad(setup);
994 }
995 }
996 }
997 }
998 else {
999 /* square points */
1000 for (iy = iymin; iy <= iymax; iy += 2) {
1001 for (ix = ixmin; ix <= ixmax; ix += 2) {
1002 setup->quad.mask = 0xf;
1003
1004 if (ix + 0.5 < x - halfSize) {
1005 /* fragment is past left edge of point, turn off left bits */
1006 setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
1007 }
1008
1009 if (ix + 1.5 > x + halfSize) {
1010 /* past the right edge */
1011 setup->quad.mask &= ~(MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
1012 }
1013
1014 if (iy + 0.5 < y - halfSize) {
1015 /* below the bottom edge */
1016 setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
1017 }
1018
1019 if (iy + 1.5 > y + halfSize) {
1020 /* above the top edge */
1021 setup->quad.mask &= ~(MASK_TOP_LEFT | MASK_TOP_RIGHT);
1022 }
1023
1024 if (setup->quad.mask) {
1025 setup->quad.x0 = ix;
1026 setup->quad.y0 = iy;
1027 clip_emit_quad(setup);
1028 }
1029 }
1030 }
1031 }
1032 }
1033 }
1034
1035
1036
1037 static void setup_begin( struct draw_stage *stage )
1038 {
1039 struct setup_stage *setup = setup_stage(stage);
1040 struct softpipe_context *sp = setup->softpipe;
1041
1042 setup->quad.nr_attrs = setup->softpipe->nr_frag_attrs;
1043
1044 sp->quad.first->begin(sp->quad.first);
1045 }
1046
1047
1048 static void setup_end( struct draw_stage *stage )
1049 {
1050 }
1051
1052
1053 static void reset_stipple_counter( struct draw_stage *stage )
1054 {
1055 struct setup_stage *setup = setup_stage(stage);
1056 setup->softpipe->line_stipple_counter = 0;
1057 }
1058
1059
1060 /**
1061 * Create a new primitive setup/render stage.
1062 */
1063 struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe )
1064 {
1065 struct setup_stage *setup = CALLOC_STRUCT(setup_stage);
1066
1067 setup->softpipe = softpipe;
1068 setup->stage.draw = softpipe->draw;
1069 setup->stage.begin = setup_begin;
1070 setup->stage.point = setup_point;
1071 setup->stage.line = setup_line;
1072 setup->stage.tri = setup_tri;
1073 setup->stage.end = setup_end;
1074 setup->stage.reset_stipple_counter = reset_stipple_counter;
1075
1076 setup->quad.coef = setup->coef;
1077
1078 return &setup->stage;
1079 }