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