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