OSDN Git Service

57a96d57ce7b524e5ee8e73204bcd773de91d036
[android-x86/external-mesa.git] / src / gallium / drivers / llvmpipe / lp_setup_line.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  * Binning code for lines
30  */
31
32 #include "util/u_math.h"
33 #include "util/u_memory.h"
34 #include "lp_perf.h"
35 #include "lp_setup_context.h"
36 #include "lp_rast.h"
37 #include "lp_state_fs.h"
38 #include "lp_state_setup.h"
39
40 #define NUM_CHANNELS 4
41
42 struct lp_line_info {
43
44    float dx;
45    float dy;
46    float oneoverarea;
47
48    const float (*v1)[4];
49    const float (*v2)[4];
50
51    float (*a0)[4];
52    float (*dadx)[4];
53    float (*dady)[4];
54 };
55
56
57 /**
58  * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
59  */
60 static void constant_coef( struct lp_setup_context *setup,
61                            struct lp_line_info *info,
62                            unsigned slot,
63                            const float value,
64                            unsigned i )
65 {
66    info->a0[slot][i] = value;
67    info->dadx[slot][i] = 0.0f;
68    info->dady[slot][i] = 0.0f;
69 }
70
71
72 /**
73  * Compute a0, dadx and dady for a linearly interpolated coefficient,
74  * for a triangle.
75  */
76 static void linear_coef( struct lp_setup_context *setup,
77                          struct lp_line_info *info,
78                          unsigned slot,
79                          unsigned vert_attr,
80                          unsigned i)
81 {
82    float a1 = info->v1[vert_attr][i]; 
83    float a2 = info->v2[vert_attr][i];
84       
85    float da21 = a1 - a2;   
86    float dadx = da21 * info->dx * info->oneoverarea;
87    float dady = da21 * info->dy * info->oneoverarea;
88
89    info->dadx[slot][i] = dadx;
90    info->dady[slot][i] = dady;  
91    
92    info->a0[slot][i] = (a1 -
93                               (dadx * (info->v1[0][0] - setup->pixel_offset) +
94                                dady * (info->v1[0][1] - setup->pixel_offset)));
95 }
96
97
98 /**
99  * Compute a0, dadx and dady for a perspective-corrected interpolant,
100  * for a triangle.
101  * We basically multiply the vertex value by 1/w before computing
102  * the plane coefficients (a0, dadx, dady).
103  * Later, when we compute the value at a particular fragment position we'll
104  * divide the interpolated value by the interpolated W at that fragment.
105  */
106 static void perspective_coef( struct lp_setup_context *setup,
107                               struct lp_line_info *info,
108                               unsigned slot,
109                               unsigned vert_attr,
110                               unsigned i)
111 {
112    /* premultiply by 1/w  (v[0][3] is always 1/w):
113     */
114    float a1 = info->v1[vert_attr][i] * info->v1[0][3];
115    float a2 = info->v2[vert_attr][i] * info->v2[0][3];
116
117    float da21 = a1 - a2;   
118    float dadx = da21 * info->dx * info->oneoverarea;
119    float dady = da21 * info->dy * info->oneoverarea;
120
121    info->dadx[slot][i] = dadx;
122    info->dady[slot][i] = dady;
123    
124    info->a0[slot][i] = (a1 -
125                         (dadx * (info->v1[0][0] - setup->pixel_offset) +
126                          dady * (info->v1[0][1] - setup->pixel_offset)));
127 }
128
129 static void
130 setup_fragcoord_coef( struct lp_setup_context *setup,
131                       struct lp_line_info *info,
132                       unsigned slot,
133                       unsigned usage_mask)
134 {
135    /*X*/
136    if (usage_mask & TGSI_WRITEMASK_X) {
137       info->a0[slot][0] = 0.0;
138       info->dadx[slot][0] = 1.0;
139       info->dady[slot][0] = 0.0;
140    }
141
142    /*Y*/
143    if (usage_mask & TGSI_WRITEMASK_Y) {
144       info->a0[slot][1] = 0.0;
145       info->dadx[slot][1] = 0.0;
146       info->dady[slot][1] = 1.0;
147    }
148
149    /*Z*/
150    if (usage_mask & TGSI_WRITEMASK_Z) {
151       linear_coef(setup, info, slot, 0, 2);
152    }
153
154    /*W*/
155    if (usage_mask & TGSI_WRITEMASK_W) {
156       linear_coef(setup, info, slot, 0, 3);
157    }
158 }
159
160 /**
161  * Compute the tri->coef[] array dadx, dady, a0 values.
162  */
163 static void setup_line_coefficients( struct lp_setup_context *setup,
164                                      struct lp_line_info *info)
165 {
166    const struct lp_setup_variant_key *key = &setup->setup.variant->key;
167    unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
168    unsigned slot;
169
170    /* setup interpolation for all the remaining attributes:
171     */
172    for (slot = 0; slot < key->num_inputs; slot++) {
173       unsigned vert_attr = key->inputs[slot].src_index;
174       unsigned usage_mask = key->inputs[slot].usage_mask;
175       unsigned i;
176            
177       switch (key->inputs[slot].interp) {
178       case LP_INTERP_CONSTANT:
179          if (key->flatshade_first) {
180             for (i = 0; i < NUM_CHANNELS; i++)
181                if (usage_mask & (1 << i))
182                   constant_coef(setup, info, slot+1, info->v1[vert_attr][i], i);
183          }
184          else {
185             for (i = 0; i < NUM_CHANNELS; i++)
186                if (usage_mask & (1 << i))
187                   constant_coef(setup, info, slot+1, info->v2[vert_attr][i], i);
188          }
189          break;
190
191       case LP_INTERP_LINEAR:
192          for (i = 0; i < NUM_CHANNELS; i++)
193             if (usage_mask & (1 << i))
194                linear_coef(setup, info, slot+1, vert_attr, i);
195          break;
196
197       case LP_INTERP_PERSPECTIVE:
198          for (i = 0; i < NUM_CHANNELS; i++)
199             if (usage_mask & (1 << i))
200                perspective_coef(setup, info, slot+1, vert_attr, i);
201          fragcoord_usage_mask |= TGSI_WRITEMASK_W;
202          break;
203
204       case LP_INTERP_POSITION:
205          /*
206           * The generated pixel interpolators will pick up the coeffs from
207           * slot 0, so all need to ensure that the usage mask is covers all
208           * usages.
209           */
210          fragcoord_usage_mask |= usage_mask;
211          break;
212
213       case LP_INTERP_FACING:
214          for (i = 0; i < NUM_CHANNELS; i++)
215             if (usage_mask & (1 << i))
216                constant_coef(setup, info, slot+1, 1.0, i);
217          break;
218
219       default:
220          assert(0);
221       }
222    }
223
224    /* The internal position input is in slot zero:
225     */
226    setup_fragcoord_coef(setup, info, 0,
227                         fragcoord_usage_mask);
228 }
229
230
231
232 static INLINE int subpixel_snap( float a )
233 {
234    return util_iround(FIXED_ONE * a);
235 }
236
237
238 /**
239  * Print line vertex attribs (for debug).
240  */
241 static void
242 print_line(struct lp_setup_context *setup,
243            const float (*v1)[4],
244            const float (*v2)[4])
245 {
246    const struct lp_setup_variant_key *key = &setup->setup.variant->key;
247    uint i;
248
249    debug_printf("llvmpipe line\n");
250    for (i = 0; i < 1 + key->num_inputs; i++) {
251       debug_printf("  v1[%d]:  %f %f %f %f\n", i,
252                    v1[i][0], v1[i][1], v1[i][2], v1[i][3]);
253    }
254    for (i = 0; i < 1 + key->num_inputs; i++) {
255       debug_printf("  v2[%d]:  %f %f %f %f\n", i,
256                    v2[i][0], v2[i][1], v2[i][2], v2[i][3]);
257    }
258 }
259
260
261 static INLINE boolean sign(float x){
262    return x >= 0;  
263 }  
264
265
266 /* Used on positive floats only:
267  */
268 static INLINE float fracf(float f)
269 {
270    return f - floorf(f);
271 }
272
273
274
275 static boolean
276 try_setup_line( struct lp_setup_context *setup,
277                const float (*v1)[4],
278                const float (*v2)[4])
279 {
280    struct lp_scene *scene = setup->scene;
281    const struct lp_setup_variant_key *key = &setup->setup.variant->key;
282    struct lp_rast_triangle *line;
283    struct lp_rast_plane *plane;
284    struct lp_line_info info;
285    float width = MAX2(1.0, setup->line_width);
286    struct u_rect bbox;
287    unsigned tri_bytes;
288    int x[4]; 
289    int y[4];
290    int i;
291    int nr_planes = 4;
292    unsigned scissor_index = 0;
293    
294    /* linewidth should be interpreted as integer */
295    int fixed_width = util_iround(width) * FIXED_ONE;
296
297    float x_offset=0;
298    float y_offset=0;
299    float x_offset_end=0;
300    float y_offset_end=0;
301       
302    float x1diff;
303    float y1diff;
304    float x2diff;
305    float y2diff;
306    float dx, dy;
307    float area;
308
309    boolean draw_start;
310    boolean draw_end;
311    boolean will_draw_start;
312    boolean will_draw_end;
313
314    if (0)
315       print_line(setup, v1, v2);
316
317    if (setup->scissor_test) {
318       nr_planes = 8;
319       if (setup->viewport_index_slot > 0) {
320          unsigned *udata = (unsigned*)v1[setup->viewport_index_slot];
321          scissor_index = lp_clamp_scissor_idx(*udata);
322       }
323    }
324    else {
325       nr_planes = 4;
326    }
327
328
329    dx = v1[0][0] - v2[0][0];
330    dy = v1[0][1] - v2[0][1];
331    area = (dx * dx  + dy * dy);
332    if (area == 0) {
333       LP_COUNT(nr_culled_tris);
334       return TRUE;
335    }
336
337    info.oneoverarea = 1.0f / area;
338    info.dx = dx;
339    info.dy = dy;
340    info.v1 = v1;
341    info.v2 = v2;
342
343   
344    /* X-MAJOR LINE */
345    if (fabsf(dx) >= fabsf(dy)) {
346       float dydx = dy / dx;
347
348       x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5;
349       y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5;
350       x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5;
351       y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5;
352
353       if (y2diff==-0.5 && dy<0){
354          y2diff = 0.5;
355       }
356       
357       /* 
358        * Diamond exit rule test for starting point 
359        */    
360       if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
361          draw_start = TRUE;
362       }
363       else if (sign(x1diff) == sign(-dx)) {
364          draw_start = FALSE;
365       }
366       else if (sign(-y1diff) != sign(dy)) {
367          draw_start = TRUE;
368       }
369       else {
370          /* do intersection test */
371          float yintersect = fracf(v1[0][1]) + x1diff * dydx;
372          draw_start = (yintersect < 1.0 && yintersect > 0.0);
373       }
374
375
376       /* 
377        * Diamond exit rule test for ending point 
378        */    
379       if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
380          draw_end = FALSE;
381       }
382       else if (sign(x2diff) != sign(-dx)) {
383          draw_end = FALSE;
384       }
385       else if (sign(-y2diff) == sign(dy)) {
386          draw_end = TRUE;
387       }
388       else {
389          /* do intersection test */
390          float yintersect = fracf(v2[0][1]) + x2diff * dydx;
391          draw_end = (yintersect < 1.0 && yintersect > 0.0);
392       }
393
394       /* Are we already drawing start/end?
395        */
396       will_draw_start = sign(-x1diff) != sign(dx);
397       will_draw_end = (sign(x2diff) == sign(-dx)) || x2diff==0;
398
399       if (dx < 0) {
400          /* if v2 is to the right of v1, swap pointers */
401          const float (*temp)[4] = v1;
402          v1 = v2;
403          v2 = temp;
404          dx = -dx;
405          dy = -dy;
406          /* Otherwise shift planes appropriately */
407          if (will_draw_start != draw_start) {
408             x_offset_end = - x1diff - 0.5;
409             y_offset_end = x_offset_end * dydx;
410
411          }
412          if (will_draw_end != draw_end) {
413             x_offset = - x2diff - 0.5;
414             y_offset = x_offset * dydx;
415          }
416
417       }
418       else{
419          /* Otherwise shift planes appropriately */
420          if (will_draw_start != draw_start) {
421             x_offset = - x1diff + 0.5;
422             y_offset = x_offset * dydx;
423          }
424          if (will_draw_end != draw_end) {
425             x_offset_end = - x2diff + 0.5;
426             y_offset_end = x_offset_end * dydx;
427          }
428       }
429   
430       /* x/y positions in fixed point */
431       x[0] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset);
432       x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset);
433       x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset);
434       x[3] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset);
435       
436       y[0] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset) - fixed_width/2;
437       y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) - fixed_width/2;
438       y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) + fixed_width/2;
439       y[3] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset) + fixed_width/2;
440       
441    }
442    else {
443       const float dxdy = dx / dy;
444
445       /* Y-MAJOR LINE */      
446       x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5;
447       y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5;
448       x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5;
449       y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5;
450
451       if (x2diff==-0.5 && dx<0) {
452          x2diff = 0.5;
453       }
454
455       /* 
456        * Diamond exit rule test for starting point 
457        */    
458       if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
459          draw_start = TRUE;
460       }
461       else if (sign(-y1diff) == sign(dy)) {
462          draw_start = FALSE;
463       }
464       else if (sign(x1diff) != sign(-dx)) {
465          draw_start = TRUE;
466       }
467       else {
468          /* do intersection test */
469          float xintersect = fracf(v1[0][0]) + y1diff * dxdy;
470          draw_start = (xintersect < 1.0 && xintersect > 0.0);
471       }
472
473       /* 
474        * Diamond exit rule test for ending point 
475        */    
476       if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
477          draw_end = FALSE;
478       }
479       else if (sign(-y2diff) != sign(dy) ) {
480          draw_end = FALSE;
481       }
482       else if (sign(x2diff) == sign(-dx) ) {
483          draw_end = TRUE;
484       }
485       else {
486          /* do intersection test */
487          float xintersect = fracf(v2[0][0]) + y2diff * dxdy;
488          draw_end = (xintersect < 1.0 && xintersect >= 0.0);
489       }
490
491       /* Are we already drawing start/end?
492        */
493       will_draw_start = sign(y1diff) == sign(dy);
494       will_draw_end = (sign(-y2diff) == sign(dy)) || y2diff==0;
495
496       if (dy > 0) {
497          /* if v2 is on top of v1, swap pointers */
498          const float (*temp)[4] = v1;
499          v1 = v2;
500          v2 = temp; 
501          dx = -dx;
502          dy = -dy;
503
504          /* Otherwise shift planes appropriately */
505          if (will_draw_start != draw_start) {
506             y_offset_end = - y1diff + 0.5;
507             x_offset_end = y_offset_end * dxdy;
508          }
509          if (will_draw_end != draw_end) {
510             y_offset = - y2diff + 0.5;
511             x_offset = y_offset * dxdy;
512          }
513       }
514       else {
515          /* Otherwise shift planes appropriately */
516          if (will_draw_start != draw_start) {
517             y_offset = - y1diff - 0.5;
518             x_offset = y_offset * dxdy;
519                      
520          }
521          if (will_draw_end != draw_end) {
522             y_offset_end = - y2diff - 0.5;
523             x_offset_end = y_offset_end * dxdy;
524          }
525       }
526
527       /* x/y positions in fixed point */
528       x[0] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset) - fixed_width/2;
529       x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) - fixed_width/2;
530       x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) + fixed_width/2;
531       x[3] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset) + fixed_width/2;
532      
533       y[0] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset); 
534       y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset);
535       y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset);
536       y[3] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset);
537    }
538
539
540
541    LP_COUNT(nr_tris);
542
543  
544    /* Bounding rectangle (in pixels) */
545    {
546       /* Yes this is necessary to accurately calculate bounding boxes
547        * with the two fill-conventions we support.  GL (normally) ends
548        * up needing a bottom-left fill convention, which requires
549        * slightly different rounding.
550        */
551       int adj = (setup->pixel_offset != 0) ? 1 : 0;
552
553       bbox.x0 = (MIN4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
554       bbox.x1 = (MAX4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
555       bbox.y0 = (MIN4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
556       bbox.y1 = (MAX4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
557
558       /* Inclusive coordinates:
559        */
560       bbox.x1--;
561       bbox.y1--;
562    }
563
564    if (bbox.x1 < bbox.x0 ||
565        bbox.y1 < bbox.y0) {
566       if (0) debug_printf("empty bounding box\n");
567       LP_COUNT(nr_culled_tris);
568       return TRUE;
569    }
570
571    if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
572       if (0) debug_printf("offscreen\n");
573       LP_COUNT(nr_culled_tris);
574       return TRUE;
575    }
576
577    /* Can safely discard negative regions:
578     */
579    bbox.x0 = MAX2(bbox.x0, 0);
580    bbox.y0 = MAX2(bbox.y0, 0);
581
582    line = lp_setup_alloc_triangle(scene,
583                                   key->num_inputs,
584                                   nr_planes,
585                                   &tri_bytes);
586    if (!line)
587       return FALSE;
588
589 #ifdef DEBUG
590    line->v[0][0] = v1[0][0];
591    line->v[1][0] = v2[0][0];   
592    line->v[0][1] = v1[0][1];
593    line->v[1][1] = v2[0][1];
594 #endif
595
596    /* calculate the deltas */
597    plane = GET_PLANES(line);
598    plane[0].dcdy = x[0] - x[1];
599    plane[1].dcdy = x[1] - x[2];
600    plane[2].dcdy = x[2] - x[3];
601    plane[3].dcdy = x[3] - x[0];
602
603    plane[0].dcdx = y[0] - y[1];
604    plane[1].dcdx = y[1] - y[2];
605    plane[2].dcdx = y[2] - y[3];
606    plane[3].dcdx = y[3] - y[0];
607
608
609    /* Setup parameter interpolants:
610     */
611    info.a0 = GET_A0(&line->inputs);
612    info.dadx = GET_DADX(&line->inputs);
613    info.dady = GET_DADY(&line->inputs);
614    setup_line_coefficients(setup, &info); 
615
616    line->inputs.frontfacing = TRUE;
617    line->inputs.disable = FALSE;
618    line->inputs.opaque = FALSE;
619
620    for (i = 0; i < 4; i++) {
621
622       /* half-edge constants, will be interated over the whole render
623        * target.
624        */
625       plane[i].c = plane[i].dcdx * x[i] - plane[i].dcdy * y[i];
626
627       
628       /* correct for top-left vs. bottom-left fill convention.  
629        */         
630       if (plane[i].dcdx < 0) {
631          /* both fill conventions want this - adjust for left edges */
632          plane[i].c++;            
633       }
634       else if (plane[i].dcdx == 0) {
635          if (setup->pixel_offset == 0) {
636             /* correct for top-left fill convention:
637              */
638             if (plane[i].dcdy > 0) plane[i].c++;
639          }
640          else {
641             /* correct for bottom-left fill convention:
642              */
643             if (plane[i].dcdy < 0) plane[i].c++;
644          }
645       }
646
647       plane[i].dcdx *= FIXED_ONE;
648       plane[i].dcdy *= FIXED_ONE;
649
650       /* find trivial reject offsets for each edge for a single-pixel
651        * sized block.  These will be scaled up at each recursive level to
652        * match the active blocksize.  Scaling in this way works best if
653        * the blocks are square.
654        */
655       plane[i].eo = 0;
656       if (plane[i].dcdx < 0) plane[i].eo -= plane[i].dcdx;
657       if (plane[i].dcdy > 0) plane[i].eo += plane[i].dcdy;
658    }
659
660
661    /* 
662     * When rasterizing scissored tris, use the intersection of the
663     * triangle bounding box and the scissor rect to generate the
664     * scissor planes.
665     *
666     * This permits us to cut off the triangle "tails" that are present
667     * in the intermediate recursive levels caused when two of the
668     * triangles edges don't diverge quickly enough to trivially reject
669     * exterior blocks from the triangle.
670     *
671     * It's not really clear if it's worth worrying about these tails,
672     * but since we generate the planes for each scissored tri, it's
673     * free to trim them in this case.
674     * 
675     * Note that otherwise, the scissor planes only vary in 'C' value,
676     * and even then only on state-changes.  Could alternatively store
677     * these planes elsewhere.
678     */
679    if (nr_planes == 8) {
680       const struct u_rect *scissor =
681          &setup->scissors[scissor_index];
682
683       plane[4].dcdx = -1;
684       plane[4].dcdy = 0;
685       plane[4].c = 1-scissor->x0;
686       plane[4].eo = 1;
687
688       plane[5].dcdx = 1;
689       plane[5].dcdy = 0;
690       plane[5].c = scissor->x1+1;
691       plane[5].eo = 0;
692
693       plane[6].dcdx = 0;
694       plane[6].dcdy = 1;
695       plane[6].c = 1-scissor->y0;
696       plane[6].eo = 1;
697
698       plane[7].dcdx = 0;
699       plane[7].dcdy = -1;
700       plane[7].c = scissor->y1+1;
701       plane[7].eo = 0;
702    }
703
704    return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, scissor_index);
705 }
706
707
708 static void lp_setup_line( struct lp_setup_context *setup,
709                            const float (*v0)[4],
710                            const float (*v1)[4] )
711 {
712    if (!try_setup_line( setup, v0, v1 ))
713    {
714       if (!lp_setup_flush_and_restart(setup))
715          return;
716
717       if (!try_setup_line( setup, v0, v1 ))
718          return;
719    }
720 }
721
722
723 void lp_setup_choose_line( struct lp_setup_context *setup ) 
724
725    setup->line = lp_setup_line;
726 }
727
728