OSDN Git Service

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