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>
37 #include "sp_context.h"
38 #include "sp_headers.h"
41 #include "sp_prim_setup.h"
42 #include "draw/draw_context.h"
43 #include "draw/draw_private.h"
44 #include "draw/draw_vertex.h"
45 #include "pipe/p_shader_tokens.h"
46 #include "pipe/p_thread.h"
47 #include "util/u_math.h"
48 #include "util/u_memory.h"
58 float dx
; /**< X(v1) - X(v0), used only during setup */
59 float dy
; /**< Y(v1) - Y(v0), used only during setup */
60 float dxdy
; /**< dx/dy */
61 float sx
, sy
; /**< first sample point coord */
62 int lines
; /**< number of lines on this edge */
65 #if SP_NUM_QUAD_THREADS > 1
69 struct setup_context
*setup
;
76 typedef void (* quad_job_routine
)( struct setup_context
*setup
, uint thread
, struct quad_job
*job
);
82 struct quad_header quad
;
83 quad_job_routine routine
;
86 #define NUM_QUAD_JOBS 64
90 struct quad_job jobs
[NUM_QUAD_JOBS
];
97 add_quad_job( struct quad_job_que
*que
, int x
, int y
, unsigned mask
, struct quad_header
*quad
, quad_job_routine routine
)
99 while ((que
->last
+ 1) % NUM_QUAD_JOBS
== que
->first
)
101 que
->jobs
[que
->last
].x
= x
;
102 que
->jobs
[que
->last
].y
= y
;
103 que
->jobs
[que
->last
].mask
= mask
;
104 que
->jobs
[que
->last
].quad
= *quad
;
105 que
->jobs
[que
->last
].routine
= routine
;
106 que
->last
= (que
->last
+ 1) % NUM_QUAD_JOBS
;
112 * Triangle setup info (derived from draw_stage).
113 * Also used for line drawing (taking some liberties).
115 struct setup_context
{
116 struct softpipe_context
*softpipe
;
118 /* Vertices are just an array of floats making up each attribute in
119 * turn. Currently fixed at 4 floats, but should change in time.
120 * Codegen will help cope with this.
122 const float (*vmax
)[4];
123 const float (*vmid
)[4];
124 const float (*vmin
)[4];
125 const float (*vprovoke
)[4];
133 struct tgsi_interp_coef coef
[PIPE_MAX_SHADER_INPUTS
];
134 struct tgsi_interp_coef posCoef
; /* For Z, W */
135 struct quad_header quad
;
137 #if SP_NUM_QUAD_THREADS > 1
138 struct quad_job_que que
;
139 struct thread_info threads
[SP_NUM_QUAD_THREADS
];
144 int left
[2]; /**< [0] = row0, [1] = row1 */
148 unsigned mask
; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
152 uint numFragsEmitted
; /**< per primitive */
153 uint numFragsWritten
; /**< per primitive */
156 unsigned winding
; /* which winding to cull */
159 #if SP_NUM_QUAD_THREADS > 1
161 static PIPE_THREAD_ROUTINE( quad_thread
, param
)
163 struct thread_info
*info
= (struct thread_info
*) param
;
166 struct quad_job
*job
;
168 while (info
->setup
->que
.last
== info
->setup
->que
.first
)
170 pipe_mutex_lock( info
->setup
->que
.mutex
);
171 job
= &info
->setup
->que
.jobs
[info
->setup
->que
.first
];
172 info
->setup
->que
.first
= (info
->setup
->que
.first
+ 1) % NUM_QUAD_JOBS
;
173 job
->routine( info
->setup
, info
->id
, job
);
174 pipe_mutex_unlock( info
->setup
->que
.mutex
);
178 #define WAIT_FOR_COMPLETION(setup) \
180 while (setup->que.last != setup->que.first)\
186 #define WAIT_FOR_COMPLETION(setup) ((void) 0)
191 * Test if x is NaN or +/- infinity.
193 static INLINE boolean
194 is_inf_or_nan(float x
)
198 return !(int)((unsigned int)((tmp
.i
& 0x7fffffff)-0x7f800000) >> 31);
202 static boolean
cull_tri( struct setup_context
*setup
,
207 /* if (det < 0 then Z points toward camera and triangle is
208 * counter-clockwise winding.
210 unsigned winding
= (det
< 0) ? PIPE_WINDING_CCW
: PIPE_WINDING_CW
;
212 if ((winding
& setup
->winding
) == 0)
224 * Clip setup->quad against the scissor/surface bounds.
227 quad_clip( struct setup_context
*setup
, struct quad_header
*quad
)
229 const struct pipe_scissor_state
*cliprect
= &setup
->softpipe
->cliprect
;
230 const int minx
= (int) cliprect
->minx
;
231 const int maxx
= (int) cliprect
->maxx
;
232 const int miny
= (int) cliprect
->miny
;
233 const int maxy
= (int) cliprect
->maxy
;
235 if (quad
->x0
>= maxx
||
237 quad
->x0
+ 1 < minx
||
238 quad
->y0
+ 1 < miny
) {
239 /* totally clipped */
244 quad
->mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
246 quad
->mask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
247 if (quad
->x0
== maxx
- 1)
248 quad
->mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
249 if (quad
->y0
== maxy
- 1)
250 quad
->mask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
255 * Emit a quad (pass to next stage) with clipping.
258 clip_emit_quad( struct setup_context
*setup
, struct quad_header
*quad
, uint thread
)
260 quad_clip( setup
, quad
);
262 struct softpipe_context
*sp
= setup
->softpipe
;
264 sp
->quad
[thread
].first
->run( sp
->quad
[thread
].first
, quad
);
268 #if SP_NUM_QUAD_THREADS > 1
271 clip_emit_quad_job( struct setup_context
*setup
, uint thread
, struct quad_job
*job
)
273 clip_emit_quad( setup
, &job
->quad
, thread
);
276 #define CLIP_EMIT_QUAD(setup) add_quad_job( &setup->que, 0, 0, 0, &setup->quad, clip_emit_quad_job )
280 #define CLIP_EMIT_QUAD(setup) clip_emit_quad( setup, &setup->quad, 0 )
285 * Emit a quad (pass to next stage). No clipping is done.
288 emit_quad( struct setup_context
*setup
, int x
, int y
, unsigned mask
, struct quad_header
*quad
, uint thread
)
290 struct softpipe_context
*sp
= setup
->softpipe
;
296 if (mask
& 1) setup
->numFragsEmitted
++;
297 if (mask
& 2) setup
->numFragsEmitted
++;
298 if (mask
& 4) setup
->numFragsEmitted
++;
299 if (mask
& 8) setup
->numFragsEmitted
++;
301 sp
->quad
[thread
].first
->run( sp
->quad
[thread
].first
, quad
);
304 if (mask
& 1) setup
->numFragsWritten
++;
305 if (mask
& 2) setup
->numFragsWritten
++;
306 if (mask
& 4) setup
->numFragsWritten
++;
307 if (mask
& 8) setup
->numFragsWritten
++;
311 #if SP_NUM_QUAD_THREADS > 1
314 emit_quad_job( struct setup_context
*setup
, uint thread
, struct quad_job
*job
)
316 emit_quad( setup
, job
->x
, job
->y
, job
->mask
, &job
->quad
, thread
);
319 #define EMIT_QUAD(setup,x,y,mask) add_quad_job( &setup->que, x, y, mask, &setup->quad, emit_quad_job )
323 #define EMIT_QUAD(setup,x,y,mask) emit_quad( setup, x, y, mask, &setup->quad, 0 )
328 * Given an X or Y coordinate, return the block/quad coordinate that it
331 static INLINE
int block( int x
)
338 * Render a horizontal span of quads
340 static void flush_spans( struct setup_context
*setup
)
342 const int xleft0
= setup
->span
.left
[0];
343 const int xleft1
= setup
->span
.left
[1];
344 const int xright0
= setup
->span
.right
[0];
345 const int xright1
= setup
->span
.right
[1];
346 int minleft
, maxright
;
349 switch (setup
->span
.y_flags
) {
351 /* both odd and even lines written (both quad rows) */
352 minleft
= block(MIN2(xleft0
, xleft1
));
353 maxright
= block(MAX2(xright0
, xright1
));
354 for (x
= minleft
; x
<= maxright
; x
+= 2) {
355 /* determine which of the four pixels is inside the span bounds */
357 if (x
>= xleft0
&& x
< xright0
)
358 mask
|= MASK_TOP_LEFT
;
359 if (x
>= xleft1
&& x
< xright1
)
360 mask
|= MASK_BOTTOM_LEFT
;
361 if (x
+1 >= xleft0
&& x
+1 < xright0
)
362 mask
|= MASK_TOP_RIGHT
;
363 if (x
+1 >= xleft1
&& x
+1 < xright1
)
364 mask
|= MASK_BOTTOM_RIGHT
;
365 EMIT_QUAD( setup
, x
, setup
->span
.y
, mask
);
370 /* only even line written (quad top row) */
371 minleft
= block(xleft0
);
372 maxright
= block(xright0
);
373 for (x
= minleft
; x
<= maxright
; x
+= 2) {
375 if (x
>= xleft0
&& x
< xright0
)
376 mask
|= MASK_TOP_LEFT
;
377 if (x
+1 >= xleft0
&& x
+1 < xright0
)
378 mask
|= MASK_TOP_RIGHT
;
379 EMIT_QUAD( setup
, x
, setup
->span
.y
, mask
);
384 /* only odd line written (quad bottom row) */
385 minleft
= block(xleft1
);
386 maxright
= block(xright1
);
387 for (x
= minleft
; x
<= maxright
; x
+= 2) {
389 if (x
>= xleft1
&& x
< xright1
)
390 mask
|= MASK_BOTTOM_LEFT
;
391 if (x
+1 >= xleft1
&& x
+1 < xright1
)
392 mask
|= MASK_BOTTOM_RIGHT
;
393 EMIT_QUAD( setup
, x
, setup
->span
.y
, mask
);
402 setup
->span
.y_flags
= 0;
403 setup
->span
.right
[0] = 0;
404 setup
->span
.right
[1] = 0;
409 static void print_vertex(const struct setup_context
*setup
,
413 debug_printf(" Vertex: (%p)\n", v
);
414 for (i
= 0; i
< setup
->quad
.nr_attrs
; i
++) {
415 debug_printf(" %d: %f %f %f %f\n", i
,
416 v
[i
][0], v
[i
][1], v
[i
][2], v
[i
][3]);
422 * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
424 static boolean
setup_sort_vertices( struct setup_context
*setup
,
426 const float (*v0
)[4],
427 const float (*v1
)[4],
428 const float (*v2
)[4] )
430 setup
->vprovoke
= v2
;
432 /* determine bottom to top order of vertices */
479 setup
->ebot
.dx
= setup
->vmid
[0][0] - setup
->vmin
[0][0];
480 setup
->ebot
.dy
= setup
->vmid
[0][1] - setup
->vmin
[0][1];
481 setup
->emaj
.dx
= setup
->vmax
[0][0] - setup
->vmin
[0][0];
482 setup
->emaj
.dy
= setup
->vmax
[0][1] - setup
->vmin
[0][1];
483 setup
->etop
.dx
= setup
->vmax
[0][0] - setup
->vmid
[0][0];
484 setup
->etop
.dy
= setup
->vmax
[0][1] - setup
->vmid
[0][1];
487 * Compute triangle's area. Use 1/area to compute partial
488 * derivatives of attributes later.
490 * The area will be the same as prim->det, but the sign may be
491 * different depending on how the vertices get sorted above.
493 * To determine whether the primitive is front or back facing we
494 * use the prim->det value because its sign is correct.
497 const float area
= (setup
->emaj
.dx
* setup
->ebot
.dy
-
498 setup
->ebot
.dx
* setup
->emaj
.dy
);
500 setup
->oneoverarea
= 1.0f
/ area
;
503 debug_printf("%s one-over-area %f area %f det %f\n",
504 __FUNCTION__, setup->oneoverarea, area, det );
506 if (is_inf_or_nan(setup
->oneoverarea
))
510 /* We need to know if this is a front or back-facing triangle for:
511 * - the GLSL gl_FrontFacing fragment attribute (bool)
512 * - two-sided stencil test
514 setup
->quad
.facing
= (det
> 0.0) ^ (setup
->softpipe
->rasterizer
->front_winding
== PIPE_WINDING_CW
);
521 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
522 * The value value comes from vertex[slot][i].
523 * The result will be put into setup->coef[slot].a0[i].
524 * \param slot which attribute slot
525 * \param i which component of the slot (0..3)
527 static void const_coeff( struct setup_context
*setup
,
528 struct tgsi_interp_coef
*coef
,
529 uint vertSlot
, uint i
)
536 /* need provoking vertex info!
538 coef
->a0
[i
] = setup
->vprovoke
[vertSlot
][i
];
543 * Compute a0, dadx and dady for a linearly interpolated coefficient,
546 static void tri_linear_coeff( struct setup_context
*setup
,
547 struct tgsi_interp_coef
*coef
,
548 uint vertSlot
, uint i
)
550 float botda
= setup
->vmid
[vertSlot
][i
] - setup
->vmin
[vertSlot
][i
];
551 float majda
= setup
->vmax
[vertSlot
][i
] - setup
->vmin
[vertSlot
][i
];
552 float a
= setup
->ebot
.dy
* majda
- botda
* setup
->emaj
.dy
;
553 float b
= setup
->emaj
.dx
* botda
- majda
* setup
->ebot
.dx
;
554 float dadx
= a
* setup
->oneoverarea
;
555 float dady
= b
* setup
->oneoverarea
;
559 coef
->dadx
[i
] = dadx
;
560 coef
->dady
[i
] = dady
;
562 /* calculate a0 as the value which would be sampled for the
563 * fragment at (0,0), taking into account that we want to sample at
564 * pixel centers, in other words (0.5, 0.5).
566 * this is neat but unfortunately not a good way to do things for
567 * triangles with very large values of dadx or dady as it will
568 * result in the subtraction and re-addition from a0 of a very
569 * large number, which means we'll end up loosing a lot of the
570 * fractional bits and precision from a0. the way to fix this is
571 * to define a0 as the sample at a pixel center somewhere near vmin
572 * instead - i'll switch to this later.
574 coef
->a0
[i
] = (setup
->vmin
[vertSlot
][i
] -
575 (dadx
* (setup
->vmin
[0][0] - 0.5f
) +
576 dady
* (setup
->vmin
[0][1] - 0.5f
)));
579 debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
581 setup->coef[slot].a0[i],
582 setup->coef[slot].dadx[i],
583 setup->coef[slot].dady[i]);
589 * Compute a0, dadx and dady for a perspective-corrected interpolant,
591 * We basically multiply the vertex value by 1/w before computing
592 * the plane coefficients (a0, dadx, dady).
593 * Later, when we compute the value at a particular fragment position we'll
594 * divide the interpolated value by the interpolated W at that fragment.
596 static void tri_persp_coeff( struct setup_context
*setup
,
597 struct tgsi_interp_coef
*coef
,
598 uint vertSlot
, uint i
)
600 /* premultiply by 1/w (v[0][3] is always W):
602 float mina
= setup
->vmin
[vertSlot
][i
] * setup
->vmin
[0][3];
603 float mida
= setup
->vmid
[vertSlot
][i
] * setup
->vmid
[0][3];
604 float maxa
= setup
->vmax
[vertSlot
][i
] * setup
->vmax
[0][3];
605 float botda
= mida
- mina
;
606 float majda
= maxa
- mina
;
607 float a
= setup
->ebot
.dy
* majda
- botda
* setup
->emaj
.dy
;
608 float b
= setup
->emaj
.dx
* botda
- majda
* setup
->ebot
.dx
;
609 float dadx
= a
* setup
->oneoverarea
;
610 float dady
= b
* setup
->oneoverarea
;
613 debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
614 setup->vmin[vertSlot][i],
615 setup->vmid[vertSlot][i],
616 setup->vmax[vertSlot][i]
621 coef
->dadx
[i
] = dadx
;
622 coef
->dady
[i
] = dady
;
623 coef
->a0
[i
] = (mina
-
624 (dadx
* (setup
->vmin
[0][0] - 0.5f
) +
625 dady
* (setup
->vmin
[0][1] - 0.5f
)));
630 * Special coefficient setup for gl_FragCoord.
631 * X and Y are trivial, though Y has to be inverted for OpenGL.
632 * Z and W are copied from posCoef which should have already been computed.
633 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
636 setup_fragcoord_coeff(struct setup_context
*setup
, uint slot
)
639 setup
->coef
[slot
].a0
[0] = 0;
640 setup
->coef
[slot
].dadx
[0] = 1.0;
641 setup
->coef
[slot
].dady
[0] = 0.0;
643 if (setup
->softpipe
->rasterizer
->origin_lower_left
) {
645 const int winHeight
= setup
->softpipe
->framebuffer
.height
;
646 setup
->coef
[slot
].a0
[1] = (float) (winHeight
- 1);
647 setup
->coef
[slot
].dady
[1] = -1.0;
651 setup
->coef
[slot
].a0
[1] = 0.0;
652 setup
->coef
[slot
].dady
[1] = 1.0;
654 setup
->coef
[slot
].dadx
[1] = 0.0;
656 setup
->coef
[slot
].a0
[2] = setup
->posCoef
.a0
[2];
657 setup
->coef
[slot
].dadx
[2] = setup
->posCoef
.dadx
[2];
658 setup
->coef
[slot
].dady
[2] = setup
->posCoef
.dady
[2];
660 setup
->coef
[slot
].a0
[3] = setup
->posCoef
.a0
[3];
661 setup
->coef
[slot
].dadx
[3] = setup
->posCoef
.dadx
[3];
662 setup
->coef
[slot
].dady
[3] = setup
->posCoef
.dady
[3];
668 * Compute the setup->coef[] array dadx, dady, a0 values.
669 * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
671 static void setup_tri_coefficients( struct setup_context
*setup
)
673 struct softpipe_context
*softpipe
= setup
->softpipe
;
674 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
675 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
678 /* z and w are done by linear interpolation:
680 tri_linear_coeff(setup
, &setup
->posCoef
, 0, 2);
681 tri_linear_coeff(setup
, &setup
->posCoef
, 0, 3);
683 /* setup interpolation for all the remaining attributes:
685 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
686 const uint vertSlot
= vinfo
->src_index
[fragSlot
];
689 switch (vinfo
->interp_mode
[fragSlot
]) {
690 case INTERP_CONSTANT
:
691 for (j
= 0; j
< NUM_CHANNELS
; j
++)
692 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
695 for (j
= 0; j
< NUM_CHANNELS
; j
++)
696 tri_linear_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
698 case INTERP_PERSPECTIVE
:
699 for (j
= 0; j
< NUM_CHANNELS
; j
++)
700 tri_persp_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
703 setup_fragcoord_coeff(setup
, fragSlot
);
709 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FOG
) {
710 /* FOG.y = front/back facing XXX fix this */
711 setup
->coef
[fragSlot
].a0
[1] = 1.0f
- setup
->quad
.facing
;
712 setup
->coef
[fragSlot
].dadx
[1] = 0.0;
713 setup
->coef
[fragSlot
].dady
[1] = 0.0;
720 static void setup_tri_edges( struct setup_context
*setup
)
722 float vmin_x
= setup
->vmin
[0][0] + 0.5f
;
723 float vmid_x
= setup
->vmid
[0][0] + 0.5f
;
725 float vmin_y
= setup
->vmin
[0][1] - 0.5f
;
726 float vmid_y
= setup
->vmid
[0][1] - 0.5f
;
727 float vmax_y
= setup
->vmax
[0][1] - 0.5f
;
729 setup
->emaj
.sy
= ceilf(vmin_y
);
730 setup
->emaj
.lines
= (int) ceilf(vmax_y
- setup
->emaj
.sy
);
731 setup
->emaj
.dxdy
= setup
->emaj
.dx
/ setup
->emaj
.dy
;
732 setup
->emaj
.sx
= vmin_x
+ (setup
->emaj
.sy
- vmin_y
) * setup
->emaj
.dxdy
;
734 setup
->etop
.sy
= ceilf(vmid_y
);
735 setup
->etop
.lines
= (int) ceilf(vmax_y
- setup
->etop
.sy
);
736 setup
->etop
.dxdy
= setup
->etop
.dx
/ setup
->etop
.dy
;
737 setup
->etop
.sx
= vmid_x
+ (setup
->etop
.sy
- vmid_y
) * setup
->etop
.dxdy
;
739 setup
->ebot
.sy
= ceilf(vmin_y
);
740 setup
->ebot
.lines
= (int) ceilf(vmid_y
- setup
->ebot
.sy
);
741 setup
->ebot
.dxdy
= setup
->ebot
.dx
/ setup
->ebot
.dy
;
742 setup
->ebot
.sx
= vmin_x
+ (setup
->ebot
.sy
- vmin_y
) * setup
->ebot
.dxdy
;
747 * Render the upper or lower half of a triangle.
748 * Scissoring/cliprect is applied here too.
750 static void subtriangle( struct setup_context
*setup
,
755 const struct pipe_scissor_state
*cliprect
= &setup
->softpipe
->cliprect
;
756 const int minx
= (int) cliprect
->minx
;
757 const int maxx
= (int) cliprect
->maxx
;
758 const int miny
= (int) cliprect
->miny
;
759 const int maxy
= (int) cliprect
->maxy
;
760 int y
, start_y
, finish_y
;
761 int sy
= (int)eleft
->sy
;
763 assert((int)eleft
->sy
== (int) eright
->sy
);
765 /* clip top/bottom */
767 finish_y
= sy
+ lines
;
779 debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
782 for (y
= start_y
; y
< finish_y
; y
++) {
784 /* avoid accumulating adds as floats don't have the precision to
785 * accurately iterate large triangle edges that way. luckily we
786 * can just multiply these days.
788 * this is all drowned out by the attribute interpolation anyway.
790 int left
= (int)(eleft
->sx
+ y
* eleft
->dxdy
);
791 int right
= (int)(eright
->sx
+ y
* eright
->dxdy
);
793 /* clip left/right */
801 if (block(_y
) != setup
->span
.y
) {
803 setup
->span
.y
= block(_y
);
806 setup
->span
.left
[_y
&1] = left
;
807 setup
->span
.right
[_y
&1] = right
;
808 setup
->span
.y_flags
|= 1<<(_y
&1);
813 /* save the values so that emaj can be restarted:
815 eleft
->sx
+= lines
* eleft
->dxdy
;
816 eright
->sx
+= lines
* eright
->dxdy
;
823 * Recalculate prim's determinant. This is needed as we don't have
824 * get this information through the vbuf_render interface & we must
828 calc_det( const float (*v0
)[4],
829 const float (*v1
)[4],
830 const float (*v2
)[4] )
832 /* edge vectors e = v0 - v2, f = v1 - v2 */
833 const float ex
= v0
[0][0] - v2
[0][0];
834 const float ey
= v0
[0][1] - v2
[0][1];
835 const float fx
= v1
[0][0] - v2
[0][0];
836 const float fy
= v1
[0][1] - v2
[0][1];
838 /* det = cross(e,f).z */
839 return ex
* fy
- ey
* fx
;
844 * Do setup for triangle rasterization, then render the triangle.
846 void setup_tri( struct setup_context
*setup
,
847 const float (*v0
)[4],
848 const float (*v1
)[4],
849 const float (*v2
)[4] )
854 debug_printf("Setup triangle:\n");
855 print_vertex(setup
, v0
);
856 print_vertex(setup
, v1
);
857 print_vertex(setup
, v2
);
860 if (setup
->softpipe
->no_rast
)
863 det
= calc_det(v0
, v1
, v2
);
865 debug_printf("%s\n", __FUNCTION__ );
869 setup
->numFragsEmitted
= 0;
870 setup
->numFragsWritten
= 0;
873 if (cull_tri( setup
, det
))
876 if (!setup_sort_vertices( setup
, det
, v0
, v1
, v2
))
878 setup_tri_coefficients( setup
);
879 setup_tri_edges( setup
);
881 setup
->quad
.prim
= PRIM_TRI
;
884 setup
->span
.y_flags
= 0;
885 setup
->span
.right
[0] = 0;
886 setup
->span
.right
[1] = 0;
887 /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
889 /* init_constant_attribs( setup ); */
891 if (setup
->oneoverarea
< 0.0) {
894 subtriangle( setup
, &setup
->emaj
, &setup
->ebot
, setup
->ebot
.lines
);
895 subtriangle( setup
, &setup
->emaj
, &setup
->etop
, setup
->etop
.lines
);
900 subtriangle( setup
, &setup
->ebot
, &setup
->emaj
, setup
->ebot
.lines
);
901 subtriangle( setup
, &setup
->etop
, &setup
->emaj
, setup
->etop
.lines
);
904 flush_spans( setup
);
906 WAIT_FOR_COMPLETION(setup
);
909 printf("Tri: %u frags emitted, %u written\n",
910 setup
->numFragsEmitted
,
911 setup
->numFragsWritten
);
918 * Compute a0, dadx and dady for a linearly interpolated coefficient,
922 line_linear_coeff(struct setup_context
*setup
,
923 struct tgsi_interp_coef
*coef
,
924 uint vertSlot
, uint i
)
926 const float da
= setup
->vmax
[vertSlot
][i
] - setup
->vmin
[vertSlot
][i
];
927 const float dadx
= da
* setup
->emaj
.dx
* setup
->oneoverarea
;
928 const float dady
= da
* setup
->emaj
.dy
* setup
->oneoverarea
;
929 coef
->dadx
[i
] = dadx
;
930 coef
->dady
[i
] = dady
;
931 coef
->a0
[i
] = (setup
->vmin
[vertSlot
][i
] -
932 (dadx
* (setup
->vmin
[0][0] - 0.5f
) +
933 dady
* (setup
->vmin
[0][1] - 0.5f
)));
938 * Compute a0, dadx and dady for a perspective-corrected interpolant,
942 line_persp_coeff(struct setup_context
*setup
,
943 struct tgsi_interp_coef
*coef
,
944 uint vertSlot
, uint i
)
946 /* XXX double-check/verify this arithmetic */
947 const float a0
= setup
->vmin
[vertSlot
][i
] * setup
->vmin
[0][3];
948 const float a1
= setup
->vmax
[vertSlot
][i
] * setup
->vmax
[0][3];
949 const float da
= a1
- a0
;
950 const float dadx
= da
* setup
->emaj
.dx
* setup
->oneoverarea
;
951 const float dady
= da
* setup
->emaj
.dy
* setup
->oneoverarea
;
952 coef
->dadx
[i
] = dadx
;
953 coef
->dady
[i
] = dady
;
954 coef
->a0
[i
] = (setup
->vmin
[vertSlot
][i
] -
955 (dadx
* (setup
->vmin
[0][0] - 0.5f
) +
956 dady
* (setup
->vmin
[0][1] - 0.5f
)));
961 * Compute the setup->coef[] array dadx, dady, a0 values.
962 * Must be called after setup->vmin,vmax are initialized.
964 static INLINE boolean
965 setup_line_coefficients(struct setup_context
*setup
,
966 const float (*v0
)[4],
967 const float (*v1
)[4])
969 struct softpipe_context
*softpipe
= setup
->softpipe
;
970 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
971 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
975 /* use setup->vmin, vmax to point to vertices */
976 setup
->vprovoke
= v1
;
980 setup
->emaj
.dx
= setup
->vmax
[0][0] - setup
->vmin
[0][0];
981 setup
->emaj
.dy
= setup
->vmax
[0][1] - setup
->vmin
[0][1];
983 /* NOTE: this is not really area but something proportional to it */
984 area
= setup
->emaj
.dx
* setup
->emaj
.dx
+ setup
->emaj
.dy
* setup
->emaj
.dy
;
985 if (area
== 0.0f
|| is_inf_or_nan(area
))
987 setup
->oneoverarea
= 1.0f
/ area
;
989 /* z and w are done by linear interpolation:
991 line_linear_coeff(setup
, &setup
->posCoef
, 0, 2);
992 line_linear_coeff(setup
, &setup
->posCoef
, 0, 3);
994 /* setup interpolation for all the remaining attributes:
996 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
997 const uint vertSlot
= vinfo
->src_index
[fragSlot
];
1000 switch (vinfo
->interp_mode
[fragSlot
]) {
1001 case INTERP_CONSTANT
:
1002 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1003 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
1006 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1007 line_linear_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
1009 case INTERP_PERSPECTIVE
:
1010 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1011 line_persp_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
1014 setup_fragcoord_coeff(setup
, fragSlot
);
1020 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FOG
) {
1021 /* FOG.y = front/back facing XXX fix this */
1022 setup
->coef
[fragSlot
].a0
[1] = 1.0f
- setup
->quad
.facing
;
1023 setup
->coef
[fragSlot
].dadx
[1] = 0.0;
1024 setup
->coef
[fragSlot
].dady
[1] = 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
.x0
||
1044 quadY
!= setup
->quad
.y0
)
1046 /* flush prev quad, start new quad */
1048 if (setup
->quad
.x0
!= -1)
1049 CLIP_EMIT_QUAD(setup
);
1051 setup
->quad
.x0
= quadX
;
1052 setup
->quad
.y0
= quadY
;
1053 setup
->quad
.mask
= 0x0;
1056 setup
->quad
.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 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 */
1117 setup
->quad
.x0
= setup
->quad
.y0
= -1;
1118 setup
->quad
.mask
= 0x0;
1119 setup
->quad
.prim
= PRIM_LINE
;
1120 /* XXX temporary: set coverage to 1.0 so the line appears
1121 * if AA mode happens to be enabled.
1123 setup
->quad
.coverage
[0] =
1124 setup
->quad
.coverage
[1] =
1125 setup
->quad
.coverage
[2] =
1126 setup
->quad
.coverage
[3] = 1.0;
1129 /*** X-major line ***/
1131 const int errorInc
= dy
+ dy
;
1132 int error
= errorInc
- dx
;
1133 const int errorDec
= error
- dx
;
1135 for (i
= 0; i
< dx
; i
++) {
1136 plot(setup
, x0
, y0
);
1149 /*** Y-major line ***/
1151 const int errorInc
= dx
+ dx
;
1152 int error
= errorInc
- dy
;
1153 const int errorDec
= error
- dy
;
1155 for (i
= 0; i
< dy
; i
++) {
1156 plot(setup
, x0
, y0
);
1169 /* draw final quad */
1170 if (setup
->quad
.mask
) {
1171 CLIP_EMIT_QUAD(setup
);
1174 WAIT_FOR_COMPLETION(setup
);
1179 point_persp_coeff(struct setup_context
*setup
,
1180 const float (*vert
)[4],
1181 struct tgsi_interp_coef
*coef
,
1182 uint vertSlot
, uint i
)
1185 coef
->dadx
[i
] = 0.0F
;
1186 coef
->dady
[i
] = 0.0F
;
1187 coef
->a0
[i
] = vert
[vertSlot
][i
] * vert
[0][3];
1192 * Do setup for point rasterization, then render the point.
1193 * Round or square points...
1194 * XXX could optimize a lot for 1-pixel points.
1197 setup_point( struct setup_context
*setup
,
1198 const float (*v0
)[4] )
1200 struct softpipe_context
*softpipe
= setup
->softpipe
;
1201 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
1202 const int sizeAttr
= setup
->softpipe
->psize_slot
;
1204 = sizeAttr
> 0 ? v0
[sizeAttr
][0]
1205 : setup
->softpipe
->rasterizer
->point_size
;
1206 const float halfSize
= 0.5F
* size
;
1207 const boolean round
= (boolean
) setup
->softpipe
->rasterizer
->point_smooth
;
1208 const float x
= v0
[0][0]; /* Note: data[0] is always position */
1209 const float y
= v0
[0][1];
1210 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
1214 debug_printf("Setup point:\n");
1215 print_vertex(setup
, v0
);
1218 if (softpipe
->no_rast
)
1221 /* For points, all interpolants are constant-valued.
1222 * However, for point sprites, we'll need to setup texcoords appropriately.
1223 * XXX: which coefficients are the texcoords???
1224 * We may do point sprites as textured quads...
1226 * KW: We don't know which coefficients are texcoords - ultimately
1227 * the choice of what interpolation mode to use for each attribute
1228 * should be determined by the fragment program, using
1229 * per-attribute declaration statements that include interpolation
1230 * mode as a parameter. So either the fragment program will have
1231 * to be adjusted for pointsprite vs normal point behaviour, or
1232 * otherwise a special interpolation mode will have to be defined
1233 * which matches the required behaviour for point sprites. But -
1234 * the latter is not a feature of normal hardware, and as such
1235 * probably should be ruled out on that basis.
1237 setup
->vprovoke
= v0
;
1240 const_coeff(setup
, &setup
->posCoef
, 0, 2);
1241 const_coeff(setup
, &setup
->posCoef
, 0, 3);
1243 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
1244 const uint vertSlot
= vinfo
->src_index
[fragSlot
];
1247 switch (vinfo
->interp_mode
[fragSlot
]) {
1248 case INTERP_CONSTANT
:
1251 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1252 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
1254 case INTERP_PERSPECTIVE
:
1255 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1256 point_persp_coeff(setup
, setup
->vprovoke
,
1257 &setup
->coef
[fragSlot
], vertSlot
, j
);
1260 setup_fragcoord_coeff(setup
, fragSlot
);
1266 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FOG
) {
1267 /* FOG.y = front/back facing XXX fix this */
1268 setup
->coef
[fragSlot
].a0
[1] = 1.0f
- setup
->quad
.facing
;
1269 setup
->coef
[fragSlot
].dadx
[1] = 0.0;
1270 setup
->coef
[fragSlot
].dady
[1] = 0.0;
1274 setup
->quad
.prim
= PRIM_POINT
;
1276 if (halfSize
<= 0.5 && !round
) {
1277 /* special case for 1-pixel points */
1278 const int ix
= ((int) x
) & 1;
1279 const int iy
= ((int) y
) & 1;
1280 setup
->quad
.x0
= (int) x
- ix
;
1281 setup
->quad
.y0
= (int) y
- iy
;
1282 setup
->quad
.mask
= (1 << ix
) << (2 * iy
);
1283 CLIP_EMIT_QUAD(setup
);
1287 /* rounded points */
1288 const int ixmin
= block((int) (x
- halfSize
));
1289 const int ixmax
= block((int) (x
+ halfSize
));
1290 const int iymin
= block((int) (y
- halfSize
));
1291 const int iymax
= block((int) (y
+ halfSize
));
1292 const float rmin
= halfSize
- 0.7071F
; /* 0.7071 = sqrt(2)/2 */
1293 const float rmax
= halfSize
+ 0.7071F
;
1294 const float rmin2
= MAX2(0.0F
, rmin
* rmin
);
1295 const float rmax2
= rmax
* rmax
;
1296 const float cscale
= 1.0F
/ (rmax2
- rmin2
);
1299 for (iy
= iymin
; iy
<= iymax
; iy
+= 2) {
1300 for (ix
= ixmin
; ix
<= ixmax
; ix
+= 2) {
1301 float dx
, dy
, dist2
, cover
;
1303 setup
->quad
.mask
= 0x0;
1305 dx
= (ix
+ 0.5f
) - x
;
1306 dy
= (iy
+ 0.5f
) - y
;
1307 dist2
= dx
* dx
+ dy
* dy
;
1308 if (dist2
<= rmax2
) {
1309 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1310 setup
->quad
.coverage
[QUAD_TOP_LEFT
] = MIN2(cover
, 1.0f
);
1311 setup
->quad
.mask
|= MASK_TOP_LEFT
;
1314 dx
= (ix
+ 1.5f
) - x
;
1315 dy
= (iy
+ 0.5f
) - y
;
1316 dist2
= dx
* dx
+ dy
* dy
;
1317 if (dist2
<= rmax2
) {
1318 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1319 setup
->quad
.coverage
[QUAD_TOP_RIGHT
] = MIN2(cover
, 1.0f
);
1320 setup
->quad
.mask
|= MASK_TOP_RIGHT
;
1323 dx
= (ix
+ 0.5f
) - x
;
1324 dy
= (iy
+ 1.5f
) - y
;
1325 dist2
= dx
* dx
+ dy
* dy
;
1326 if (dist2
<= rmax2
) {
1327 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1328 setup
->quad
.coverage
[QUAD_BOTTOM_LEFT
] = MIN2(cover
, 1.0f
);
1329 setup
->quad
.mask
|= MASK_BOTTOM_LEFT
;
1332 dx
= (ix
+ 1.5f
) - x
;
1333 dy
= (iy
+ 1.5f
) - y
;
1334 dist2
= dx
* dx
+ dy
* dy
;
1335 if (dist2
<= rmax2
) {
1336 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1337 setup
->quad
.coverage
[QUAD_BOTTOM_RIGHT
] = MIN2(cover
, 1.0f
);
1338 setup
->quad
.mask
|= MASK_BOTTOM_RIGHT
;
1341 if (setup
->quad
.mask
) {
1342 setup
->quad
.x0
= ix
;
1343 setup
->quad
.y0
= iy
;
1344 CLIP_EMIT_QUAD(setup
);
1351 const int xmin
= (int) (x
+ 0.75 - halfSize
);
1352 const int ymin
= (int) (y
+ 0.25 - halfSize
);
1353 const int xmax
= xmin
+ (int) size
;
1354 const int ymax
= ymin
+ (int) size
;
1355 /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
1356 const int ixmin
= block(xmin
);
1357 const int ixmax
= block(xmax
- 1);
1358 const int iymin
= block(ymin
);
1359 const int iymax
= block(ymax
- 1);
1363 debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
1365 for (iy
= iymin
; iy
<= iymax
; iy
+= 2) {
1368 /* above the top edge */
1369 rowMask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
1371 if (iy
+ 1 >= ymax
) {
1372 /* below the bottom edge */
1373 rowMask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
1376 for (ix
= ixmin
; ix
<= ixmax
; ix
+= 2) {
1377 uint mask
= rowMask
;
1380 /* fragment is past left edge of point, turn off left bits */
1381 mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
1383 if (ix
+ 1 >= xmax
) {
1384 /* past the right edge */
1385 mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
1388 setup
->quad
.mask
= mask
;
1389 setup
->quad
.x0
= ix
;
1390 setup
->quad
.y0
= iy
;
1391 CLIP_EMIT_QUAD(setup
);
1397 WAIT_FOR_COMPLETION(setup
);
1400 void setup_prepare( struct setup_context
*setup
)
1402 struct softpipe_context
*sp
= setup
->softpipe
;
1406 softpipe_update_derived(sp
);
1409 /* Mark surfaces as defined now */
1410 for (i
= 0; i
< sp
->framebuffer
.num_cbufs
; i
++){
1411 if (sp
->framebuffer
.cbufs
[i
]) {
1412 sp
->framebuffer
.cbufs
[i
]->status
= PIPE_SURFACE_STATUS_DEFINED
;
1415 if (sp
->framebuffer
.zsbuf
) {
1416 sp
->framebuffer
.zsbuf
->status
= PIPE_SURFACE_STATUS_DEFINED
;
1419 /* Note: nr_attrs is only used for debugging (vertex printing) */
1420 setup
->quad
.nr_attrs
= draw_num_vs_outputs(sp
->draw
);
1422 for (i
= 0; i
< SP_NUM_QUAD_THREADS
; i
++) {
1423 sp
->quad
[i
].first
->begin( sp
->quad
[i
].first
);
1426 if (sp
->reduced_api_prim
== PIPE_PRIM_TRIANGLES
&&
1427 sp
->rasterizer
->fill_cw
== PIPE_POLYGON_MODE_FILL
&&
1428 sp
->rasterizer
->fill_ccw
== PIPE_POLYGON_MODE_FILL
) {
1429 /* we'll do culling */
1430 setup
->winding
= sp
->rasterizer
->cull_mode
;
1433 /* 'draw' will do culling */
1434 setup
->winding
= PIPE_WINDING_NONE
;
1440 void setup_destroy_context( struct setup_context
*setup
)
1447 * Create a new primitive setup/render stage.
1449 struct setup_context
*setup_create_context( struct softpipe_context
*softpipe
)
1451 struct setup_context
*setup
= CALLOC_STRUCT(setup_context
);
1454 setup
->softpipe
= softpipe
;
1456 setup
->quad
.coef
= setup
->coef
;
1457 setup
->quad
.posCoef
= &setup
->posCoef
;
1459 #if SP_NUM_QUAD_THREADS > 1
1460 setup
->que
.first
= 0;
1461 setup
->que
.last
= 0;
1462 pipe_mutex_init( setup
->que
.mutex
);
1463 for (i
= 0; i
< SP_NUM_QUAD_THREADS
; i
++) {
1464 setup
->threads
[i
].setup
= setup
;
1465 setup
->threads
[i
].id
= i
;
1466 setup
->threads
[i
].handle
= pipe_thread_create( quad_thread
, &setup
->threads
[i
] );