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 * Triangle rendering within a tile.
32 #include <transpose_matrix4x4.h>
33 #include "pipe/p_compiler.h"
34 #include "pipe/p_format.h"
35 #include "util/u_math.h"
36 #include "spu_colorpack.h"
38 #include "spu_texture.h"
43 /** Masks are uint[4] vectors with each element being 0 or 0xffffffff */
44 typedef vector
unsigned int mask_t
;
49 * Simplified types taken from other parts of Gallium
51 struct vertex_header
{
59 #define CEILF(X) ((float) (int) ((X) + 0.99999))
62 #define QUAD_TOP_LEFT 0
63 #define QUAD_TOP_RIGHT 1
64 #define QUAD_BOTTOM_LEFT 2
65 #define QUAD_BOTTOM_RIGHT 3
66 #define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
67 #define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
68 #define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
69 #define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
79 float dx
; /**< X(v1) - X(v0), used only during setup */
80 float dy
; /**< Y(v1) - Y(v0), used only during setup */
81 float dxdy
; /**< dx/dy */
82 float sx
, sy
; /**< first sample point coord */
83 int lines
; /**< number of lines on this edge */
96 * Triangle setup info (derived from draw_stage).
97 * Also used for line drawing (taking some liberties).
101 /* Vertices are just an array of floats making up each attribute in
102 * turn. Currently fixed at 4 floats, but should change in time.
103 * Codegen will help cope with this.
105 const struct vertex_header
*vmax
;
106 const struct vertex_header
*vmid
;
107 const struct vertex_header
*vmin
;
108 const struct vertex_header
*vprovoke
;
114 float oneOverArea
; /* XXX maybe make into vector? */
118 uint tx
, ty
; /**< position of current tile (x, y) */
120 int cliprect_minx
, cliprect_maxx
, cliprect_miny
, cliprect_maxy
;
122 struct interp_coef coef
[PIPE_MAX_SHADER_INPUTS
];
125 int left
[2]; /**< [0] = row0, [1] = row1 */
129 unsigned mask
; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
134 static struct setup_stage setup
;
138 * Evaluate attribute coefficients (plane equations) to compute
139 * attribute values for the four fragments in a quad.
140 * Eg: four colors will be computed (in AoS format).
143 eval_coeff(uint slot
, float x
, float y
, vector
float w
, vector
float result
[4])
145 switch (spu
.vertex_info
.attrib
[slot
].interp_mode
) {
146 case INTERP_CONSTANT
:
147 result
[QUAD_TOP_LEFT
] =
148 result
[QUAD_TOP_RIGHT
] =
149 result
[QUAD_BOTTOM_LEFT
] =
150 result
[QUAD_BOTTOM_RIGHT
] = setup
.coef
[slot
].a0
;
154 vector
float dadx
= setup
.coef
[slot
].dadx
;
155 vector
float dady
= setup
.coef
[slot
].dady
;
156 vector
float topLeft
=
157 spu_add(setup
.coef
[slot
].a0
,
158 spu_add(spu_mul(spu_splats(x
), dadx
),
159 spu_mul(spu_splats(y
), dady
)));
161 result
[QUAD_TOP_LEFT
] = topLeft
;
162 result
[QUAD_TOP_RIGHT
] = spu_add(topLeft
, dadx
);
163 result
[QUAD_BOTTOM_LEFT
] = spu_add(topLeft
, dady
);
164 result
[QUAD_BOTTOM_RIGHT
] = spu_add(spu_add(topLeft
, dadx
), dady
);
167 case INTERP_PERSPECTIVE
:
169 vector
float dadx
= setup
.coef
[slot
].dadx
;
170 vector
float dady
= setup
.coef
[slot
].dady
;
171 vector
float topLeft
=
172 spu_add(setup
.coef
[slot
].a0
,
173 spu_add(spu_mul(spu_splats(x
), dadx
),
174 spu_mul(spu_splats(y
), dady
)));
176 vector
float wInv
= spu_re(w
); /* 1.0 / w */
178 result
[QUAD_TOP_LEFT
] = spu_mul(topLeft
, wInv
);
179 result
[QUAD_TOP_RIGHT
] = spu_mul(spu_add(topLeft
, dadx
), wInv
);
180 result
[QUAD_BOTTOM_LEFT
] = spu_mul(spu_add(topLeft
, dady
), wInv
);
181 result
[QUAD_BOTTOM_RIGHT
] = spu_mul(spu_add(spu_add(topLeft
, dadx
), dady
), wInv
);
194 * As above, but return 4 vectors in SOA format.
195 * XXX this will all be re-written someday.
198 eval_coeff_soa(uint slot
, float x
, float y
, vector
float w
, vector
float result
[4])
200 eval_coeff(slot
, x
, y
, w
, result
);
201 _transpose_matrix4x4(result
, result
);
205 /** Evalute coefficients to get Z for four pixels in a quad */
206 static INLINE vector
float
207 eval_z(float x
, float y
)
210 const float dzdx
= spu_extract(setup
.coef
[slot
].dadx
, 2);
211 const float dzdy
= spu_extract(setup
.coef
[slot
].dady
, 2);
212 const float topLeft
= spu_extract(setup
.coef
[slot
].a0
, 2) + x
* dzdx
+ y
* dzdy
;
213 const vector
float topLeftv
= spu_splats(topLeft
);
214 const vector
float derivs
= (vector
float) { 0.0, dzdx
, dzdy
, dzdx
+ dzdy
};
215 return spu_add(topLeftv
, derivs
);
219 /** Evalute coefficients to get W for four pixels in a quad */
220 static INLINE vector
float
221 eval_w(float x
, float y
)
224 const float dwdx
= spu_extract(setup
.coef
[slot
].dadx
, 3);
225 const float dwdy
= spu_extract(setup
.coef
[slot
].dady
, 3);
226 const float topLeft
= spu_extract(setup
.coef
[slot
].a0
, 3) + x
* dwdx
+ y
* dwdy
;
227 const vector
float topLeftv
= spu_splats(topLeft
);
228 const vector
float derivs
= (vector
float) { 0.0, dwdx
, dwdy
, dwdx
+ dwdy
};
229 return spu_add(topLeftv
, derivs
);
234 * Emit a quad (pass to next stage). No clipping is done.
235 * Note: about 1/5 to 1/7 of the time, mask is zero and this function
236 * should be skipped. But adding the test for that slows things down
240 emit_quad( int x
, int y
, mask_t mask
)
242 /* If any bits in mask are set... */
243 if (spu_extract(spu_orx(mask
), 0)) {
244 const int ix
= x
- setup
.cliprect_minx
;
245 const int iy
= y
- setup
.cliprect_miny
;
247 spu
.cur_ctile_status
= TILE_STATUS_DIRTY
;
248 spu
.cur_ztile_status
= TILE_STATUS_DIRTY
;
252 * Run fragment shader, execute per-fragment ops, update fb/tile.
254 vector
float inputs
[4*4], outputs
[2*4];
255 vector
float fragZ
= eval_z((float) x
, (float) y
);
256 vector
float fragW
= eval_w((float) x
, (float) y
);
257 vector
unsigned int kill_mask
;
261 eval_coeff_soa(1, (float) x
, (float) y
, fragW
, inputs
);
264 for (i
= 0; i
< spu
.vertex_info
.num_attribs
; i
++) {
265 eval_coeff_soa(i
+1, (float) x
, (float) y
, fragW
, inputs
+ i
* 4);
268 ASSERT(spu
.fragment_program
);
269 ASSERT(spu
.fragment_ops
);
271 /* Execute the current fragment program */
272 kill_mask
= spu
.fragment_program(inputs
, outputs
, spu
.constants
);
274 mask
= spu_andc(mask
, kill_mask
);
276 /* Execute per-fragment/quad operations, including:
277 * alpha test, z test, stencil test, blend and framebuffer writing.
278 * Note that there are two different fragment operations functions
279 * that can be called, one for front-facing fragments, and one
280 * for back-facing fragments. (Often the two are the same;
281 * but in some cases, like two-sided stenciling, they can be
282 * very different.) So choose the correct function depending
283 * on the calculated facing.
285 spu
.fragment_ops
[setup
.facing
](ix
, iy
, &spu
.ctile
, &spu
.ztile
,
298 * Given an X or Y coordinate, return the block/quad coordinate that it
309 * Compute mask which indicates which pixels in the 2x2 quad are actually inside
310 * the triangle's bounds.
311 * The mask is a uint4 vector and each element will be 0 or 0xffffffff.
314 calculate_mask(int x
)
316 /* This is a little tricky.
317 * Use & instead of && to avoid branches.
318 * Use negation to convert true/false to ~0/0 values.
321 mask
= spu_insert(-((x
>= setup
.span
.left
[0]) & (x
< setup
.span
.right
[0])), mask
, 0);
322 mask
= spu_insert(-((x
+1 >= setup
.span
.left
[0]) & (x
+1 < setup
.span
.right
[0])), mask
, 1);
323 mask
= spu_insert(-((x
>= setup
.span
.left
[1]) & (x
< setup
.span
.right
[1])), mask
, 2);
324 mask
= spu_insert(-((x
+1 >= setup
.span
.left
[1]) & (x
+1 < setup
.span
.right
[1])), mask
, 3);
330 * Render a horizontal span of quads
335 int minleft
, maxright
;
338 switch (setup
.span
.y_flags
) {
340 /* both odd and even lines written (both quad rows) */
341 minleft
= MIN2(setup
.span
.left
[0], setup
.span
.left
[1]);
342 maxright
= MAX2(setup
.span
.right
[0], setup
.span
.right
[1]);
346 /* only even line written (quad top row) */
347 minleft
= setup
.span
.left
[0];
348 maxright
= setup
.span
.right
[0];
352 /* only odd line written (quad bottom row) */
353 minleft
= setup
.span
.left
[1];
354 maxright
= setup
.span
.right
[1];
361 /* OK, we're very likely to need the tile data now.
362 * clear or finish waiting if needed.
364 if (spu
.cur_ctile_status
== TILE_STATUS_GETTING
) {
365 /* wait for mfc_get() to complete */
366 //printf("SPU: %u: waiting for ctile\n", spu.init.id);
367 wait_on_mask(1 << TAG_READ_TILE_COLOR
);
368 spu
.cur_ctile_status
= TILE_STATUS_CLEAN
;
370 else if (spu
.cur_ctile_status
== TILE_STATUS_CLEAR
) {
371 //printf("SPU %u: clearing C tile %u, %u\n", spu.init.id, setup.tx, setup.ty);
372 clear_c_tile(&spu
.ctile
);
373 spu
.cur_ctile_status
= TILE_STATUS_DIRTY
;
375 ASSERT(spu
.cur_ctile_status
!= TILE_STATUS_DEFINED
);
377 if (spu
.read_depth_stencil
) {
378 if (spu
.cur_ztile_status
== TILE_STATUS_GETTING
) {
379 /* wait for mfc_get() to complete */
380 //printf("SPU: %u: waiting for ztile\n", spu.init.id);
381 wait_on_mask(1 << TAG_READ_TILE_Z
);
382 spu
.cur_ztile_status
= TILE_STATUS_CLEAN
;
384 else if (spu
.cur_ztile_status
== TILE_STATUS_CLEAR
) {
385 //printf("SPU %u: clearing Z tile %u, %u\n", spu.init.id, setup.tx, setup.ty);
386 clear_z_tile(&spu
.ztile
);
387 spu
.cur_ztile_status
= TILE_STATUS_DIRTY
;
389 ASSERT(spu
.cur_ztile_status
!= TILE_STATUS_DEFINED
);
392 /* XXX this loop could be moved into the above switch cases and
393 * calculate_mask() could be simplified a bit...
395 for (x
= block(minleft
); x
<= block(maxright
); x
+= 2) {
396 emit_quad( x
, setup
.span
.y
, calculate_mask( x
));
400 setup
.span
.y_flags
= 0;
401 setup
.span
.right
[0] = 0;
402 setup
.span
.right
[1] = 0;
408 print_vertex(const struct vertex_header
*v
)
411 fprintf(stderr
, " Vertex: (%p)\n", v
);
412 for (i
= 0; i
< spu
.vertex_info
.num_attribs
; i
++) {
413 fprintf(stderr
, " %d: %f %f %f %f\n", i
,
414 spu_extract(v
->data
[i
], 0),
415 spu_extract(v
->data
[i
], 1),
416 spu_extract(v
->data
[i
], 2),
417 spu_extract(v
->data
[i
], 3));
424 * Sort vertices from top to bottom.
425 * Compute area and determine front vs. back facing.
426 * Do coarse clip test against tile bounds
427 * \return FALSE if tri is totally outside tile, TRUE otherwise
430 setup_sort_vertices(const struct vertex_header
*v0
,
431 const struct vertex_header
*v1
,
432 const struct vertex_header
*v2
)
437 if (spu
.init
.id
==0) {
438 fprintf(stderr
, "SPU %u: Triangle:\n", spu
.init
.id
);
445 /* determine bottom to top order of vertices */
447 float y0
= spu_extract(v0
->data
[0], 1);
448 float y1
= spu_extract(v1
->data
[0], 1);
449 float y2
= spu_extract(v2
->data
[0], 1);
498 /* Check if triangle is completely outside the tile bounds */
499 if (spu_extract(setup
.vmin
->data
[0], 1) > setup
.cliprect_maxy
)
501 if (spu_extract(setup
.vmax
->data
[0], 1) < setup
.cliprect_miny
)
503 if (spu_extract(setup
.vmin
->data
[0], 0) < setup
.cliprect_minx
&&
504 spu_extract(setup
.vmid
->data
[0], 0) < setup
.cliprect_minx
&&
505 spu_extract(setup
.vmax
->data
[0], 0) < setup
.cliprect_minx
)
507 if (spu_extract(setup
.vmin
->data
[0], 0) > setup
.cliprect_maxx
&&
508 spu_extract(setup
.vmid
->data
[0], 0) > setup
.cliprect_maxx
&&
509 spu_extract(setup
.vmax
->data
[0], 0) > setup
.cliprect_maxx
)
512 setup
.ebot
.dx
= spu_extract(setup
.vmid
->data
[0], 0) - spu_extract(setup
.vmin
->data
[0], 0);
513 setup
.ebot
.dy
= spu_extract(setup
.vmid
->data
[0], 1) - spu_extract(setup
.vmin
->data
[0], 1);
514 setup
.emaj
.dx
= spu_extract(setup
.vmax
->data
[0], 0) - spu_extract(setup
.vmin
->data
[0], 0);
515 setup
.emaj
.dy
= spu_extract(setup
.vmax
->data
[0], 1) - spu_extract(setup
.vmin
->data
[0], 1);
516 setup
.etop
.dx
= spu_extract(setup
.vmax
->data
[0], 0) - spu_extract(setup
.vmid
->data
[0], 0);
517 setup
.etop
.dy
= spu_extract(setup
.vmax
->data
[0], 1) - spu_extract(setup
.vmid
->data
[0], 1);
520 * Compute triangle's area. Use 1/area to compute partial
521 * derivatives of attributes later.
523 area
= setup
.emaj
.dx
* setup
.ebot
.dy
- setup
.ebot
.dx
* setup
.emaj
.dy
;
525 setup
.oneOverArea
= 1.0f
/ area
;
527 /* The product of area * sign indicates front/back orientation (0/1).
528 * Just in case someone gets the bright idea of switching the front
529 * and back constants without noticing that we're assuming their
530 * values in this operation, also assert that the values are
531 * what we think they are.
533 ASSERT(CELL_FACING_FRONT
== 0);
534 ASSERT(CELL_FACING_BACK
== 1);
535 setup
.facing
= (area
* sign
> 0.0f
)
536 ^ (spu
.rasterizer
.front_winding
== PIPE_WINDING_CW
);
545 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
546 * The value value comes from vertex->data[slot].
547 * The result will be put into setup.coef[slot].a0.
548 * \param slot which attribute slot
551 const_coeff4(uint slot
)
553 setup
.coef
[slot
].dadx
= (vector
float) {0.0, 0.0, 0.0, 0.0};
554 setup
.coef
[slot
].dady
= (vector
float) {0.0, 0.0, 0.0, 0.0};
555 setup
.coef
[slot
].a0
= setup
.vprovoke
->data
[slot
];
560 * As above, but interp setup all four vector components.
563 tri_linear_coeff4(uint slot
)
565 const vector
float vmin_d
= setup
.vmin
->data
[slot
];
566 const vector
float vmid_d
= setup
.vmid
->data
[slot
];
567 const vector
float vmax_d
= setup
.vmax
->data
[slot
];
568 const vector
float xxxx
= spu_splats(spu_extract(setup
.vmin
->data
[0], 0) - 0.5f
);
569 const vector
float yyyy
= spu_splats(spu_extract(setup
.vmin
->data
[0], 1) - 0.5f
);
571 vector
float botda
= vmid_d
- vmin_d
;
572 vector
float majda
= vmax_d
- vmin_d
;
574 vector
float a
= spu_sub(spu_mul(spu_splats(setup
.ebot
.dy
), majda
),
575 spu_mul(botda
, spu_splats(setup
.emaj
.dy
)));
576 vector
float b
= spu_sub(spu_mul(spu_splats(setup
.emaj
.dx
), botda
),
577 spu_mul(majda
, spu_splats(setup
.ebot
.dx
)));
579 setup
.coef
[slot
].dadx
= spu_mul(a
, spu_splats(setup
.oneOverArea
));
580 setup
.coef
[slot
].dady
= spu_mul(b
, spu_splats(setup
.oneOverArea
));
582 vector
float tempx
= spu_mul(setup
.coef
[slot
].dadx
, xxxx
);
583 vector
float tempy
= spu_mul(setup
.coef
[slot
].dady
, yyyy
);
585 setup
.coef
[slot
].a0
= spu_sub(vmin_d
, spu_add(tempx
, tempy
));
590 * Compute a0, dadx and dady for a perspective-corrected interpolant,
592 * We basically multiply the vertex value by 1/w before computing
593 * the plane coefficients (a0, dadx, dady).
594 * Later, when we compute the value at a particular fragment position we'll
595 * divide the interpolated value by the interpolated W at that fragment.
598 tri_persp_coeff4(uint slot
)
600 const vector
float xxxx
= spu_splats(spu_extract(setup
.vmin
->data
[0], 0) - 0.5f
);
601 const vector
float yyyy
= spu_splats(spu_extract(setup
.vmin
->data
[0], 1) - 0.5f
);
603 const vector
float vmin_w
= spu_splats(spu_extract(setup
.vmin
->data
[0], 3));
604 const vector
float vmid_w
= spu_splats(spu_extract(setup
.vmid
->data
[0], 3));
605 const vector
float vmax_w
= spu_splats(spu_extract(setup
.vmax
->data
[0], 3));
607 vector
float vmin_d
= setup
.vmin
->data
[slot
];
608 vector
float vmid_d
= setup
.vmid
->data
[slot
];
609 vector
float vmax_d
= setup
.vmax
->data
[slot
];
611 vmin_d
= spu_mul(vmin_d
, vmin_w
);
612 vmid_d
= spu_mul(vmid_d
, vmid_w
);
613 vmax_d
= spu_mul(vmax_d
, vmax_w
);
615 vector
float botda
= vmid_d
- vmin_d
;
616 vector
float majda
= vmax_d
- vmin_d
;
618 vector
float a
= spu_sub(spu_mul(spu_splats(setup
.ebot
.dy
), majda
),
619 spu_mul(botda
, spu_splats(setup
.emaj
.dy
)));
620 vector
float b
= spu_sub(spu_mul(spu_splats(setup
.emaj
.dx
), botda
),
621 spu_mul(majda
, spu_splats(setup
.ebot
.dx
)));
623 setup
.coef
[slot
].dadx
= spu_mul(a
, spu_splats(setup
.oneOverArea
));
624 setup
.coef
[slot
].dady
= spu_mul(b
, spu_splats(setup
.oneOverArea
));
626 vector
float tempx
= spu_mul(setup
.coef
[slot
].dadx
, xxxx
);
627 vector
float tempy
= spu_mul(setup
.coef
[slot
].dady
, yyyy
);
629 setup
.coef
[slot
].a0
= spu_sub(vmin_d
, spu_add(tempx
, tempy
));
635 * Compute the setup.coef[] array dadx, dady, a0 values.
636 * Must be called after setup.vmin,vmid,vmax,vprovoke are initialized.
639 setup_tri_coefficients(void)
643 for (i
= 0; i
< spu
.vertex_info
.num_attribs
; i
++) {
644 switch (spu
.vertex_info
.attrib
[i
].interp_mode
) {
647 case INTERP_CONSTANT
:
653 tri_linear_coeff4(i
);
655 case INTERP_PERSPECTIVE
:
666 setup_tri_edges(void)
668 float vmin_x
= spu_extract(setup
.vmin
->data
[0], 0) + 0.5f
;
669 float vmid_x
= spu_extract(setup
.vmid
->data
[0], 0) + 0.5f
;
671 float vmin_y
= spu_extract(setup
.vmin
->data
[0], 1) - 0.5f
;
672 float vmid_y
= spu_extract(setup
.vmid
->data
[0], 1) - 0.5f
;
673 float vmax_y
= spu_extract(setup
.vmax
->data
[0], 1) - 0.5f
;
675 setup
.emaj
.sy
= CEILF(vmin_y
);
676 setup
.emaj
.lines
= (int) CEILF(vmax_y
- setup
.emaj
.sy
);
677 setup
.emaj
.dxdy
= setup
.emaj
.dx
/ setup
.emaj
.dy
;
678 setup
.emaj
.sx
= vmin_x
+ (setup
.emaj
.sy
- vmin_y
) * setup
.emaj
.dxdy
;
680 setup
.etop
.sy
= CEILF(vmid_y
);
681 setup
.etop
.lines
= (int) CEILF(vmax_y
- setup
.etop
.sy
);
682 setup
.etop
.dxdy
= setup
.etop
.dx
/ setup
.etop
.dy
;
683 setup
.etop
.sx
= vmid_x
+ (setup
.etop
.sy
- vmid_y
) * setup
.etop
.dxdy
;
685 setup
.ebot
.sy
= CEILF(vmin_y
);
686 setup
.ebot
.lines
= (int) CEILF(vmid_y
- setup
.ebot
.sy
);
687 setup
.ebot
.dxdy
= setup
.ebot
.dx
/ setup
.ebot
.dy
;
688 setup
.ebot
.sx
= vmin_x
+ (setup
.ebot
.sy
- vmin_y
) * setup
.ebot
.dxdy
;
693 * Render the upper or lower half of a triangle.
694 * Scissoring/cliprect is applied here too.
697 subtriangle(struct edge
*eleft
, struct edge
*eright
, unsigned lines
)
699 const int minx
= setup
.cliprect_minx
;
700 const int maxx
= setup
.cliprect_maxx
;
701 const int miny
= setup
.cliprect_miny
;
702 const int maxy
= setup
.cliprect_maxy
;
703 int y
, start_y
, finish_y
;
704 int sy
= (int)eleft
->sy
;
706 ASSERT((int)eleft
->sy
== (int) eright
->sy
);
708 /* clip top/bottom */
710 finish_y
= sy
+ lines
;
722 _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
725 for (y
= start_y
; y
< finish_y
; y
++) {
727 /* avoid accumulating adds as floats don't have the precision to
728 * accurately iterate large triangle edges that way. luckily we
729 * can just multiply these days.
731 * this is all drowned out by the attribute interpolation anyway.
733 int left
= (int)(eleft
->sx
+ y
* eleft
->dxdy
);
734 int right
= (int)(eright
->sx
+ y
* eright
->dxdy
);
736 /* clip left/right */
744 if (block(_y
) != setup
.span
.y
) {
746 setup
.span
.y
= block(_y
);
749 setup
.span
.left
[_y
&1] = left
;
750 setup
.span
.right
[_y
&1] = right
;
751 setup
.span
.y_flags
|= 1<<(_y
&1);
756 /* save the values so that emaj can be restarted:
758 eleft
->sx
+= lines
* eleft
->dxdy
;
759 eright
->sx
+= lines
* eright
->dxdy
;
766 * Draw triangle into tile at (tx, ty) (tile coords)
767 * The tile data should have already been fetched.
770 tri_draw(const float *v0
, const float *v1
, const float *v2
,
776 /* set clipping bounds to tile bounds */
777 setup
.cliprect_minx
= tx
* TILE_SIZE
;
778 setup
.cliprect_miny
= ty
* TILE_SIZE
;
779 setup
.cliprect_maxx
= (tx
+ 1) * TILE_SIZE
;
780 setup
.cliprect_maxy
= (ty
+ 1) * TILE_SIZE
;
782 if (!setup_sort_vertices((struct vertex_header
*) v0
,
783 (struct vertex_header
*) v1
,
784 (struct vertex_header
*) v2
)) {
785 return FALSE
; /* totally clipped */
788 setup_tri_coefficients();
792 setup
.span
.y_flags
= 0;
793 setup
.span
.right
[0] = 0;
794 setup
.span
.right
[1] = 0;
796 if (setup
.oneOverArea
< 0.0) {
798 subtriangle( &setup
.emaj
, &setup
.ebot
, setup
.ebot
.lines
);
799 subtriangle( &setup
.emaj
, &setup
.etop
, setup
.etop
.lines
);
803 subtriangle( &setup
.ebot
, &setup
.emaj
, setup
.ebot
.lines
);
804 subtriangle( &setup
.etop
, &setup
.emaj
, setup
.etop
.lines
);