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