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