1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
29 * Binning code for lines
32 #include "util/u_math.h"
33 #include "util/u_memory.h"
35 #include "lp_setup_context.h"
37 #include "lp_state_fs.h"
39 #define NUM_CHANNELS 4
42 static const int step_scissor_minx
[16] = {
49 static const int step_scissor_maxx
[16] = {
56 static const int step_scissor_miny
[16] = {
63 static const int step_scissor_maxy
[16] = {
73 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
75 static void constant_coef( struct lp_setup_context
*setup
,
76 struct lp_rast_triangle
*tri
,
81 tri
->inputs
.a0
[slot
][i
] = value
;
82 tri
->inputs
.dadx
[slot
][i
] = 0.0f
;
83 tri
->inputs
.dady
[slot
][i
] = 0.0f
;
88 * Compute a0, dadx and dady for a linearly interpolated coefficient,
91 static void linear_coef( struct lp_setup_context
*setup
,
92 struct lp_rast_triangle
*tri
,
100 float a1
= v1
[vert_attr
][i
];
101 float a2
= v2
[vert_attr
][i
];
103 float da21
= a1
- a2
;
104 float dadx
= da21
* tri
->dx
* oneoverarea
;
105 float dady
= da21
* tri
->dy
* oneoverarea
;
107 tri
->inputs
.dadx
[slot
][i
] = dadx
;
108 tri
->inputs
.dady
[slot
][i
] = dady
;
110 tri
->inputs
.a0
[slot
][i
] = (a1
-
111 (dadx
* (v1
[0][0] - setup
->pixel_offset
) +
112 dady
* (v1
[0][1] - setup
->pixel_offset
)));
117 * Compute a0, dadx and dady for a perspective-corrected interpolant,
119 * We basically multiply the vertex value by 1/w before computing
120 * the plane coefficients (a0, dadx, dady).
121 * Later, when we compute the value at a particular fragment position we'll
122 * divide the interpolated value by the interpolated W at that fragment.
124 static void perspective_coef( struct lp_setup_context
*setup
,
125 struct lp_rast_triangle
*tri
,
128 const float (*v1
)[4],
129 const float (*v2
)[4],
133 /* premultiply by 1/w (v[0][3] is always 1/w):
135 float a1
= v1
[vert_attr
][i
] * v1
[0][3];
136 float a2
= v2
[vert_attr
][i
] * v2
[0][3];
138 float da21
= a1
- a2
;
139 float dadx
= da21
* tri
->dx
* oneoverarea
;
140 float dady
= da21
* tri
->dy
* oneoverarea
;
142 tri
->inputs
.dadx
[slot
][i
] = dadx
;
143 tri
->inputs
.dady
[slot
][i
] = dady
;
145 tri
->inputs
.a0
[slot
][i
] = (a1
-
146 (dadx
* (v1
[0][0] - setup
->pixel_offset
) +
147 dady
* (v1
[0][1] - setup
->pixel_offset
)));
151 * Compute the tri->coef[] array dadx, dady, a0 values.
153 static void setup_line_coefficients( struct lp_setup_context
*setup
,
154 struct lp_rast_triangle
*tri
,
156 const float (*v1
)[4],
157 const float (*v2
)[4])
159 unsigned fragcoord_usage_mask
= TGSI_WRITEMASK_XYZ
;
162 /* setup interpolation for all the remaining attributes:
164 for (slot
= 0; slot
< setup
->fs
.nr_inputs
; slot
++) {
165 unsigned vert_attr
= setup
->fs
.input
[slot
].src_index
;
166 unsigned usage_mask
= setup
->fs
.input
[slot
].usage_mask
;
169 switch (setup
->fs
.input
[slot
].interp
) {
170 case LP_INTERP_CONSTANT
:
171 if (setup
->flatshade_first
) {
172 for (i
= 0; i
< NUM_CHANNELS
; i
++)
173 if (usage_mask
& (1 << i
))
174 constant_coef(setup
, tri
, slot
+1, v1
[vert_attr
][i
], i
);
177 for (i
= 0; i
< NUM_CHANNELS
; i
++)
178 if (usage_mask
& (1 << i
))
179 constant_coef(setup
, tri
, slot
+1, v2
[vert_attr
][i
], i
);
183 case LP_INTERP_LINEAR
:
184 for (i
= 0; i
< NUM_CHANNELS
; i
++)
185 if (usage_mask
& (1 << i
))
186 linear_coef(setup
, tri
, oneoverarea
, slot
+1, v1
, v2
, vert_attr
, i
);
189 case LP_INTERP_PERSPECTIVE
:
190 for (i
= 0; i
< NUM_CHANNELS
; i
++)
191 if (usage_mask
& (1 << i
))
192 perspective_coef(setup
, tri
, oneoverarea
, slot
+1, v1
, v2
, vert_attr
, i
);
193 fragcoord_usage_mask
|= TGSI_WRITEMASK_W
;
196 case LP_INTERP_POSITION
:
198 * The generated pixel interpolators will pick up the coeffs from
199 * slot 0, so all need to ensure that the usage mask is covers all
202 fragcoord_usage_mask
|= usage_mask
;
210 /* The internal position input is in slot zero:
212 lp_setup_fragcoord_coef(setup
, tri
, oneoverarea
, 0, v1
, v2
, v2
,
213 fragcoord_usage_mask
);
218 static INLINE
int subpixel_snap( float a
)
220 return util_iround(FIXED_ONE
* a
);
225 * Print line vertex attribs (for debug).
228 print_line(struct lp_setup_context
*setup
,
229 const float (*v1
)[4],
230 const float (*v2
)[4])
234 debug_printf("llvmpipe line\n");
235 for (i
= 0; i
< 1 + setup
->fs
.nr_inputs
; i
++) {
236 debug_printf(" v1[%d]: %f %f %f %f\n", i
,
237 v1
[i
][0], v1
[i
][1], v1
[i
][2], v1
[i
][3]);
239 for (i
= 0; i
< 1 + setup
->fs
.nr_inputs
; i
++) {
240 debug_printf(" v2[%d]: %f %f %f %f\n", i
,
241 v2
[i
][0], v2
[i
][1], v2
[i
][2], v2
[i
][3]);
246 static INLINE boolean
sign(float x
){
252 lp_setup_line( struct lp_setup_context
*setup
,
253 const float (*v1
)[4],
254 const float (*v2
)[4])
256 struct lp_scene
*scene
= lp_setup_get_current_scene(setup
);
257 struct lp_rast_triangle
*line
;
259 float width
= MAX2(1.0, setup
->line_width
);
260 int minx
, maxx
, miny
, maxy
;
261 int ix0
, ix1
, iy0
, iy1
;
269 /* linewidth should be interpreted as integer */
270 int fixed_width
= subpixel_snap(round(width
));
272 float xdiamond_offset
=0;
273 float ydiamond_offset
=0;
274 float xdiamond_offset_end
=0;
275 float ydiamond_offset_end
=0;
284 boolean will_draw_start
;
285 boolean will_draw_end
;
288 print_line(setup
, v1
, v2
);
290 if (setup
->scissor_test
) {
297 line
= lp_setup_alloc_triangle(scene
,
305 line
->v
[0][0] = v1
[0][0];
306 line
->v
[1][0] = v2
[0][0];
307 line
->v
[0][1] = v1
[0][1];
308 line
->v
[1][1] = v2
[0][1];
311 line
->dx
= v1
[0][0] - v2
[0][0];
312 line
->dy
= v1
[0][1] - v2
[0][1];
315 if (fabsf(line
->dx
) >= fabsf(line
->dy
)) {
317 x1diff
= v1
[0][0] - (float) floor(v1
[0][0]) - 0.5;
318 y1diff
= v1
[0][1] - (float) floor(v1
[0][1]) - 0.5;
319 x2diff
= v2
[0][0] - (float) floor(v2
[0][0]) - 0.5;
320 y2diff
= v2
[0][1] - (float) floor(v2
[0][1]) - 0.5;
322 if (y2diff
==-0.5 && line
->dy
<0){
327 * Diamond exit rule test for starting point
329 if (fabsf(x1diff
) + fabsf(y1diff
) < 0.5) {
332 else if (sign(x1diff
) == sign(-line
->dx
)) {
335 else if (sign(-y1diff
) != sign(line
->dy
)) {
339 /* do intersection test */
340 float yintersect
= v1
[0][1] + x1diff
*((float)line
->dy
/(float)line
->dx
);
341 if (yintersect
< ceil(v1
[0][1]) && yintersect
> floor(v1
[0][1])){
344 else draw_start
= FALSE
;
349 * Diamond exit rule test for ending point
351 if (fabsf(x2diff
) + fabsf(y2diff
) < 0.5) {
354 else if (sign(x2diff
) != sign(-line
->dx
)) {
357 else if (sign(-y2diff
) == sign(line
->dy
)) {
361 /* do intersection test */
362 float yintersect
= v2
[0][1] + x2diff
*((float)line
->dy
/(float)line
->dx
);
363 if (yintersect
< ceil(v2
[0][1]) && yintersect
> floor(v2
[0][1])){
366 else draw_end
= FALSE
;
369 /* Are we already drawing start/end?
371 will_draw_start
= sign(-x1diff
) != sign(line
->dx
);
372 will_draw_end
= (sign(x2diff
) == sign(-line
->dx
)) || x2diff
==0;
375 /* if v2 is to the right of v1, swap pointers */
376 const float (*temp
)[4] = v1
;
379 line
->dx
= -line
->dx
;
380 line
->dy
= -line
->dy
;
381 /* Otherwise shift planes appropriately */
382 if (will_draw_start
!= draw_start
) {
383 xdiamond_offset_end
= - x1diff
- 0.5;
384 ydiamond_offset_end
= xdiamond_offset_end
*(float)line
->dy
/(float)line
->dx
;
387 if (will_draw_end
!= draw_end
) {
388 xdiamond_offset
= - x2diff
- 0.5;
389 ydiamond_offset
= xdiamond_offset
*(float)line
->dy
/(float)line
->dx
;
394 /* Otherwise shift planes appropriately */
395 if (will_draw_start
!= draw_start
) {
396 xdiamond_offset
= - x1diff
+ 0.5;
397 ydiamond_offset
= xdiamond_offset
*(float)line
->dy
/(float)line
->dx
;
399 if (will_draw_end
!= draw_end
) {
400 xdiamond_offset_end
= - x2diff
+ 0.5;
401 ydiamond_offset_end
= xdiamond_offset_end
*(float)line
->dy
/(float)line
->dx
;
405 /* x/y positions in fixed point */
406 x
[0] = subpixel_snap(v1
[0][0] + xdiamond_offset
- setup
->pixel_offset
);
407 x
[1] = subpixel_snap(v2
[0][0] + xdiamond_offset_end
- setup
->pixel_offset
);
408 x
[2] = subpixel_snap(v2
[0][0] + xdiamond_offset_end
- setup
->pixel_offset
);
409 x
[3] = subpixel_snap(v1
[0][0] + xdiamond_offset
- setup
->pixel_offset
);
411 y
[0] = subpixel_snap(v1
[0][1] + ydiamond_offset
- setup
->pixel_offset
) - fixed_width
/2;
412 y
[1] = subpixel_snap(v2
[0][1] + ydiamond_offset_end
- setup
->pixel_offset
) - fixed_width
/2;
413 y
[2] = subpixel_snap(v2
[0][1] + ydiamond_offset_end
- setup
->pixel_offset
) + fixed_width
/2;
414 y
[3] = subpixel_snap(v1
[0][1] + ydiamond_offset
- setup
->pixel_offset
) + fixed_width
/2;
421 x1diff
= v1
[0][0] - (float) floor(v1
[0][0]) - 0.5;
422 y1diff
= v1
[0][1] - (float) floor(v1
[0][1]) - 0.5;
423 x2diff
= v2
[0][0] - (float) floor(v2
[0][0]) - 0.5;
424 y2diff
= v2
[0][1] - (float) floor(v2
[0][1]) - 0.5;
426 if (x2diff
==-0.5 && line
->dx
<0){
431 * Diamond exit rule test for starting point
433 if (fabsf(x1diff
) + fabsf(y1diff
) < 0.5) {
436 else if (sign(-y1diff
) == sign(line
->dy
)) {
439 else if (sign(x1diff
) != sign(-line
->dx
)) {
443 /* do intersection test */
444 float xintersect
= v1
[0][0] + y1diff
*((float)line
->dx
/(float)line
->dy
);
445 if (xintersect
< ceil(v1
[0][0]) && xintersect
> floor(v1
[0][0])){
448 else draw_start
= FALSE
;
452 * Diamond exit rule test for ending point
454 if (fabsf(x2diff
) + fabsf(y2diff
) < 0.5) {
457 else if (sign(-y2diff
) != sign(line
->dy
) ) {
460 else if (sign(x2diff
) == sign(-line
->dx
) ) {
464 /* do intersection test */
465 float xintersect
= v2
[0][0] + y2diff
*((float)line
->dx
/(float)line
->dy
);
466 if (xintersect
< ceil(v2
[0][0]) && xintersect
> floor(v2
[0][0])){
469 else draw_end
= FALSE
;
472 /* Are we already drawing start/end?
474 will_draw_start
= sign(y1diff
) == sign(line
->dy
);
475 will_draw_end
= (sign(-y2diff
) == sign(line
->dy
)) || y2diff
==0;
478 /* if v2 is on top of v1, swap pointers */
479 const float (*temp
)[4] = v1
;
482 line
->dx
= -line
->dx
;
483 line
->dy
= -line
->dy
;
485 /* Otherwise shift planes appropriately */
486 if (will_draw_start
!= draw_start
) {
487 ydiamond_offset_end
= - y1diff
+ 0.5;
488 xdiamond_offset_end
= ydiamond_offset_end
*(float)line
->dx
/(float)line
->dy
;
490 if (will_draw_end
!= draw_end
) {
491 ydiamond_offset
= - y2diff
+ 0.5;
492 xdiamond_offset
= ydiamond_offset
*(float)line
->dx
/(float)line
->dy
;
497 /* Otherwise shift planes appropriately */
498 if (will_draw_start
!= draw_start
) {
499 ydiamond_offset
= - y1diff
- 0.5;
500 xdiamond_offset
= ydiamond_offset
*(float)line
->dx
/(float)line
->dy
;
503 if (will_draw_end
!= draw_end
) {
504 ydiamond_offset_end
= - y2diff
- 0.5;
505 xdiamond_offset_end
= ydiamond_offset_end
*(float)line
->dx
/(float)line
->dy
;
509 /* x/y positions in fixed point */
510 x
[0] = subpixel_snap(v1
[0][0] + xdiamond_offset
- setup
->pixel_offset
) - fixed_width
/2;
511 x
[1] = subpixel_snap(v2
[0][0] + xdiamond_offset_end
- setup
->pixel_offset
) - fixed_width
/2;
512 x
[2] = subpixel_snap(v2
[0][0] + xdiamond_offset_end
- setup
->pixel_offset
) + fixed_width
/2;
513 x
[3] = subpixel_snap(v1
[0][0] + xdiamond_offset
- setup
->pixel_offset
) + fixed_width
/2;
515 y
[0] = subpixel_snap(v1
[0][1] + ydiamond_offset
- setup
->pixel_offset
);
516 y
[1] = subpixel_snap(v2
[0][1] + ydiamond_offset_end
- setup
->pixel_offset
);
517 y
[2] = subpixel_snap(v2
[0][1] + ydiamond_offset_end
- setup
->pixel_offset
);
518 y
[3] = subpixel_snap(v1
[0][1] + ydiamond_offset
- setup
->pixel_offset
);
522 /* calculate the deltas */
523 line
->plane
[0].dcdy
= x
[0] - x
[1];
524 line
->plane
[1].dcdy
= x
[1] - x
[2];
525 line
->plane
[2].dcdy
= x
[2] - x
[3];
526 line
->plane
[3].dcdy
= x
[3] - x
[0];
528 line
->plane
[0].dcdx
= y
[0] - y
[1];
529 line
->plane
[1].dcdx
= y
[1] - y
[2];
530 line
->plane
[2].dcdx
= y
[2] - y
[3];
531 line
->plane
[3].dcdx
= y
[3] - y
[0];
537 /* Bounding rectangle (in pixels) */
539 /* Yes this is necessary to accurately calculate bounding boxes
540 * with the two fill-conventions we support. GL (normally) ends
541 * up needing a bottom-left fill convention, which requires
542 * slightly different rounding.
544 int adj
= (setup
->pixel_offset
!= 0) ? 1 : 0;
546 minx
= (MIN4(x
[0], x
[1], x
[2], x
[3]) + (FIXED_ONE
-1)) >> FIXED_ORDER
;
547 maxx
= (MAX4(x
[0], x
[1], x
[2], x
[3]) + (FIXED_ONE
-1)) >> FIXED_ORDER
;
548 miny
= (MIN4(y
[0], y
[1], y
[2], y
[3]) + (FIXED_ONE
-1) + adj
) >> FIXED_ORDER
;
549 maxy
= (MAX4(y
[0], y
[1], y
[2], y
[3]) + (FIXED_ONE
-1) + adj
) >> FIXED_ORDER
;
552 if (setup
->scissor_test
) {
553 minx
= MAX2(minx
, setup
->scissor
.current
.minx
);
554 maxx
= MIN2(maxx
, setup
->scissor
.current
.maxx
);
555 miny
= MAX2(miny
, setup
->scissor
.current
.miny
);
556 maxy
= MIN2(maxy
, setup
->scissor
.current
.maxy
);
559 minx
= MAX2(minx
, 0);
560 miny
= MAX2(miny
, 0);
561 maxx
= MIN2(maxx
, scene
->fb
.width
);
562 maxy
= MIN2(maxy
, scene
->fb
.height
);
566 if (miny
>= maxy
|| minx
>= maxx
) {
567 lp_scene_putback_data( scene
, tri_bytes
);
571 oneoverarea
= 1.0f
/ (line
->dx
* line
->dx
+ line
->dy
* line
->dy
);
573 /* Setup parameter interpolants:
575 setup_line_coefficients( setup
, line
, oneoverarea
, v1
, v2
);
577 for (i
= 0; i
< 4; i
++) {
578 struct lp_rast_plane
*plane
= &line
->plane
[i
];
580 /* half-edge constants, will be interated over the whole render
583 plane
->c
= plane
->dcdx
* x
[i
] - plane
->dcdy
* y
[i
];
586 /* correct for top-left vs. bottom-left fill convention.
588 * note that we're overloading gl_rasterization_rules to mean
589 * both (0.5,0.5) pixel centers *and* bottom-left filling
592 * GL actually has a top-left filling convention, but GL's
593 * notion of "top" differs from gallium's...
595 * Also, sometimes (in FBO cases) GL will render upside down
596 * to its usual method, in which case it will probably want
597 * to use the opposite, top-left convention.
599 if (plane
->dcdx
< 0) {
600 /* both fill conventions want this - adjust for left edges */
603 else if (plane
->dcdx
== 0) {
604 if (setup
->pixel_offset
== 0) {
605 /* correct for top-left fill convention:
607 if (plane
->dcdy
> 0) plane
->c
++;
610 /* correct for bottom-left fill convention:
612 if (plane
->dcdy
< 0) plane
->c
++;
616 plane
->dcdx
*= FIXED_ONE
;
617 plane
->dcdy
*= FIXED_ONE
;
619 /* find trivial reject offsets for each edge for a single-pixel
620 * sized block. These will be scaled up at each recursive level to
621 * match the active blocksize. Scaling in this way works best if
622 * the blocks are square.
625 if (plane
->dcdx
< 0) plane
->eo
-= plane
->dcdx
;
626 if (plane
->dcdy
> 0) plane
->eo
+= plane
->dcdy
;
628 /* Calculate trivial accept offsets from the above.
630 plane
->ei
= plane
->dcdy
- plane
->dcdx
- plane
->eo
;
632 plane
->step
= line
->step
[i
];
634 /* Fill in the inputs.step[][] arrays.
635 * We've manually unrolled some loops here.
637 #define SETUP_STEP(j, x, y) \
638 line->step[i][j] = y * plane->dcdy - x * plane->dcdx
652 SETUP_STEP(10, 0, 3);
653 SETUP_STEP(11, 1, 3);
655 SETUP_STEP(12, 2, 2);
656 SETUP_STEP(13, 3, 2);
657 SETUP_STEP(14, 2, 3);
658 SETUP_STEP(15, 3, 3);
664 * When rasterizing scissored tris, use the intersection of the
665 * triangle bounding box and the scissor rect to generate the
668 * This permits us to cut off the triangle "tails" that are present
669 * in the intermediate recursive levels caused when two of the
670 * triangles edges don't diverge quickly enough to trivially reject
671 * exterior blocks from the triangle.
673 * It's not really clear if it's worth worrying about these tails,
674 * but since we generate the planes for each scissored tri, it's
675 * free to trim them in this case.
677 * Note that otherwise, the scissor planes only vary in 'C' value,
678 * and even then only on state-changes. Could alternatively store
679 * these planes elsewhere.
681 if (nr_planes
== 8) {
682 line
->plane
[4].step
= step_scissor_maxx
;
683 line
->plane
[4].dcdx
= 1;
684 line
->plane
[4].dcdy
= 0;
685 line
->plane
[4].c
= maxx
;
686 line
->plane
[4].ei
= -1;
687 line
->plane
[4].eo
= 0;
689 line
->plane
[5].step
= step_scissor_miny
;
690 line
->plane
[5].dcdx
= 0;
691 line
->plane
[5].dcdy
= 1;
692 line
->plane
[5].c
= 1-miny
;
693 line
->plane
[5].ei
= 0;
694 line
->plane
[5].eo
= 1;
696 line
->plane
[6].step
= step_scissor_maxy
;
697 line
->plane
[6].dcdx
= 0;
698 line
->plane
[6].dcdy
= -1;
699 line
->plane
[6].c
= maxy
;
700 line
->plane
[6].ei
= -1;
701 line
->plane
[6].eo
= 0;
703 line
->plane
[7].step
= step_scissor_minx
;
704 line
->plane
[7].dcdx
= -1;
705 line
->plane
[7].dcdy
= 0;
706 line
->plane
[7].c
= 1-minx
;
707 line
->plane
[7].ei
= 0;
708 line
->plane
[7].eo
= 1;
713 * All fields of 'line' are now set. The remaining code here is
714 * concerned with binning.
717 /* Convert to tile coordinates, and inclusive ranges:
719 ix0
= minx
/ TILE_SIZE
;
720 iy0
= miny
/ TILE_SIZE
;
721 ix1
= (maxx
-1) / TILE_SIZE
;
722 iy1
= (maxy
-1) / TILE_SIZE
;
725 * Clamp to framebuffer size
727 assert(ix0
== MAX2(ix0
, 0));
728 assert(iy0
== MAX2(iy0
, 0));
729 assert(ix1
== MIN2(ix1
, scene
->tiles_x
- 1));
730 assert(iy1
== MIN2(iy1
, scene
->tiles_y
- 1));
732 /* Determine which tile(s) intersect the triangle's bounding box
734 if (iy0
== iy1
&& ix0
== ix1
)
736 /* Triangle is contained in a single tile:
738 lp_scene_bin_command( scene
, ix0
, iy0
,
739 lp_rast_tri_tab
[nr_planes
],
740 lp_rast_arg_triangle(line
, (1<<nr_planes
)-1) );
750 int is_blit
= -1; /* undetermined */
752 for (i
= 0; i
< nr_planes
; i
++) {
753 c
[i
] = (line
->plane
[i
].c
+
754 line
->plane
[i
].dcdy
* iy0
* TILE_SIZE
-
755 line
->plane
[i
].dcdx
* ix0
* TILE_SIZE
);
757 ei
[i
] = line
->plane
[i
].ei
<< TILE_ORDER
;
758 eo
[i
] = line
->plane
[i
].eo
<< TILE_ORDER
;
759 xstep
[i
] = -(line
->plane
[i
].dcdx
<< TILE_ORDER
);
760 ystep
[i
] = line
->plane
[i
].dcdy
<< TILE_ORDER
;
765 /* Test tile-sized blocks against the triangle.
766 * Discard blocks fully outside the tri. If the block is fully
767 * contained inside the tri, bin an lp_rast_shade_tile command.
768 * Else, bin a lp_rast_triangle command.
770 for (y
= iy0
; y
<= iy1
; y
++)
772 boolean in
= FALSE
; /* are we inside the triangle? */
775 for (i
= 0; i
< nr_planes
; i
++)
778 for (x
= ix0
; x
<= ix1
; x
++)
783 for (i
= 0; i
< nr_planes
; i
++) {
784 int planeout
= cx
[i
] + eo
[i
];
785 int planepartial
= cx
[i
] + ei
[i
] - 1;
786 out
|= (planeout
>> 31);
787 partial
|= (planepartial
>> 31) & (1<<i
);
792 break; /* exiting triangle, all done with this row */
793 LP_COUNT(nr_empty_64
);
796 /* Not trivially accepted by at least one plane -
797 * rasterize/shade partial tile
799 int count
= util_bitcount(partial
);
801 lp_scene_bin_command( scene
, x
, y
,
802 lp_rast_tri_tab
[count
],
803 lp_rast_arg_triangle(line
, partial
) );
805 LP_COUNT(nr_partially_covered_64
);
808 /* triangle covers the whole tile- shade whole tile */
809 LP_COUNT(nr_fully_covered_64
);
811 /* leverages on existing code in lp_setup_tri.c */
812 do_triangle_ccw_whole_tile(setup
, scene
, line
, x
, y
,
816 /* Iterate cx values across the region:
818 for (i
= 0; i
< nr_planes
; i
++)
822 /* Iterate c values down the region:
824 for (i
= 0; i
< nr_planes
; i
++)
831 void lp_setup_choose_line( struct lp_setup_context
*setup
)
833 setup
->line
= lp_setup_line
;