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 * \brief Primitive rasterization/rendering (points, lines, triangles)
31 * \author Keith Whitwell <keith@tungstengraphics.com>
35 #include "sp_context.h"
37 #include "sp_quad_pipe.h"
40 #include "draw/draw_context.h"
41 #include "draw/draw_vertex.h"
42 #include "pipe/p_shader_tokens.h"
43 #include "util/u_math.h"
44 #include "util/u_memory.h"
55 float dx
; /**< X(v1) - X(v0), used only during setup */
56 float dy
; /**< Y(v1) - Y(v0), used only during setup */
57 float dxdy
; /**< dx/dy */
58 float sx
, sy
; /**< first sample point coord */
59 int lines
; /**< number of lines on this edge */
64 * Max number of quads (2x2 pixel blocks) to process per batch.
65 * This can't be arbitrarily increased since we depend on some 32-bit
66 * bitmasks (two bits per quad).
72 * Triangle setup info.
73 * Also used for line drawing (taking some liberties).
75 struct setup_context
{
76 struct softpipe_context
*softpipe
;
78 /* Vertices are just an array of floats making up each attribute in
79 * turn. Currently fixed at 4 floats, but should change in time.
80 * Codegen will help cope with this.
82 const float (*vmax
)[4];
83 const float (*vmid
)[4];
84 const float (*vmin
)[4];
85 const float (*vprovoke
)[4];
96 struct quad_header quad
[MAX_QUADS
];
97 struct quad_header
*quad_ptrs
[MAX_QUADS
];
100 struct tgsi_interp_coef coef
[PIPE_MAX_SHADER_INPUTS
];
101 struct tgsi_interp_coef posCoef
; /* For Z, W */
104 int left
[2]; /**< [0] = row0, [1] = row1 */
110 uint numFragsEmitted
; /**< per primitive */
111 uint numFragsWritten
; /**< per primitive */
114 unsigned winding
; /* which winding to cull */
115 unsigned nr_vertex_attrs
;
122 * Do triangle cull test using tri determinant (sign indicates orientation)
123 * \return true if triangle is to be culled.
125 static INLINE boolean
126 cull_tri(const struct setup_context
*setup
, float det
)
129 /* if (det < 0 then Z points toward camera and triangle is
130 * counter-clockwise winding.
132 unsigned winding
= (det
< 0) ? PIPE_WINDING_CCW
: PIPE_WINDING_CW
;
134 if ((winding
& setup
->winding
) == 0)
146 * Clip setup->quad against the scissor/surface bounds.
149 quad_clip(struct setup_context
*setup
, struct quad_header
*quad
)
151 const struct pipe_scissor_state
*cliprect
= &setup
->softpipe
->cliprect
;
152 const int minx
= (int) cliprect
->minx
;
153 const int maxx
= (int) cliprect
->maxx
;
154 const int miny
= (int) cliprect
->miny
;
155 const int maxy
= (int) cliprect
->maxy
;
157 if (quad
->input
.x0
>= maxx
||
158 quad
->input
.y0
>= maxy
||
159 quad
->input
.x0
+ 1 < minx
||
160 quad
->input
.y0
+ 1 < miny
) {
161 /* totally clipped */
162 quad
->inout
.mask
= 0x0;
165 if (quad
->input
.x0
< minx
)
166 quad
->inout
.mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
167 if (quad
->input
.y0
< miny
)
168 quad
->inout
.mask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
169 if (quad
->input
.x0
== maxx
- 1)
170 quad
->inout
.mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
171 if (quad
->input
.y0
== maxy
- 1)
172 quad
->inout
.mask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
177 * Emit a quad (pass to next stage) with clipping.
180 clip_emit_quad(struct setup_context
*setup
, struct quad_header
*quad
)
182 quad_clip( setup
, quad
);
184 if (quad
->inout
.mask
) {
185 struct softpipe_context
*sp
= setup
->softpipe
;
187 sp
->quad
.first
->run( sp
->quad
.first
, &quad
, 1 );
194 * Given an X or Y coordinate, return the block/quad coordinate that it
212 * Render a horizontal span of quads
215 flush_spans(struct setup_context
*setup
)
217 const int step
= MAX_QUADS
;
218 const int xleft0
= setup
->span
.left
[0];
219 const int xleft1
= setup
->span
.left
[1];
220 const int xright0
= setup
->span
.right
[0];
221 const int xright1
= setup
->span
.right
[1];
222 struct quad_stage
*pipe
= setup
->softpipe
->quad
.first
;
224 const int minleft
= block_x(MIN2(xleft0
, xleft1
));
225 const int maxright
= MAX2(xright0
, xright1
);
228 /* process quads in horizontal chunks of 16 */
229 for (x
= minleft
; x
< maxright
; x
+= step
) {
230 unsigned skip_left0
= CLAMP(xleft0
- x
, 0, step
);
231 unsigned skip_left1
= CLAMP(xleft1
- x
, 0, step
);
232 unsigned skip_right0
= CLAMP(x
+ step
- xright0
, 0, step
);
233 unsigned skip_right1
= CLAMP(x
+ step
- xright1
, 0, step
);
237 unsigned skipmask_left0
= (1U << skip_left0
) - 1U;
238 unsigned skipmask_left1
= (1U << skip_left1
) - 1U;
240 /* These calculations fail when step == 32 and skip_right == 0.
242 unsigned skipmask_right0
= ~0U << (unsigned)(step
- skip_right0
);
243 unsigned skipmask_right1
= ~0U << (unsigned)(step
- skip_right1
);
245 unsigned mask0
= ~skipmask_left0
& ~skipmask_right0
;
246 unsigned mask1
= ~skipmask_left1
& ~skipmask_right1
;
250 unsigned quadmask
= (mask0
& 3) | ((mask1
& 3) << 2);
252 setup
->quad
[q
].input
.x0
= lx
;
253 setup
->quad
[q
].input
.y0
= setup
->span
.y
;
254 setup
->quad
[q
].input
.facing
= setup
->facing
;
255 setup
->quad
[q
].inout
.mask
= quadmask
;
256 setup
->quad_ptrs
[q
] = &setup
->quad
[q
];
262 } while (mask0
| mask1
);
264 pipe
->run( pipe
, setup
->quad_ptrs
, q
);
270 setup
->span
.right
[0] = 0;
271 setup
->span
.right
[1] = 0;
272 setup
->span
.left
[0] = 1000000; /* greater than right[0] */
273 setup
->span
.left
[1] = 1000000; /* greater than right[1] */
279 print_vertex(const struct setup_context
*setup
,
283 debug_printf(" Vertex: (%p)\n", (void *) v
);
284 for (i
= 0; i
< setup
->nr_vertex_attrs
; i
++) {
285 debug_printf(" %d: %f %f %f %f\n", i
,
286 v
[i
][0], v
[i
][1], v
[i
][2], v
[i
][3]);
287 if (util_is_inf_or_nan(v
[i
][0])) {
288 debug_printf(" NaN!\n");
296 * Sort the vertices from top to bottom order, setting up the triangle
297 * edge fields (ebot, emaj, etop).
298 * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
301 setup_sort_vertices(struct setup_context
*setup
,
303 const float (*v0
)[4],
304 const float (*v1
)[4],
305 const float (*v2
)[4])
307 setup
->vprovoke
= v2
;
309 /* determine bottom to top order of vertices */
356 setup
->ebot
.dx
= setup
->vmid
[0][0] - setup
->vmin
[0][0];
357 setup
->ebot
.dy
= setup
->vmid
[0][1] - setup
->vmin
[0][1];
358 setup
->emaj
.dx
= setup
->vmax
[0][0] - setup
->vmin
[0][0];
359 setup
->emaj
.dy
= setup
->vmax
[0][1] - setup
->vmin
[0][1];
360 setup
->etop
.dx
= setup
->vmax
[0][0] - setup
->vmid
[0][0];
361 setup
->etop
.dy
= setup
->vmax
[0][1] - setup
->vmid
[0][1];
364 * Compute triangle's area. Use 1/area to compute partial
365 * derivatives of attributes later.
367 * The area will be the same as prim->det, but the sign may be
368 * different depending on how the vertices get sorted above.
370 * To determine whether the primitive is front or back facing we
371 * use the prim->det value because its sign is correct.
374 const float area
= (setup
->emaj
.dx
* setup
->ebot
.dy
-
375 setup
->ebot
.dx
* setup
->emaj
.dy
);
377 setup
->oneoverarea
= 1.0f
/ area
;
380 debug_printf("%s one-over-area %f area %f det %f\n",
381 __FUNCTION__, setup->oneoverarea, area, det );
383 if (util_is_inf_or_nan(setup
->oneoverarea
))
387 /* We need to know if this is a front or back-facing triangle for:
388 * - the GLSL gl_FrontFacing fragment attribute (bool)
389 * - two-sided stencil test
393 (setup
->softpipe
->rasterizer
->front_winding
== PIPE_WINDING_CW
));
395 /* Prepare pixel offset for rasterisation:
396 * - pixel center (0.5, 0.5) for GL, or
397 * - assume (0.0, 0.0) for other APIs.
399 if (setup
->softpipe
->rasterizer
->gl_rasterization_rules
) {
400 setup
->pixel_offset
= 0.5f
;
402 setup
->pixel_offset
= 0.0f
;
409 /* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
410 * Input coordinates must be in [0, 1] range, otherwise results are undefined.
411 * Some combinations of coordinates produce invalid results,
412 * but this behaviour is acceptable.
415 tri_apply_cylindrical_wrap(float v0
,
418 uint cylindrical_wrap
,
421 if (cylindrical_wrap
) {
428 else if (delta
< -0.5f
) {
436 else if (delta
< -0.5f
) {
444 else if (delta
< -0.5f
) {
456 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
457 * The value value comes from vertex[slot][i].
458 * The result will be put into setup->coef[slot].a0[i].
459 * \param slot which attribute slot
460 * \param i which component of the slot (0..3)
463 const_coeff(struct setup_context
*setup
,
464 struct tgsi_interp_coef
*coef
,
465 uint vertSlot
, uint i
)
472 /* need provoking vertex info!
474 coef
->a0
[i
] = setup
->vprovoke
[vertSlot
][i
];
479 * Compute a0, dadx and dady for a linearly interpolated coefficient,
481 * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
484 tri_linear_coeff(struct setup_context
*setup
,
485 struct tgsi_interp_coef
*coef
,
489 float botda
= v
[1] - v
[0];
490 float majda
= v
[2] - v
[0];
491 float a
= setup
->ebot
.dy
* majda
- botda
* setup
->emaj
.dy
;
492 float b
= setup
->emaj
.dx
* botda
- majda
* setup
->ebot
.dx
;
493 float dadx
= a
* setup
->oneoverarea
;
494 float dady
= b
* setup
->oneoverarea
;
498 coef
->dadx
[i
] = dadx
;
499 coef
->dady
[i
] = dady
;
501 /* calculate a0 as the value which would be sampled for the
502 * fragment at (0,0), taking into account that we want to sample at
503 * pixel centers, in other words (pixel_offset, pixel_offset).
505 * this is neat but unfortunately not a good way to do things for
506 * triangles with very large values of dadx or dady as it will
507 * result in the subtraction and re-addition from a0 of a very
508 * large number, which means we'll end up loosing a lot of the
509 * fractional bits and precision from a0. the way to fix this is
510 * to define a0 as the sample at a pixel center somewhere near vmin
511 * instead - i'll switch to this later.
513 coef
->a0
[i
] = (v
[0] -
514 (dadx
* (setup
->vmin
[0][0] - setup
->pixel_offset
) +
515 dady
* (setup
->vmin
[0][1] - setup
->pixel_offset
)));
518 debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
520 setup->coef[slot].a0[i],
521 setup->coef[slot].dadx[i],
522 setup->coef[slot].dady[i]);
528 * Compute a0, dadx and dady for a perspective-corrected interpolant,
530 * We basically multiply the vertex value by 1/w before computing
531 * the plane coefficients (a0, dadx, dady).
532 * Later, when we compute the value at a particular fragment position we'll
533 * divide the interpolated value by the interpolated W at that fragment.
534 * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
537 tri_persp_coeff(struct setup_context
*setup
,
538 struct tgsi_interp_coef
*coef
,
542 /* premultiply by 1/w (v[0][3] is always W):
544 float mina
= v
[0] * setup
->vmin
[0][3];
545 float mida
= v
[1] * setup
->vmid
[0][3];
546 float maxa
= v
[2] * setup
->vmax
[0][3];
547 float botda
= mida
- mina
;
548 float majda
= maxa
- mina
;
549 float a
= setup
->ebot
.dy
* majda
- botda
* setup
->emaj
.dy
;
550 float b
= setup
->emaj
.dx
* botda
- majda
* setup
->ebot
.dx
;
551 float dadx
= a
* setup
->oneoverarea
;
552 float dady
= b
* setup
->oneoverarea
;
555 debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
556 setup->vmin[vertSlot][i],
557 setup->vmid[vertSlot][i],
558 setup->vmax[vertSlot][i]
563 coef
->dadx
[i
] = dadx
;
564 coef
->dady
[i
] = dady
;
565 coef
->a0
[i
] = (mina
-
566 (dadx
* (setup
->vmin
[0][0] - setup
->pixel_offset
) +
567 dady
* (setup
->vmin
[0][1] - setup
->pixel_offset
)));
572 * Special coefficient setup for gl_FragCoord.
573 * X and Y are trivial, though Y may have to be inverted for OpenGL.
574 * Z and W are copied from posCoef which should have already been computed.
575 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
578 setup_fragcoord_coeff(struct setup_context
*setup
, uint slot
)
580 struct sp_fragment_shader
* spfs
= setup
->softpipe
->fs
;
582 setup
->coef
[slot
].a0
[0] = spfs
->pixel_center_integer
? 0.0 : 0.5;
583 setup
->coef
[slot
].dadx
[0] = 1.0;
584 setup
->coef
[slot
].dady
[0] = 0.0;
586 setup
->coef
[slot
].a0
[1] =
587 (spfs
->origin_lower_left
? setup
->softpipe
->framebuffer
.height
: 0)
588 + (spfs
->pixel_center_integer
? 0.0 : 0.5);
589 setup
->coef
[slot
].dadx
[1] = 0.0;
590 setup
->coef
[slot
].dady
[1] = spfs
->origin_lower_left
? -1.0 : 1.0;
592 setup
->coef
[slot
].a0
[2] = setup
->posCoef
.a0
[2];
593 setup
->coef
[slot
].dadx
[2] = setup
->posCoef
.dadx
[2];
594 setup
->coef
[slot
].dady
[2] = setup
->posCoef
.dady
[2];
596 setup
->coef
[slot
].a0
[3] = setup
->posCoef
.a0
[3];
597 setup
->coef
[slot
].dadx
[3] = setup
->posCoef
.dadx
[3];
598 setup
->coef
[slot
].dady
[3] = setup
->posCoef
.dady
[3];
604 * Compute the setup->coef[] array dadx, dady, a0 values.
605 * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
608 setup_tri_coefficients(struct setup_context
*setup
)
610 struct softpipe_context
*softpipe
= setup
->softpipe
;
611 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
612 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
616 /* z and w are done by linear interpolation:
618 v
[0] = setup
->vmin
[0][2];
619 v
[1] = setup
->vmid
[0][2];
620 v
[2] = setup
->vmax
[0][2];
621 tri_linear_coeff(setup
, &setup
->posCoef
, 2, v
);
623 v
[0] = setup
->vmin
[0][3];
624 v
[1] = setup
->vmid
[0][3];
625 v
[2] = setup
->vmax
[0][3];
626 tri_linear_coeff(setup
, &setup
->posCoef
, 3, v
);
628 /* setup interpolation for all the remaining attributes:
630 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
631 const uint vertSlot
= vinfo
->attrib
[fragSlot
].src_index
;
634 switch (vinfo
->attrib
[fragSlot
].interp_mode
) {
635 case INTERP_CONSTANT
:
636 for (j
= 0; j
< NUM_CHANNELS
; j
++)
637 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
640 for (j
= 0; j
< NUM_CHANNELS
; j
++) {
641 tri_apply_cylindrical_wrap(setup
->vmin
[vertSlot
][j
],
642 setup
->vmid
[vertSlot
][j
],
643 setup
->vmax
[vertSlot
][j
],
644 spfs
->info
.input_cylindrical_wrap
[fragSlot
] & (1 << j
),
646 tri_linear_coeff(setup
, &setup
->coef
[fragSlot
], j
, v
);
649 case INTERP_PERSPECTIVE
:
650 for (j
= 0; j
< NUM_CHANNELS
; j
++) {
651 tri_apply_cylindrical_wrap(setup
->vmin
[vertSlot
][j
],
652 setup
->vmid
[vertSlot
][j
],
653 setup
->vmax
[vertSlot
][j
],
654 spfs
->info
.input_cylindrical_wrap
[fragSlot
] & (1 << j
),
656 tri_persp_coeff(setup
, &setup
->coef
[fragSlot
], j
, v
);
660 setup_fragcoord_coeff(setup
, fragSlot
);
666 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FACE
) {
667 setup
->coef
[fragSlot
].a0
[0] = 1.0f
- setup
->facing
;
668 setup
->coef
[fragSlot
].dadx
[0] = 0.0;
669 setup
->coef
[fragSlot
].dady
[0] = 0.0;
676 setup_tri_edges(struct setup_context
*setup
)
678 float vmin_x
= setup
->vmin
[0][0] + setup
->pixel_offset
;
679 float vmid_x
= setup
->vmid
[0][0] + setup
->pixel_offset
;
681 float vmin_y
= setup
->vmin
[0][1] - setup
->pixel_offset
;
682 float vmid_y
= setup
->vmid
[0][1] - setup
->pixel_offset
;
683 float vmax_y
= setup
->vmax
[0][1] - setup
->pixel_offset
;
685 setup
->emaj
.sy
= ceilf(vmin_y
);
686 setup
->emaj
.lines
= (int) ceilf(vmax_y
- setup
->emaj
.sy
);
687 setup
->emaj
.dxdy
= setup
->emaj
.dx
/ setup
->emaj
.dy
;
688 setup
->emaj
.sx
= vmin_x
+ (setup
->emaj
.sy
- vmin_y
) * setup
->emaj
.dxdy
;
690 setup
->etop
.sy
= ceilf(vmid_y
);
691 setup
->etop
.lines
= (int) ceilf(vmax_y
- setup
->etop
.sy
);
692 setup
->etop
.dxdy
= setup
->etop
.dx
/ setup
->etop
.dy
;
693 setup
->etop
.sx
= vmid_x
+ (setup
->etop
.sy
- vmid_y
) * setup
->etop
.dxdy
;
695 setup
->ebot
.sy
= ceilf(vmin_y
);
696 setup
->ebot
.lines
= (int) ceilf(vmid_y
- setup
->ebot
.sy
);
697 setup
->ebot
.dxdy
= setup
->ebot
.dx
/ setup
->ebot
.dy
;
698 setup
->ebot
.sx
= vmin_x
+ (setup
->ebot
.sy
- vmin_y
) * setup
->ebot
.dxdy
;
703 * Render the upper or lower half of a triangle.
704 * Scissoring/cliprect is applied here too.
707 subtriangle(struct setup_context
*setup
,
712 const struct pipe_scissor_state
*cliprect
= &setup
->softpipe
->cliprect
;
713 const int minx
= (int) cliprect
->minx
;
714 const int maxx
= (int) cliprect
->maxx
;
715 const int miny
= (int) cliprect
->miny
;
716 const int maxy
= (int) cliprect
->maxy
;
717 int y
, start_y
, finish_y
;
718 int sy
= (int)eleft
->sy
;
720 assert((int)eleft
->sy
== (int) eright
->sy
);
723 /* clip top/bottom */
728 finish_y
= sy
+ lines
;
736 debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
739 for (y
= start_y
; y
< finish_y
; y
++) {
741 /* avoid accumulating adds as floats don't have the precision to
742 * accurately iterate large triangle edges that way. luckily we
743 * can just multiply these days.
745 * this is all drowned out by the attribute interpolation anyway.
747 int left
= (int)(eleft
->sx
+ y
* eleft
->dxdy
);
748 int right
= (int)(eright
->sx
+ y
* eright
->dxdy
);
750 /* clip left/right */
758 if (block(_y
) != setup
->span
.y
) {
760 setup
->span
.y
= block(_y
);
763 setup
->span
.left
[_y
&1] = left
;
764 setup
->span
.right
[_y
&1] = right
;
769 /* save the values so that emaj can be restarted:
771 eleft
->sx
+= lines
* eleft
->dxdy
;
772 eright
->sx
+= lines
* eright
->dxdy
;
779 * Recalculate prim's determinant. This is needed as we don't have
780 * get this information through the vbuf_render interface & we must
784 calc_det(const float (*v0
)[4],
785 const float (*v1
)[4],
786 const float (*v2
)[4])
788 /* edge vectors e = v0 - v2, f = v1 - v2 */
789 const float ex
= v0
[0][0] - v2
[0][0];
790 const float ey
= v0
[0][1] - v2
[0][1];
791 const float fx
= v1
[0][0] - v2
[0][0];
792 const float fy
= v1
[0][1] - v2
[0][1];
794 /* det = cross(e,f).z */
795 return ex
* fy
- ey
* fx
;
800 * Do setup for triangle rasterization, then render the triangle.
803 sp_setup_tri(struct setup_context
*setup
,
804 const float (*v0
)[4],
805 const float (*v1
)[4],
806 const float (*v2
)[4])
811 debug_printf("Setup triangle:\n");
812 print_vertex(setup
, v0
);
813 print_vertex(setup
, v1
);
814 print_vertex(setup
, v2
);
817 if (setup
->softpipe
->no_rast
)
820 det
= calc_det(v0
, v1
, v2
);
822 debug_printf("%s\n", __FUNCTION__ );
826 setup
->numFragsEmitted
= 0;
827 setup
->numFragsWritten
= 0;
830 if (cull_tri( setup
, det
))
833 if (!setup_sort_vertices( setup
, det
, v0
, v1
, v2
))
835 setup_tri_coefficients( setup
);
836 setup_tri_edges( setup
);
838 assert(setup
->softpipe
->reduced_prim
== PIPE_PRIM_TRIANGLES
);
841 setup
->span
.right
[0] = 0;
842 setup
->span
.right
[1] = 0;
843 /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
845 /* init_constant_attribs( setup ); */
847 if (setup
->oneoverarea
< 0.0) {
850 subtriangle( setup
, &setup
->emaj
, &setup
->ebot
, setup
->ebot
.lines
);
851 subtriangle( setup
, &setup
->emaj
, &setup
->etop
, setup
->etop
.lines
);
856 subtriangle( setup
, &setup
->ebot
, &setup
->emaj
, setup
->ebot
.lines
);
857 subtriangle( setup
, &setup
->etop
, &setup
->emaj
, setup
->etop
.lines
);
860 flush_spans( setup
);
863 printf("Tri: %u frags emitted, %u written\n",
864 setup
->numFragsEmitted
,
865 setup
->numFragsWritten
);
870 /* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
871 * Input coordinates must be in [0, 1] range, otherwise results are undefined.
874 line_apply_cylindrical_wrap(float v0
,
876 uint cylindrical_wrap
,
879 if (cylindrical_wrap
) {
886 else if (delta
< -0.5f
) {
897 * Compute a0, dadx and dady for a linearly interpolated coefficient,
899 * v[0] and v[1] are vmin and vmax, respectively.
902 line_linear_coeff(const struct setup_context
*setup
,
903 struct tgsi_interp_coef
*coef
,
907 const float da
= v
[1] - v
[0];
908 const float dadx
= da
* setup
->emaj
.dx
* setup
->oneoverarea
;
909 const float dady
= da
* setup
->emaj
.dy
* setup
->oneoverarea
;
910 coef
->dadx
[i
] = dadx
;
911 coef
->dady
[i
] = dady
;
912 coef
->a0
[i
] = (v
[0] -
913 (dadx
* (setup
->vmin
[0][0] - setup
->pixel_offset
) +
914 dady
* (setup
->vmin
[0][1] - setup
->pixel_offset
)));
919 * Compute a0, dadx and dady for a perspective-corrected interpolant,
921 * v[0] and v[1] are vmin and vmax, respectively.
924 line_persp_coeff(const struct setup_context
*setup
,
925 struct tgsi_interp_coef
*coef
,
929 const float a0
= v
[0] * setup
->vmin
[0][3];
930 const float a1
= v
[1] * setup
->vmax
[0][3];
931 const float da
= a1
- a0
;
932 const float dadx
= da
* setup
->emaj
.dx
* setup
->oneoverarea
;
933 const float dady
= da
* setup
->emaj
.dy
* setup
->oneoverarea
;
934 coef
->dadx
[i
] = dadx
;
935 coef
->dady
[i
] = dady
;
937 (dadx
* (setup
->vmin
[0][0] - setup
->pixel_offset
) +
938 dady
* (setup
->vmin
[0][1] - setup
->pixel_offset
)));
943 * Compute the setup->coef[] array dadx, dady, a0 values.
944 * Must be called after setup->vmin,vmax are initialized.
947 setup_line_coefficients(struct setup_context
*setup
,
948 const float (*v0
)[4],
949 const float (*v1
)[4])
951 struct softpipe_context
*softpipe
= setup
->softpipe
;
952 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
953 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
958 /* use setup->vmin, vmax to point to vertices */
959 if (softpipe
->rasterizer
->flatshade_first
)
960 setup
->vprovoke
= v0
;
962 setup
->vprovoke
= v1
;
966 setup
->emaj
.dx
= setup
->vmax
[0][0] - setup
->vmin
[0][0];
967 setup
->emaj
.dy
= setup
->vmax
[0][1] - setup
->vmin
[0][1];
969 /* NOTE: this is not really area but something proportional to it */
970 area
= setup
->emaj
.dx
* setup
->emaj
.dx
+ setup
->emaj
.dy
* setup
->emaj
.dy
;
971 if (area
== 0.0f
|| util_is_inf_or_nan(area
))
973 setup
->oneoverarea
= 1.0f
/ area
;
975 /* z and w are done by linear interpolation:
977 v
[0] = setup
->vmin
[0][2];
978 v
[1] = setup
->vmax
[0][2];
979 line_linear_coeff(setup
, &setup
->posCoef
, 2, v
);
981 v
[0] = setup
->vmin
[0][3];
982 v
[1] = setup
->vmax
[0][3];
983 line_linear_coeff(setup
, &setup
->posCoef
, 3, v
);
985 /* setup interpolation for all the remaining attributes:
987 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
988 const uint vertSlot
= vinfo
->attrib
[fragSlot
].src_index
;
991 switch (vinfo
->attrib
[fragSlot
].interp_mode
) {
992 case INTERP_CONSTANT
:
993 for (j
= 0; j
< NUM_CHANNELS
; j
++)
994 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
997 for (j
= 0; j
< NUM_CHANNELS
; j
++) {
998 line_apply_cylindrical_wrap(setup
->vmin
[vertSlot
][j
],
999 setup
->vmax
[vertSlot
][j
],
1000 spfs
->info
.input_cylindrical_wrap
[fragSlot
] & (1 << j
),
1002 line_linear_coeff(setup
, &setup
->coef
[fragSlot
], j
, v
);
1005 case INTERP_PERSPECTIVE
:
1006 for (j
= 0; j
< NUM_CHANNELS
; j
++) {
1007 line_apply_cylindrical_wrap(setup
->vmin
[vertSlot
][j
],
1008 setup
->vmax
[vertSlot
][j
],
1009 spfs
->info
.input_cylindrical_wrap
[fragSlot
] & (1 << j
),
1011 line_persp_coeff(setup
, &setup
->coef
[fragSlot
], j
, v
);
1015 setup_fragcoord_coeff(setup
, fragSlot
);
1021 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FACE
) {
1022 setup
->coef
[fragSlot
].a0
[0] = 1.0f
- setup
->facing
;
1023 setup
->coef
[fragSlot
].dadx
[0] = 0.0;
1024 setup
->coef
[fragSlot
].dady
[0] = 0.0;
1032 * Plot a pixel in a line segment.
1035 plot(struct setup_context
*setup
, int x
, int y
)
1037 const int iy
= y
& 1;
1038 const int ix
= x
& 1;
1039 const int quadX
= x
- ix
;
1040 const int quadY
= y
- iy
;
1041 const int mask
= (1 << ix
) << (2 * iy
);
1043 if (quadX
!= setup
->quad
[0].input
.x0
||
1044 quadY
!= setup
->quad
[0].input
.y0
)
1046 /* flush prev quad, start new quad */
1048 if (setup
->quad
[0].input
.x0
!= -1)
1049 clip_emit_quad( setup
, &setup
->quad
[0] );
1051 setup
->quad
[0].input
.x0
= quadX
;
1052 setup
->quad
[0].input
.y0
= quadY
;
1053 setup
->quad
[0].inout
.mask
= 0x0;
1056 setup
->quad
[0].inout
.mask
|= mask
;
1061 * Do setup for line rasterization, then render the line.
1062 * Single-pixel width, no stipple, etc. We rely on the 'draw' module
1063 * to handle stippling and wide lines.
1066 sp_setup_line(struct setup_context
*setup
,
1067 const float (*v0
)[4],
1068 const float (*v1
)[4])
1070 int x0
= (int) v0
[0][0];
1071 int x1
= (int) v1
[0][0];
1072 int y0
= (int) v0
[0][1];
1073 int y1
= (int) v1
[0][1];
1079 debug_printf("Setup line:\n");
1080 print_vertex(setup
, v0
);
1081 print_vertex(setup
, v1
);
1084 if (setup
->softpipe
->no_rast
)
1087 if (dx
== 0 && dy
== 0)
1090 if (!setup_line_coefficients(setup
, v0
, v1
))
1093 assert(v0
[0][0] < 1.0e9
);
1094 assert(v0
[0][1] < 1.0e9
);
1095 assert(v1
[0][0] < 1.0e9
);
1096 assert(v1
[0][1] < 1.0e9
);
1099 dx
= -dx
; /* make positive */
1107 dy
= -dy
; /* make positive */
1116 assert(setup
->softpipe
->reduced_prim
== PIPE_PRIM_LINES
);
1118 setup
->quad
[0].input
.x0
= setup
->quad
[0].input
.y0
= -1;
1119 setup
->quad
[0].inout
.mask
= 0x0;
1121 /* XXX temporary: set coverage to 1.0 so the line appears
1122 * if AA mode happens to be enabled.
1124 setup
->quad
[0].input
.coverage
[0] =
1125 setup
->quad
[0].input
.coverage
[1] =
1126 setup
->quad
[0].input
.coverage
[2] =
1127 setup
->quad
[0].input
.coverage
[3] = 1.0;
1130 /*** X-major line ***/
1132 const int errorInc
= dy
+ dy
;
1133 int error
= errorInc
- dx
;
1134 const int errorDec
= error
- dx
;
1136 for (i
= 0; i
< dx
; i
++) {
1137 plot(setup
, x0
, y0
);
1150 /*** Y-major line ***/
1152 const int errorInc
= dx
+ dx
;
1153 int error
= errorInc
- dy
;
1154 const int errorDec
= error
- dy
;
1156 for (i
= 0; i
< dy
; i
++) {
1157 plot(setup
, x0
, y0
);
1170 /* draw final quad */
1171 if (setup
->quad
[0].inout
.mask
) {
1172 clip_emit_quad( setup
, &setup
->quad
[0] );
1178 point_persp_coeff(const struct setup_context
*setup
,
1179 const float (*vert
)[4],
1180 struct tgsi_interp_coef
*coef
,
1181 uint vertSlot
, uint i
)
1184 coef
->dadx
[i
] = 0.0F
;
1185 coef
->dady
[i
] = 0.0F
;
1186 coef
->a0
[i
] = vert
[vertSlot
][i
] * vert
[0][3];
1191 * Do setup for point rasterization, then render the point.
1192 * Round or square points...
1193 * XXX could optimize a lot for 1-pixel points.
1196 sp_setup_point(struct setup_context
*setup
,
1197 const float (*v0
)[4])
1199 struct softpipe_context
*softpipe
= setup
->softpipe
;
1200 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
1201 const int sizeAttr
= setup
->softpipe
->psize_slot
;
1203 = sizeAttr
> 0 ? v0
[sizeAttr
][0]
1204 : setup
->softpipe
->rasterizer
->point_size
;
1205 const float halfSize
= 0.5F
* size
;
1206 const boolean round
= (boolean
) setup
->softpipe
->rasterizer
->point_smooth
;
1207 const float x
= v0
[0][0]; /* Note: data[0] is always position */
1208 const float y
= v0
[0][1];
1209 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
1213 debug_printf("Setup point:\n");
1214 print_vertex(setup
, v0
);
1217 if (softpipe
->no_rast
)
1220 assert(setup
->softpipe
->reduced_prim
== PIPE_PRIM_POINTS
);
1222 /* For points, all interpolants are constant-valued.
1223 * However, for point sprites, we'll need to setup texcoords appropriately.
1224 * XXX: which coefficients are the texcoords???
1225 * We may do point sprites as textured quads...
1227 * KW: We don't know which coefficients are texcoords - ultimately
1228 * the choice of what interpolation mode to use for each attribute
1229 * should be determined by the fragment program, using
1230 * per-attribute declaration statements that include interpolation
1231 * mode as a parameter. So either the fragment program will have
1232 * to be adjusted for pointsprite vs normal point behaviour, or
1233 * otherwise a special interpolation mode will have to be defined
1234 * which matches the required behaviour for point sprites. But -
1235 * the latter is not a feature of normal hardware, and as such
1236 * probably should be ruled out on that basis.
1238 setup
->vprovoke
= v0
;
1241 const_coeff(setup
, &setup
->posCoef
, 0, 2);
1242 const_coeff(setup
, &setup
->posCoef
, 0, 3);
1244 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
1245 const uint vertSlot
= vinfo
->attrib
[fragSlot
].src_index
;
1248 switch (vinfo
->attrib
[fragSlot
].interp_mode
) {
1249 case INTERP_CONSTANT
:
1252 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1253 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
1255 case INTERP_PERSPECTIVE
:
1256 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1257 point_persp_coeff(setup
, setup
->vprovoke
,
1258 &setup
->coef
[fragSlot
], vertSlot
, j
);
1261 setup_fragcoord_coeff(setup
, fragSlot
);
1267 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FACE
) {
1268 setup
->coef
[fragSlot
].a0
[0] = 1.0f
- setup
->facing
;
1269 setup
->coef
[fragSlot
].dadx
[0] = 0.0;
1270 setup
->coef
[fragSlot
].dady
[0] = 0.0;
1275 if (halfSize
<= 0.5 && !round
) {
1276 /* special case for 1-pixel points */
1277 const int ix
= ((int) x
) & 1;
1278 const int iy
= ((int) y
) & 1;
1279 setup
->quad
[0].input
.x0
= (int) x
- ix
;
1280 setup
->quad
[0].input
.y0
= (int) y
- iy
;
1281 setup
->quad
[0].inout
.mask
= (1 << ix
) << (2 * iy
);
1282 clip_emit_quad( setup
, &setup
->quad
[0] );
1286 /* rounded points */
1287 const int ixmin
= block((int) (x
- halfSize
));
1288 const int ixmax
= block((int) (x
+ halfSize
));
1289 const int iymin
= block((int) (y
- halfSize
));
1290 const int iymax
= block((int) (y
+ halfSize
));
1291 const float rmin
= halfSize
- 0.7071F
; /* 0.7071 = sqrt(2)/2 */
1292 const float rmax
= halfSize
+ 0.7071F
;
1293 const float rmin2
= MAX2(0.0F
, rmin
* rmin
);
1294 const float rmax2
= rmax
* rmax
;
1295 const float cscale
= 1.0F
/ (rmax2
- rmin2
);
1298 for (iy
= iymin
; iy
<= iymax
; iy
+= 2) {
1299 for (ix
= ixmin
; ix
<= ixmax
; ix
+= 2) {
1300 float dx
, dy
, dist2
, cover
;
1302 setup
->quad
[0].inout
.mask
= 0x0;
1304 dx
= (ix
+ 0.5f
) - x
;
1305 dy
= (iy
+ 0.5f
) - y
;
1306 dist2
= dx
* dx
+ dy
* dy
;
1307 if (dist2
<= rmax2
) {
1308 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1309 setup
->quad
[0].input
.coverage
[QUAD_TOP_LEFT
] = MIN2(cover
, 1.0f
);
1310 setup
->quad
[0].inout
.mask
|= MASK_TOP_LEFT
;
1313 dx
= (ix
+ 1.5f
) - x
;
1314 dy
= (iy
+ 0.5f
) - y
;
1315 dist2
= dx
* dx
+ dy
* dy
;
1316 if (dist2
<= rmax2
) {
1317 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1318 setup
->quad
[0].input
.coverage
[QUAD_TOP_RIGHT
] = MIN2(cover
, 1.0f
);
1319 setup
->quad
[0].inout
.mask
|= MASK_TOP_RIGHT
;
1322 dx
= (ix
+ 0.5f
) - x
;
1323 dy
= (iy
+ 1.5f
) - y
;
1324 dist2
= dx
* dx
+ dy
* dy
;
1325 if (dist2
<= rmax2
) {
1326 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1327 setup
->quad
[0].input
.coverage
[QUAD_BOTTOM_LEFT
] = MIN2(cover
, 1.0f
);
1328 setup
->quad
[0].inout
.mask
|= MASK_BOTTOM_LEFT
;
1331 dx
= (ix
+ 1.5f
) - x
;
1332 dy
= (iy
+ 1.5f
) - y
;
1333 dist2
= dx
* dx
+ dy
* dy
;
1334 if (dist2
<= rmax2
) {
1335 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1336 setup
->quad
[0].input
.coverage
[QUAD_BOTTOM_RIGHT
] = MIN2(cover
, 1.0f
);
1337 setup
->quad
[0].inout
.mask
|= MASK_BOTTOM_RIGHT
;
1340 if (setup
->quad
[0].inout
.mask
) {
1341 setup
->quad
[0].input
.x0
= ix
;
1342 setup
->quad
[0].input
.y0
= iy
;
1343 clip_emit_quad( setup
, &setup
->quad
[0] );
1350 const int xmin
= (int) (x
+ 0.75 - halfSize
);
1351 const int ymin
= (int) (y
+ 0.25 - halfSize
);
1352 const int xmax
= xmin
+ (int) size
;
1353 const int ymax
= ymin
+ (int) size
;
1354 /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
1355 const int ixmin
= block(xmin
);
1356 const int ixmax
= block(xmax
- 1);
1357 const int iymin
= block(ymin
);
1358 const int iymax
= block(ymax
- 1);
1362 debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
1364 for (iy
= iymin
; iy
<= iymax
; iy
+= 2) {
1367 /* above the top edge */
1368 rowMask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
1370 if (iy
+ 1 >= ymax
) {
1371 /* below the bottom edge */
1372 rowMask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
1375 for (ix
= ixmin
; ix
<= ixmax
; ix
+= 2) {
1376 uint mask
= rowMask
;
1379 /* fragment is past left edge of point, turn off left bits */
1380 mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
1382 if (ix
+ 1 >= xmax
) {
1383 /* past the right edge */
1384 mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
1387 setup
->quad
[0].inout
.mask
= mask
;
1388 setup
->quad
[0].input
.x0
= ix
;
1389 setup
->quad
[0].input
.y0
= iy
;
1390 clip_emit_quad( setup
, &setup
->quad
[0] );
1399 * Called by vbuf code just before we start buffering primitives.
1402 sp_setup_prepare(struct setup_context
*setup
)
1404 struct softpipe_context
*sp
= setup
->softpipe
;
1407 softpipe_update_derived(sp
);
1410 /* Note: nr_attrs is only used for debugging (vertex printing) */
1411 setup
->nr_vertex_attrs
= draw_num_shader_outputs(sp
->draw
);
1413 sp
->quad
.first
->begin( sp
->quad
.first
);
1415 if (sp
->reduced_api_prim
== PIPE_PRIM_TRIANGLES
&&
1416 sp
->rasterizer
->fill_cw
== PIPE_POLYGON_MODE_FILL
&&
1417 sp
->rasterizer
->fill_ccw
== PIPE_POLYGON_MODE_FILL
) {
1418 /* we'll do culling */
1419 setup
->winding
= sp
->rasterizer
->cull_mode
;
1422 /* 'draw' will do culling */
1423 setup
->winding
= PIPE_WINDING_NONE
;
1429 sp_setup_destroy_context(struct setup_context
*setup
)
1436 * Create a new primitive setup/render stage.
1438 struct setup_context
*
1439 sp_setup_create_context(struct softpipe_context
*softpipe
)
1441 struct setup_context
*setup
= CALLOC_STRUCT(setup_context
);
1444 setup
->softpipe
= softpipe
;
1446 for (i
= 0; i
< MAX_QUADS
; i
++) {
1447 setup
->quad
[i
].coef
= setup
->coef
;
1448 setup
->quad
[i
].posCoef
= &setup
->posCoef
;
1451 setup
->span
.left
[0] = 1000000; /* greater than right[0] */
1452 setup
->span
.left
[1] = 1000000; /* greater than right[1] */