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 "pipe/p_compiler.h"
33 #include "pipe/p_format.h"
34 #include "pipe/p_util.h"
35 #include "spu_blend.h"
36 #include "spu_colorpack.h"
38 #include "spu_texture.h"
42 #include "spu_ztest.h"
45 /** Masks are uint[4] vectors with each element being 0 or 0xffffffff */
46 typedef vector
unsigned int mask_t
;
56 * Simplified types taken from other parts of Gallium
58 struct vertex_header
{
66 #define CEILF(X) ((float) (int) ((X) + 0.99999))
69 #define QUAD_TOP_LEFT 0
70 #define QUAD_TOP_RIGHT 1
71 #define QUAD_BOTTOM_LEFT 2
72 #define QUAD_BOTTOM_RIGHT 3
73 #define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
74 #define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
75 #define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
76 #define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
86 float dx
; /**< X(v1) - X(v0), used only during setup */
87 float dy
; /**< Y(v1) - Y(v0), used only during setup */
88 float dxdy
; /**< dx/dy */
89 float sx
, sy
; /**< first sample point coord */
90 int lines
; /**< number of lines on this edge */
103 * Triangle setup info (derived from draw_stage).
104 * Also used for line drawing (taking some liberties).
108 /* Vertices are just an array of floats making up each attribute in
109 * turn. Currently fixed at 4 floats, but should change in time.
110 * Codegen will help cope with this.
112 const struct vertex_header
*vmax
;
113 const struct vertex_header
*vmid
;
114 const struct vertex_header
*vmin
;
115 const struct vertex_header
*vprovoke
;
125 int cliprect_minx
, cliprect_maxx
, cliprect_miny
, cliprect_maxy
;
128 struct tgsi_interp_coef coef
[PIPE_MAX_SHADER_INPUTS
];
130 struct interp_coef coef
[PIPE_MAX_SHADER_INPUTS
];
134 struct quad_header quad
;
138 int left
[2]; /**< [0] = row0, [1] = row1 */
142 unsigned mask
; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
148 static struct setup_stage setup
;
155 * Basically a cast wrapper.
157 static INLINE
struct setup_stage
*setup_stage( struct draw_stage
*stage
)
159 return (struct setup_stage
*)stage
;
165 * Clip setup.quad against the scissor/surface bounds.
168 quad_clip(struct setup_stage
*setup
)
170 const struct pipe_scissor_state
*cliprect
= &setup
.softpipe
->cliprect
;
171 const int minx
= (int) cliprect
->minx
;
172 const int maxx
= (int) cliprect
->maxx
;
173 const int miny
= (int) cliprect
->miny
;
174 const int maxy
= (int) cliprect
->maxy
;
176 if (setup
.quad
.x0
>= maxx
||
177 setup
.quad
.y0
>= maxy
||
178 setup
.quad
.x0
+ 1 < minx
||
179 setup
.quad
.y0
+ 1 < miny
) {
180 /* totally clipped */
181 setup
.quad
.mask
= 0x0;
184 if (setup
.quad
.x0
< minx
)
185 setup
.quad
.mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
186 if (setup
.quad
.y0
< miny
)
187 setup
.quad
.mask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
188 if (setup
.quad
.x0
== maxx
- 1)
189 setup
.quad
.mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
190 if (setup
.quad
.y0
== maxy
- 1)
191 setup
.quad
.mask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
197 * Emit a quad (pass to next stage) with clipping.
200 clip_emit_quad(struct setup_stage
*setup
)
203 if (setup
.quad
.mask
) {
204 struct softpipe_context
*sp
= setup
.softpipe
;
205 sp
->quad
.first
->run(sp
->quad
.first
, &setup
.quad
);
211 * Evaluate attribute coefficients (plane equations) to compute
212 * attribute values for the four fragments in a quad.
213 * Eg: four colors will be compute.
216 eval_coeff(uint slot
, float x
, float y
, vector
float result
[4])
218 switch (spu
.vertex_info
.interp_mode
[slot
]) {
219 case INTERP_CONSTANT
:
220 result
[QUAD_TOP_LEFT
] =
221 result
[QUAD_TOP_RIGHT
] =
222 result
[QUAD_BOTTOM_LEFT
] =
223 result
[QUAD_BOTTOM_RIGHT
] = setup
.coef
[slot
].a0
.v
;
227 /* fall-through, for now */
230 register vector
float dadx
= setup
.coef
[slot
].dadx
.v
;
231 register vector
float dady
= setup
.coef
[slot
].dady
.v
;
232 register vector
float topLeft
233 = spu_add(setup
.coef
[slot
].a0
.v
,
234 spu_add(spu_mul(spu_splats(x
), dadx
),
235 spu_mul(spu_splats(y
), dady
)));
237 result
[QUAD_TOP_LEFT
] = topLeft
;
238 result
[QUAD_TOP_RIGHT
] = spu_add(topLeft
, dadx
);
239 result
[QUAD_BOTTOM_LEFT
] = spu_add(topLeft
, dady
);
240 result
[QUAD_BOTTOM_RIGHT
] = spu_add(spu_add(topLeft
, dadx
), dady
);
246 static INLINE vector
float
247 eval_z(float x
, float y
)
250 const float dzdx
= setup
.coef
[slot
].dadx
.f
[2];
251 const float dzdy
= setup
.coef
[slot
].dady
.f
[2];
252 const float topLeft
= setup
.coef
[slot
].a0
.f
[2] + x
* dzdx
+ y
* dzdy
;
253 const vector
float topLeftv
= spu_splats(topLeft
);
254 const vector
float derivs
= (vector
float) { 0.0, dzdx
, dzdy
, dzdx
+ dzdy
};
255 return spu_add(topLeftv
, derivs
);
260 do_depth_test(int x
, int y
, mask_t quadmask
)
265 zvals
.v
= eval_z((float) x
, (float) y
);
267 if (spu
.fb
.depth_format
== PIPE_FORMAT_Z16_UNORM
) {
268 int ix
= (x
- setup
.cliprect_minx
) / 4;
269 int iy
= (y
- setup
.cliprect_miny
) / 2;
270 mask
= spu_z16_test_less(zvals
.v
, &spu
.ztile
.us8
[iy
][ix
], x
>>1, quadmask
);
273 int ix
= (x
- setup
.cliprect_minx
) / 2;
274 int iy
= (y
- setup
.cliprect_miny
) / 2;
275 mask
= spu_z32_test_less(zvals
.v
, &spu
.ztile
.ui4
[iy
][ix
], quadmask
);
278 if (spu_extract(spu_orx(mask
), 0))
279 spu
.cur_ztile_status
= TILE_STATUS_DIRTY
;
286 * Emit a quad (pass to next stage). No clipping is done.
287 * Note: about 1/5 to 1/7 of the time, mask is zero and this function
288 * should be skipped. But adding the test for that slows things down
292 emit_quad( int x
, int y
, mask_t mask
)
295 struct softpipe_context
*sp
= setup
.softpipe
;
298 setup
.quad
.mask
= mask
;
299 sp
->quad
.first
->run(sp
->quad
.first
, &setup
.quad
);
302 if (spu
.depth_stencil
.depth
.enabled
) {
303 mask
= do_depth_test(x
, y
, mask
);
306 /* If any bits in mask are set... */
307 if (spu_extract(spu_orx(mask
), 0)) {
308 const int ix
= x
- setup
.cliprect_minx
;
309 const int iy
= y
- setup
.cliprect_miny
;
310 const vector
unsigned char shuffle
= spu
.color_shuffle
;
311 vector
float colors
[4];
313 spu
.cur_ctile_status
= TILE_STATUS_DIRTY
;
315 if (spu
.texture
.start
) {
316 /* texture mapping */
317 vector
float texcoords
[4];
318 eval_coeff(2, (float) x
, (float) y
, texcoords
);
320 if (spu_extract(mask
, 0))
321 colors
[0] = spu
.sample_texture(texcoords
[0]);
322 if (spu_extract(mask
, 1))
323 colors
[1] = spu
.sample_texture(texcoords
[1]);
324 if (spu_extract(mask
, 2))
325 colors
[2] = spu
.sample_texture(texcoords
[2]);
326 if (spu_extract(mask
, 3))
327 colors
[3] = spu
.sample_texture(texcoords
[3]);
331 eval_coeff(1, (float) x
, (float) y
, colors
);
335 if (spu
.blend
.blend_enable
)
336 blend_quad(ix
% TILE_SIZE
, iy
% TILE_SIZE
, colors
);
339 if (spu_extract(mask
, 0))
340 spu
.ctile
.ui
[iy
][ix
] = spu_pack_color_shuffle(colors
[0], shuffle
);
341 if (spu_extract(mask
, 1))
342 spu
.ctile
.ui
[iy
][ix
+1] = spu_pack_color_shuffle(colors
[1], shuffle
);
343 if (spu_extract(mask
, 2))
344 spu
.ctile
.ui
[iy
+1][ix
] = spu_pack_color_shuffle(colors
[2], shuffle
);
345 if (spu_extract(mask
, 3))
346 spu
.ctile
.ui
[iy
+1][ix
+1] = spu_pack_color_shuffle(colors
[3], shuffle
);
349 /* SIMD_Z with swizzled color buffer (someday) */
350 vector
unsigned int uicolors
= *((vector
unsigned int *) &colors
);
351 spu
.ctile
.ui4
[iy
/2][ix
/2] = spu_sel(spu
.ctile
.ui4
[iy
/2][ix
/2], uicolors
, mask
);
360 * Given an X or Y coordinate, return the block/quad coordinate that it
363 static INLINE
int block( int x
)
370 * Compute mask which indicates which pixels in the 2x2 quad are actually inside
371 * the triangle's bounds.
372 * The mask is a uint4 vector and each element will be 0 or 0xffffffff.
374 static INLINE mask_t
calculate_mask( int x
)
376 /* This is a little tricky.
377 * Use & instead of && to avoid branches.
378 * Use negation to convert true/false to ~0/0 values.
381 mask
= spu_insert(-((x
>= setup
.span
.left
[0]) & (x
< setup
.span
.right
[0])), mask
, 0);
382 mask
= spu_insert(-((x
+1 >= setup
.span
.left
[0]) & (x
+1 < setup
.span
.right
[0])), mask
, 1);
383 mask
= spu_insert(-((x
>= setup
.span
.left
[1]) & (x
< setup
.span
.right
[1])), mask
, 2);
384 mask
= spu_insert(-((x
+1 >= setup
.span
.left
[1]) & (x
+1 < setup
.span
.right
[1])), mask
, 3);
390 * Render a horizontal span of quads
392 static void flush_spans( void )
394 int minleft
, maxright
;
397 switch (setup
.span
.y_flags
) {
399 /* both odd and even lines written (both quad rows) */
400 minleft
= MIN2(setup
.span
.left
[0], setup
.span
.left
[1]);
401 maxright
= MAX2(setup
.span
.right
[0], setup
.span
.right
[1]);
405 /* only even line written (quad top row) */
406 minleft
= setup
.span
.left
[0];
407 maxright
= setup
.span
.right
[0];
411 /* only odd line written (quad bottom row) */
412 minleft
= setup
.span
.left
[1];
413 maxright
= setup
.span
.right
[1];
421 /* OK, we're very likely to need the tile data now.
422 * clear or finish waiting if needed.
424 if (spu
.cur_ctile_status
== TILE_STATUS_GETTING
) {
425 /* wait for mfc_get() to complete */
426 //printf("SPU: %u: waiting for ctile\n", spu.init.id);
427 wait_on_mask(1 << TAG_READ_TILE_COLOR
);
428 spu
.cur_ctile_status
= TILE_STATUS_CLEAN
;
430 else if (spu
.cur_ctile_status
== TILE_STATUS_CLEAR
) {
431 //printf("SPU %u: clearing C tile %u, %u\n", spu.init.id, setup.tx, setup.ty);
432 clear_c_tile(&spu
.ctile
);
433 spu
.cur_ctile_status
= TILE_STATUS_DIRTY
;
435 ASSERT(spu
.cur_ctile_status
!= TILE_STATUS_DEFINED
);
437 if (spu
.depth_stencil
.depth
.enabled
) {
438 if (spu
.cur_ztile_status
== TILE_STATUS_GETTING
) {
439 /* wait for mfc_get() to complete */
440 //printf("SPU: %u: waiting for ztile\n", spu.init.id);
441 wait_on_mask(1 << TAG_READ_TILE_Z
);
442 spu
.cur_ztile_status
= TILE_STATUS_CLEAN
;
444 else if (spu
.cur_ztile_status
== TILE_STATUS_CLEAR
) {
445 //printf("SPU %u: clearing Z tile %u, %u\n", spu.init.id, setup.tx, setup.ty);
446 clear_z_tile(&spu
.ztile
);
447 spu
.cur_ztile_status
= TILE_STATUS_DIRTY
;
449 ASSERT(spu
.cur_ztile_status
!= TILE_STATUS_DEFINED
);
452 /* XXX this loop could be moved into the above switch cases and
453 * calculate_mask() could be simplified a bit...
455 for (x
= block(minleft
); x
<= block(maxright
); x
+= 2) {
457 emit_quad( x
, setup
.span
.y
, calculate_mask( x
) );
462 setup
.span
.y_flags
= 0;
463 setup
.span
.right
[0] = 0;
464 setup
.span
.right
[1] = 0;
468 static void print_vertex(const struct vertex_header
*v
)
471 fprintf(stderr
, "Vertex: (%p)\n", v
);
472 for (i
= 0; i
< setup
.quad
.nr_attrs
; i
++) {
473 fprintf(stderr
, " %d: %f %f %f %f\n", i
,
474 v
->data
[i
][0], v
->data
[i
][1], v
->data
[i
][2], v
->data
[i
][3]);
480 static boolean
setup_sort_vertices(const struct vertex_header
*v0
,
481 const struct vertex_header
*v1
,
482 const struct vertex_header
*v2
)
486 fprintf(stderr
, "Triangle:\n");
494 /* determine bottom to top order of vertices */
496 float y0
= spu_extract(v0
->data
[0], 1);
497 float y1
= spu_extract(v1
->data
[0], 1);
498 float y2
= spu_extract(v2
->data
[0], 1);
541 /* Check if triangle is completely outside the tile bounds */
542 if (spu_extract(setup
.vmin
->data
[0], 1) > setup
.cliprect_maxy
)
544 if (spu_extract(setup
.vmax
->data
[0], 1) < setup
.cliprect_miny
)
546 if (spu_extract(setup
.vmin
->data
[0], 0) < setup
.cliprect_minx
&&
547 spu_extract(setup
.vmid
->data
[0], 0) < setup
.cliprect_minx
&&
548 spu_extract(setup
.vmax
->data
[0], 0) < setup
.cliprect_minx
)
550 if (spu_extract(setup
.vmin
->data
[0], 0) > setup
.cliprect_maxx
&&
551 spu_extract(setup
.vmid
->data
[0], 0) > setup
.cliprect_maxx
&&
552 spu_extract(setup
.vmax
->data
[0], 0) > setup
.cliprect_maxx
)
555 setup
.ebot
.dx
= spu_extract(setup
.vmid
->data
[0], 0) - spu_extract(setup
.vmin
->data
[0], 0);
556 setup
.ebot
.dy
= spu_extract(setup
.vmid
->data
[0], 1) - spu_extract(setup
.vmin
->data
[0], 1);
557 setup
.emaj
.dx
= spu_extract(setup
.vmax
->data
[0], 0) - spu_extract(setup
.vmin
->data
[0], 0);
558 setup
.emaj
.dy
= spu_extract(setup
.vmax
->data
[0], 1) - spu_extract(setup
.vmin
->data
[0], 1);
559 setup
.etop
.dx
= spu_extract(setup
.vmax
->data
[0], 0) - spu_extract(setup
.vmid
->data
[0], 0);
560 setup
.etop
.dy
= spu_extract(setup
.vmax
->data
[0], 1) - spu_extract(setup
.vmid
->data
[0], 1);
563 * Compute triangle's area. Use 1/area to compute partial
564 * derivatives of attributes later.
566 * The area will be the same as prim->det, but the sign may be
567 * different depending on how the vertices get sorted above.
569 * To determine whether the primitive is front or back facing we
570 * use the prim->det value because its sign is correct.
573 const float area
= (setup
.emaj
.dx
* setup
.ebot
.dy
-
574 setup
.ebot
.dx
* setup
.emaj
.dy
);
576 setup
.oneoverarea
= 1.0f
/ area
;
578 _mesa_printf("%s one-over-area %f area %f det %f\n",
579 __FUNCTION__, setup.oneoverarea, area, prim->det );
584 /* We need to know if this is a front or back-facing triangle for:
585 * - the GLSL gl_FrontFacing fragment attribute (bool)
586 * - two-sided stencil test
588 setup
.quad
.facing
= (prim
->det
> 0.0) ^ (setup
.softpipe
->rasterizer
->front_winding
== PIPE_WINDING_CW
);
596 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
597 * The value value comes from vertex->data[slot].
598 * The result will be put into setup.coef[slot].a0.
599 * \param slot which attribute slot
602 const_coeff(uint slot
)
604 setup
.coef
[slot
].dadx
.v
= (vector
float) {0.0, 0.0, 0.0, 0.0};
605 setup
.coef
[slot
].dady
.v
= (vector
float) {0.0, 0.0, 0.0, 0.0};
606 setup
.coef
[slot
].a0
.v
= setup
.vprovoke
->data
[slot
];
611 * Compute a0, dadx and dady for a linearly interpolated coefficient,
615 tri_linear_coeff(uint slot
, uint firstComp
, uint lastComp
)
618 const float *vmin_d
= (float *) &setup
.vmin
->data
[slot
];
619 const float *vmid_d
= (float *) &setup
.vmid
->data
[slot
];
620 const float *vmax_d
= (float *) &setup
.vmax
->data
[slot
];
621 const float x
= spu_extract(setup
.vmin
->data
[0], 0) - 0.5f
;
622 const float y
= spu_extract(setup
.vmin
->data
[0], 1) - 0.5f
;
624 for (i
= firstComp
; i
< lastComp
; i
++) {
625 float botda
= vmid_d
[i
] - vmin_d
[i
];
626 float majda
= vmax_d
[i
] - vmin_d
[i
];
627 float a
= setup
.ebot
.dy
* majda
- botda
* setup
.emaj
.dy
;
628 float b
= setup
.emaj
.dx
* botda
- majda
* setup
.ebot
.dx
;
630 ASSERT(slot
< PIPE_MAX_SHADER_INPUTS
);
632 setup
.coef
[slot
].dadx
.f
[i
] = a
* setup
.oneoverarea
;
633 setup
.coef
[slot
].dady
.f
[i
] = b
* setup
.oneoverarea
;
635 /* calculate a0 as the value which would be sampled for the
636 * fragment at (0,0), taking into account that we want to sample at
637 * pixel centers, in other words (0.5, 0.5).
639 * this is neat but unfortunately not a good way to do things for
640 * triangles with very large values of dadx or dady as it will
641 * result in the subtraction and re-addition from a0 of a very
642 * large number, which means we'll end up loosing a lot of the
643 * fractional bits and precision from a0. the way to fix this is
644 * to define a0 as the sample at a pixel center somewhere near vmin
645 * instead - i'll switch to this later.
647 setup
.coef
[slot
].a0
.f
[i
] = (vmin_d
[i
] -
648 (setup
.coef
[slot
].dadx
.f
[i
] * x
+
649 setup
.coef
[slot
].dady
.f
[i
] * y
));
653 _mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n",
655 setup.coef[slot].a0[i],
656 setup.coef[slot].dadx.f[i],
657 setup.coef[slot].dady.f[i]);
663 * As above, but interp setup all four vector components.
666 tri_linear_coeff4(uint slot
)
668 const vector
float vmin_d
= setup
.vmin
->data
[slot
];
669 const vector
float vmid_d
= setup
.vmid
->data
[slot
];
670 const vector
float vmax_d
= setup
.vmax
->data
[slot
];
671 const vector
float xxxx
= spu_splats(spu_extract(setup
.vmin
->data
[0], 0) - 0.5f
);
672 const vector
float yyyy
= spu_splats(spu_extract(setup
.vmin
->data
[0], 1) - 0.5f
);
674 vector
float botda
= vmid_d
- vmin_d
;
675 vector
float majda
= vmax_d
- vmin_d
;
677 vector
float a
= spu_sub(spu_mul(spu_splats(setup
.ebot
.dy
), majda
),
678 spu_mul(botda
, spu_splats(setup
.emaj
.dy
)));
679 vector
float b
= spu_sub(spu_mul(spu_splats(setup
.emaj
.dx
), botda
),
680 spu_mul(majda
, spu_splats(setup
.ebot
.dx
)));
682 setup
.coef
[slot
].dadx
.v
= spu_mul(a
, spu_splats(setup
.oneoverarea
));
683 setup
.coef
[slot
].dady
.v
= spu_mul(b
, spu_splats(setup
.oneoverarea
));
685 vector
float tempx
= spu_mul(setup
.coef
[slot
].dadx
.v
, xxxx
);
686 vector
float tempy
= spu_mul(setup
.coef
[slot
].dady
.v
, yyyy
);
688 setup
.coef
[slot
].a0
.v
= spu_sub(vmin_d
, spu_add(tempx
, tempy
));
695 * Compute a0, dadx and dady for a perspective-corrected interpolant,
697 * We basically multiply the vertex value by 1/w before computing
698 * the plane coefficients (a0, dadx, dady).
699 * Later, when we compute the value at a particular fragment position we'll
700 * divide the interpolated value by the interpolated W at that fragment.
702 static void tri_persp_coeff( unsigned slot
,
705 /* premultiply by 1/w:
707 float mina
= setup
.vmin
->data
[slot
][i
] * setup
.vmin
->data
[0][3];
708 float mida
= setup
.vmid
->data
[slot
][i
] * setup
.vmid
->data
[0][3];
709 float maxa
= setup
.vmax
->data
[slot
][i
] * setup
.vmax
->data
[0][3];
711 float botda
= mida
- mina
;
712 float majda
= maxa
- mina
;
713 float a
= setup
.ebot
.dy
* majda
- botda
* setup
.emaj
.dy
;
714 float b
= setup
.emaj
.dx
* botda
- majda
* setup
.ebot
.dx
;
717 printf("tri persp %d,%d: %f %f %f\n", slot, i,
718 setup.vmin->data[slot][i],
719 setup.vmid->data[slot][i],
720 setup.vmax->data[slot][i]
724 assert(slot
< PIPE_MAX_SHADER_INPUTS
);
727 setup
.coef
[slot
].dadx
.f
[i
] = a
* setup
.oneoverarea
;
728 setup
.coef
[slot
].dady
.f
[i
] = b
* setup
.oneoverarea
;
729 setup
.coef
[slot
].a0
.f
[i
] = (mina
-
730 (setup
.coef
[slot
].dadx
.f
[i
] * (setup
.vmin
->data
[0][0] - 0.5f
) +
731 setup
.coef
[slot
].dady
.f
[i
] * (setup
.vmin
->data
[0][1] - 0.5f
)));
737 * Compute the setup.coef[] array dadx, dady, a0 values.
738 * Must be called after setup.vmin,vmid,vmax,vprovoke are initialized.
740 static void setup_tri_coefficients(void)
745 for (i
= 0; i
< spu
.vertex_info
.num_attribs
; i
++) {
746 switch (spu
.vertex_info
.interp_mode
[i
]) {
750 /*tri_linear_coeff(i, 2, 3);*/
751 /* XXX interp W if PERSPECTIVE... */
752 tri_linear_coeff4(i
);
754 case INTERP_CONSTANT
:
758 tri_linear_coeff4(i
);
760 case INTERP_PERSPECTIVE
:
761 tri_linear_coeff4(i
); /* temporary */
768 ASSERT(spu
.vertex_info
.interp_mode
[0] == INTERP_POS
);
769 ASSERT(spu
.vertex_info
.interp_mode
[1] == INTERP_LINEAR
||
770 spu
.vertex_info
.interp_mode
[1] == INTERP_CONSTANT
);
771 tri_linear_coeff(0, 2, 3); /* slot 0, z */
772 tri_linear_coeff(1, 0, 4); /* slot 1, color */
777 static void setup_tri_edges(void)
779 float vmin_x
= spu_extract(setup
.vmin
->data
[0], 0) + 0.5f
;
780 float vmid_x
= spu_extract(setup
.vmid
->data
[0], 0) + 0.5f
;
782 float vmin_y
= spu_extract(setup
.vmin
->data
[0], 1) - 0.5f
;
783 float vmid_y
= spu_extract(setup
.vmid
->data
[0], 1) - 0.5f
;
784 float vmax_y
= spu_extract(setup
.vmax
->data
[0], 1) - 0.5f
;
786 setup
.emaj
.sy
= CEILF(vmin_y
);
787 setup
.emaj
.lines
= (int) CEILF(vmax_y
- setup
.emaj
.sy
);
788 setup
.emaj
.dxdy
= setup
.emaj
.dx
/ setup
.emaj
.dy
;
789 setup
.emaj
.sx
= vmin_x
+ (setup
.emaj
.sy
- vmin_y
) * setup
.emaj
.dxdy
;
791 setup
.etop
.sy
= CEILF(vmid_y
);
792 setup
.etop
.lines
= (int) CEILF(vmax_y
- setup
.etop
.sy
);
793 setup
.etop
.dxdy
= setup
.etop
.dx
/ setup
.etop
.dy
;
794 setup
.etop
.sx
= vmid_x
+ (setup
.etop
.sy
- vmid_y
) * setup
.etop
.dxdy
;
796 setup
.ebot
.sy
= CEILF(vmin_y
);
797 setup
.ebot
.lines
= (int) CEILF(vmid_y
- setup
.ebot
.sy
);
798 setup
.ebot
.dxdy
= setup
.ebot
.dx
/ setup
.ebot
.dy
;
799 setup
.ebot
.sx
= vmin_x
+ (setup
.ebot
.sy
- vmin_y
) * setup
.ebot
.dxdy
;
804 * Render the upper or lower half of a triangle.
805 * Scissoring/cliprect is applied here too.
807 static void subtriangle( struct edge
*eleft
,
811 const int minx
= setup
.cliprect_minx
;
812 const int maxx
= setup
.cliprect_maxx
;
813 const int miny
= setup
.cliprect_miny
;
814 const int maxy
= setup
.cliprect_maxy
;
815 int y
, start_y
, finish_y
;
816 int sy
= (int)eleft
->sy
;
818 ASSERT((int)eleft
->sy
== (int) eright
->sy
);
820 /* clip top/bottom */
822 finish_y
= sy
+ lines
;
834 _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
837 for (y
= start_y
; y
< finish_y
; y
++) {
839 /* avoid accumulating adds as floats don't have the precision to
840 * accurately iterate large triangle edges that way. luckily we
841 * can just multiply these days.
843 * this is all drowned out by the attribute interpolation anyway.
845 int left
= (int)(eleft
->sx
+ y
* eleft
->dxdy
);
846 int right
= (int)(eright
->sx
+ y
* eright
->dxdy
);
848 /* clip left/right */
856 if (block(_y
) != setup
.span
.y
) {
858 setup
.span
.y
= block(_y
);
861 setup
.span
.left
[_y
&1] = left
;
862 setup
.span
.right
[_y
&1] = right
;
863 setup
.span
.y_flags
|= 1<<(_y
&1);
868 /* save the values so that emaj can be restarted:
870 eleft
->sx
+= lines
* eleft
->dxdy
;
871 eright
->sx
+= lines
* eright
->dxdy
;
878 * Draw triangle into tile at (tx, ty) (tile coords)
879 * The tile data should have already been fetched.
882 tri_draw(const float *v0
, const float *v1
, const float *v2
, uint tx
, uint ty
)
887 /* set clipping bounds to tile bounds */
888 setup
.cliprect_minx
= tx
* TILE_SIZE
;
889 setup
.cliprect_miny
= ty
* TILE_SIZE
;
890 setup
.cliprect_maxx
= (tx
+ 1) * TILE_SIZE
;
891 setup
.cliprect_maxy
= (ty
+ 1) * TILE_SIZE
;
893 if (!setup_sort_vertices((struct vertex_header
*) v0
,
894 (struct vertex_header
*) v1
,
895 (struct vertex_header
*) v2
)) {
896 return FALSE
; /* totally clipped */
899 setup_tri_coefficients();
903 setup
.span
.y_flags
= 0;
904 setup
.span
.right
[0] = 0;
905 setup
.span
.right
[1] = 0;
906 /* setup.span.z_mode = tri_z_mode( setup.ctx ); */
908 /* init_constant_attribs( setup ); */
910 if (setup
.oneoverarea
< 0.0) {
913 subtriangle( &setup
.emaj
, &setup
.ebot
, setup
.ebot
.lines
);
914 subtriangle( &setup
.emaj
, &setup
.etop
, setup
.etop
.lines
);
919 subtriangle( &setup
.ebot
, &setup
.emaj
, setup
.ebot
.lines
);
920 subtriangle( &setup
.etop
, &setup
.emaj
, setup
.etop
.lines
);