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_private.h"
43 #include "draw/draw_vertex.h"
44 #include "pipe/p_util.h"
45 #include "pipe/p_shader_tokens.h"
54 float dx
; /**< X(v1) - X(v0), used only during setup */
55 float dy
; /**< Y(v1) - Y(v0), used only during setup */
56 float dxdy
; /**< dx/dy */
57 float sx
, sy
; /**< first sample point coord */
58 int lines
; /**< number of lines on this edge */
63 * Triangle setup info (derived from draw_stage).
64 * Also used for line drawing (taking some liberties).
66 struct setup_context
{
67 struct softpipe_context
*softpipe
;
69 /* Vertices are just an array of floats making up each attribute in
70 * turn. Currently fixed at 4 floats, but should change in time.
71 * Codegen will help cope with this.
73 const float (*vmax
)[4];
74 const float (*vmid
)[4];
75 const float (*vmin
)[4];
76 const float (*vprovoke
)[4];
84 struct tgsi_interp_coef coef
[PIPE_MAX_SHADER_INPUTS
];
85 struct tgsi_interp_coef posCoef
; /* For Z, W */
86 struct quad_header quad
;
89 int left
[2]; /**< [0] = row0, [1] = row1 */
93 unsigned mask
; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
97 uint numFragsEmitted
; /**< per primitive */
98 uint numFragsWritten
; /**< per primitive */
101 unsigned winding
; /* which winding to cull */
108 static boolean
cull_tri( struct setup_context
*setup
,
113 /* if (det < 0 then Z points toward camera and triangle is
114 * counter-clockwise winding.
116 unsigned winding
= (det
< 0) ? PIPE_WINDING_CCW
: PIPE_WINDING_CW
;
118 if ((winding
& setup
->winding
) == 0)
130 * Clip setup->quad against the scissor/surface bounds.
133 quad_clip(struct setup_context
*setup
)
135 const struct pipe_scissor_state
*cliprect
= &setup
->softpipe
->cliprect
;
136 const int minx
= (int) cliprect
->minx
;
137 const int maxx
= (int) cliprect
->maxx
;
138 const int miny
= (int) cliprect
->miny
;
139 const int maxy
= (int) cliprect
->maxy
;
141 if (setup
->quad
.x0
>= maxx
||
142 setup
->quad
.y0
>= maxy
||
143 setup
->quad
.x0
+ 1 < minx
||
144 setup
->quad
.y0
+ 1 < miny
) {
145 /* totally clipped */
146 setup
->quad
.mask
= 0x0;
149 if (setup
->quad
.x0
< minx
)
150 setup
->quad
.mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
151 if (setup
->quad
.y0
< miny
)
152 setup
->quad
.mask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
153 if (setup
->quad
.x0
== maxx
- 1)
154 setup
->quad
.mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
155 if (setup
->quad
.y0
== maxy
- 1)
156 setup
->quad
.mask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
161 * Emit a quad (pass to next stage) with clipping.
164 clip_emit_quad(struct setup_context
*setup
)
167 if (setup
->quad
.mask
) {
168 struct softpipe_context
*sp
= setup
->softpipe
;
169 sp
->quad
.first
->run(sp
->quad
.first
, &setup
->quad
);
175 * Emit a quad (pass to next stage). No clipping is done.
178 emit_quad( struct setup_context
*setup
, int x
, int y
, unsigned mask
)
180 struct softpipe_context
*sp
= setup
->softpipe
;
183 setup
->quad
.mask
= mask
;
185 if (mask
& 1) setup
->numFragsEmitted
++;
186 if (mask
& 2) setup
->numFragsEmitted
++;
187 if (mask
& 4) setup
->numFragsEmitted
++;
188 if (mask
& 8) setup
->numFragsEmitted
++;
190 sp
->quad
.first
->run(sp
->quad
.first
, &setup
->quad
);
192 mask
= setup
->quad
.mask
;
193 if (mask
& 1) setup
->numFragsWritten
++;
194 if (mask
& 2) setup
->numFragsWritten
++;
195 if (mask
& 4) setup
->numFragsWritten
++;
196 if (mask
& 8) setup
->numFragsWritten
++;
202 * Given an X or Y coordinate, return the block/quad coordinate that it
205 static INLINE
int block( int x
)
212 * Render a horizontal span of quads
214 static void flush_spans( struct setup_context
*setup
)
216 const int xleft0
= setup
->span
.left
[0];
217 const int xleft1
= setup
->span
.left
[1];
218 const int xright0
= setup
->span
.right
[0];
219 const int xright1
= setup
->span
.right
[1];
220 int minleft
, maxright
;
223 switch (setup
->span
.y_flags
) {
225 /* both odd and even lines written (both quad rows) */
226 minleft
= block(MIN2(xleft0
, xleft1
));
227 maxright
= block(MAX2(xright0
, xright1
));
228 for (x
= minleft
; x
<= maxright
; x
+= 2) {
229 /* determine which of the four pixels is inside the span bounds */
231 if (x
>= xleft0
&& x
< xright0
)
232 mask
|= MASK_TOP_LEFT
;
233 if (x
>= xleft1
&& x
< xright1
)
234 mask
|= MASK_BOTTOM_LEFT
;
235 if (x
+1 >= xleft0
&& x
+1 < xright0
)
236 mask
|= MASK_TOP_RIGHT
;
237 if (x
+1 >= xleft1
&& x
+1 < xright1
)
238 mask
|= MASK_BOTTOM_RIGHT
;
239 emit_quad( setup
, x
, setup
->span
.y
, mask
);
244 /* only even line written (quad top row) */
245 minleft
= block(xleft0
);
246 maxright
= block(xright0
);
247 for (x
= minleft
; x
<= maxright
; x
+= 2) {
249 if (x
>= xleft0
&& x
< xright0
)
250 mask
|= MASK_TOP_LEFT
;
251 if (x
+1 >= xleft0
&& x
+1 < xright0
)
252 mask
|= MASK_TOP_RIGHT
;
253 emit_quad( setup
, x
, setup
->span
.y
, mask
);
258 /* only odd line written (quad bottom row) */
259 minleft
= block(xleft1
);
260 maxright
= block(xright1
);
261 for (x
= minleft
; x
<= maxright
; x
+= 2) {
263 if (x
>= xleft1
&& x
< xright1
)
264 mask
|= MASK_BOTTOM_LEFT
;
265 if (x
+1 >= xleft1
&& x
+1 < xright1
)
266 mask
|= MASK_BOTTOM_RIGHT
;
267 emit_quad( setup
, x
, setup
->span
.y
, mask
);
276 setup
->span
.y_flags
= 0;
277 setup
->span
.right
[0] = 0;
278 setup
->span
.right
[1] = 0;
283 static void print_vertex(const struct setup_context
*setup
,
287 debug_printf("Vertex: (%p)\n", v
);
288 for (i
= 0; i
< setup
->quad
.nr_attrs
; i
++) {
289 debug_printf(" %d: %f %f %f %f\n", i
,
290 v
[i
][0], v
[i
][1], v
[i
][2], v
[i
][3]);
295 static boolean
setup_sort_vertices( struct setup_context
*setup
,
297 const float (*v0
)[4],
298 const float (*v1
)[4],
299 const float (*v2
)[4] )
301 setup
->vprovoke
= v2
;
303 /* determine bottom to top order of vertices */
350 setup
->ebot
.dx
= setup
->vmid
[0][0] - setup
->vmin
[0][0];
351 setup
->ebot
.dy
= setup
->vmid
[0][1] - setup
->vmin
[0][1];
352 setup
->emaj
.dx
= setup
->vmax
[0][0] - setup
->vmin
[0][0];
353 setup
->emaj
.dy
= setup
->vmax
[0][1] - setup
->vmin
[0][1];
354 setup
->etop
.dx
= setup
->vmax
[0][0] - setup
->vmid
[0][0];
355 setup
->etop
.dy
= setup
->vmax
[0][1] - setup
->vmid
[0][1];
358 * Compute triangle's area. Use 1/area to compute partial
359 * derivatives of attributes later.
361 * The area will be the same as prim->det, but the sign may be
362 * different depending on how the vertices get sorted above.
364 * To determine whether the primitive is front or back facing we
365 * use the prim->det value because its sign is correct.
368 const float area
= (setup
->emaj
.dx
* setup
->ebot
.dy
-
369 setup
->ebot
.dx
* setup
->emaj
.dy
);
371 setup
->oneoverarea
= 1.0f
/ area
;
373 debug_printf("%s one-over-area %f area %f det %f\n",
374 __FUNCTION__, setup->oneoverarea, area, det );
378 /* We need to know if this is a front or back-facing triangle for:
379 * - the GLSL gl_FrontFacing fragment attribute (bool)
380 * - two-sided stencil test
382 setup
->quad
.facing
= (det
> 0.0) ^ (setup
->softpipe
->rasterizer
->front_winding
== PIPE_WINDING_CW
);
389 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
390 * The value value comes from vertex[slot][i].
391 * The result will be put into setup->coef[slot].a0[i].
392 * \param slot which attribute slot
393 * \param i which component of the slot (0..3)
395 static void const_coeff( struct setup_context
*setup
,
396 struct tgsi_interp_coef
*coef
,
397 uint vertSlot
, uint i
)
404 /* need provoking vertex info!
406 coef
->a0
[i
] = setup
->vprovoke
[vertSlot
][i
];
411 * Compute a0, dadx and dady for a linearly interpolated coefficient,
414 static void tri_linear_coeff( struct setup_context
*setup
,
415 struct tgsi_interp_coef
*coef
,
416 uint vertSlot
, uint i
)
418 float botda
= setup
->vmid
[vertSlot
][i
] - setup
->vmin
[vertSlot
][i
];
419 float majda
= setup
->vmax
[vertSlot
][i
] - setup
->vmin
[vertSlot
][i
];
420 float a
= setup
->ebot
.dy
* majda
- botda
* setup
->emaj
.dy
;
421 float b
= setup
->emaj
.dx
* botda
- majda
* setup
->ebot
.dx
;
422 float dadx
= a
* setup
->oneoverarea
;
423 float dady
= b
* setup
->oneoverarea
;
427 coef
->dadx
[i
] = dadx
;
428 coef
->dady
[i
] = dady
;
430 /* calculate a0 as the value which would be sampled for the
431 * fragment at (0,0), taking into account that we want to sample at
432 * pixel centers, in other words (0.5, 0.5).
434 * this is neat but unfortunately not a good way to do things for
435 * triangles with very large values of dadx or dady as it will
436 * result in the subtraction and re-addition from a0 of a very
437 * large number, which means we'll end up loosing a lot of the
438 * fractional bits and precision from a0. the way to fix this is
439 * to define a0 as the sample at a pixel center somewhere near vmin
440 * instead - i'll switch to this later.
442 coef
->a0
[i
] = (setup
->vmin
[vertSlot
][i
] -
443 (dadx
* (setup
->vmin
[0][0] - 0.5f
) +
444 dady
* (setup
->vmin
[0][1] - 0.5f
)));
447 debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
449 setup->coef[slot].a0[i],
450 setup->coef[slot].dadx[i],
451 setup->coef[slot].dady[i]);
457 * Compute a0, dadx and dady for a perspective-corrected interpolant,
459 * We basically multiply the vertex value by 1/w before computing
460 * the plane coefficients (a0, dadx, dady).
461 * Later, when we compute the value at a particular fragment position we'll
462 * divide the interpolated value by the interpolated W at that fragment.
464 static void tri_persp_coeff( struct setup_context
*setup
,
465 struct tgsi_interp_coef
*coef
,
466 uint vertSlot
, uint i
)
468 /* premultiply by 1/w (v[0][3] is always W):
470 float mina
= setup
->vmin
[vertSlot
][i
] * setup
->vmin
[0][3];
471 float mida
= setup
->vmid
[vertSlot
][i
] * setup
->vmid
[0][3];
472 float maxa
= setup
->vmax
[vertSlot
][i
] * setup
->vmax
[0][3];
473 float botda
= mida
- mina
;
474 float majda
= maxa
- mina
;
475 float a
= setup
->ebot
.dy
* majda
- botda
* setup
->emaj
.dy
;
476 float b
= setup
->emaj
.dx
* botda
- majda
* setup
->ebot
.dx
;
477 float dadx
= a
* setup
->oneoverarea
;
478 float dady
= b
* setup
->oneoverarea
;
481 debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
482 setup->vmin[vertSlot][i],
483 setup->vmid[vertSlot][i],
484 setup->vmax[vertSlot][i]
489 coef
->dadx
[i
] = dadx
;
490 coef
->dady
[i
] = dady
;
491 coef
->a0
[i
] = (mina
-
492 (dadx
* (setup
->vmin
[0][0] - 0.5f
) +
493 dady
* (setup
->vmin
[0][1] - 0.5f
)));
498 * Special coefficient setup for gl_FragCoord.
499 * X and Y are trivial, though Y has to be inverted for OpenGL.
500 * Z and W are copied from posCoef which should have already been computed.
501 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
504 setup_fragcoord_coeff(struct setup_context
*setup
, uint slot
)
507 setup
->coef
[slot
].a0
[0] = 0;
508 setup
->coef
[slot
].dadx
[0] = 1.0;
509 setup
->coef
[slot
].dady
[0] = 0.0;
511 if (setup
->softpipe
->rasterizer
->origin_lower_left
) {
513 const int winHeight
= setup
->softpipe
->framebuffer
.height
;
514 setup
->coef
[slot
].a0
[1] = (float) (winHeight
- 1);
515 setup
->coef
[slot
].dady
[1] = -1.0;
519 setup
->coef
[slot
].a0
[1] = 0.0;
520 setup
->coef
[slot
].dady
[1] = 1.0;
522 setup
->coef
[slot
].dadx
[1] = 0.0;
524 setup
->coef
[slot
].a0
[2] = setup
->posCoef
.a0
[2];
525 setup
->coef
[slot
].dadx
[2] = setup
->posCoef
.dadx
[2];
526 setup
->coef
[slot
].dady
[2] = setup
->posCoef
.dady
[2];
528 setup
->coef
[slot
].a0
[3] = setup
->posCoef
.a0
[3];
529 setup
->coef
[slot
].dadx
[3] = setup
->posCoef
.dadx
[3];
530 setup
->coef
[slot
].dady
[3] = setup
->posCoef
.dady
[3];
536 * Compute the setup->coef[] array dadx, dady, a0 values.
537 * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
539 static void setup_tri_coefficients( struct setup_context
*setup
)
541 struct softpipe_context
*softpipe
= setup
->softpipe
;
542 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
543 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
546 /* z and w are done by linear interpolation:
548 tri_linear_coeff(setup
, &setup
->posCoef
, 0, 2);
549 tri_linear_coeff(setup
, &setup
->posCoef
, 0, 3);
551 /* setup interpolation for all the remaining attributes:
553 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
554 const uint vertSlot
= vinfo
->src_index
[fragSlot
];
557 switch (vinfo
->interp_mode
[fragSlot
]) {
558 case INTERP_CONSTANT
:
559 for (j
= 0; j
< NUM_CHANNELS
; j
++)
560 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
563 for (j
= 0; j
< NUM_CHANNELS
; j
++)
564 tri_linear_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
566 case INTERP_PERSPECTIVE
:
567 for (j
= 0; j
< NUM_CHANNELS
; j
++)
568 tri_persp_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
571 setup_fragcoord_coeff(setup
, fragSlot
);
577 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FOG
) {
578 /* FOG.y = front/back facing XXX fix this */
579 setup
->coef
[fragSlot
].a0
[1] = 1.0f
- setup
->quad
.facing
;
580 setup
->coef
[fragSlot
].dadx
[1] = 0.0;
581 setup
->coef
[fragSlot
].dady
[1] = 0.0;
588 static void setup_tri_edges( struct setup_context
*setup
)
590 float vmin_x
= setup
->vmin
[0][0] + 0.5f
;
591 float vmid_x
= setup
->vmid
[0][0] + 0.5f
;
593 float vmin_y
= setup
->vmin
[0][1] - 0.5f
;
594 float vmid_y
= setup
->vmid
[0][1] - 0.5f
;
595 float vmax_y
= setup
->vmax
[0][1] - 0.5f
;
597 setup
->emaj
.sy
= CEILF(vmin_y
);
598 setup
->emaj
.lines
= (int) CEILF(vmax_y
- setup
->emaj
.sy
);
599 setup
->emaj
.dxdy
= setup
->emaj
.dx
/ setup
->emaj
.dy
;
600 setup
->emaj
.sx
= vmin_x
+ (setup
->emaj
.sy
- vmin_y
) * setup
->emaj
.dxdy
;
602 setup
->etop
.sy
= CEILF(vmid_y
);
603 setup
->etop
.lines
= (int) CEILF(vmax_y
- setup
->etop
.sy
);
604 setup
->etop
.dxdy
= setup
->etop
.dx
/ setup
->etop
.dy
;
605 setup
->etop
.sx
= vmid_x
+ (setup
->etop
.sy
- vmid_y
) * setup
->etop
.dxdy
;
607 setup
->ebot
.sy
= CEILF(vmin_y
);
608 setup
->ebot
.lines
= (int) CEILF(vmid_y
- setup
->ebot
.sy
);
609 setup
->ebot
.dxdy
= setup
->ebot
.dx
/ setup
->ebot
.dy
;
610 setup
->ebot
.sx
= vmin_x
+ (setup
->ebot
.sy
- vmin_y
) * setup
->ebot
.dxdy
;
615 * Render the upper or lower half of a triangle.
616 * Scissoring/cliprect is applied here too.
618 static void subtriangle( struct setup_context
*setup
,
623 const struct pipe_scissor_state
*cliprect
= &setup
->softpipe
->cliprect
;
624 const int minx
= (int) cliprect
->minx
;
625 const int maxx
= (int) cliprect
->maxx
;
626 const int miny
= (int) cliprect
->miny
;
627 const int maxy
= (int) cliprect
->maxy
;
628 int y
, start_y
, finish_y
;
629 int sy
= (int)eleft
->sy
;
631 assert((int)eleft
->sy
== (int) eright
->sy
);
633 /* clip top/bottom */
635 finish_y
= sy
+ lines
;
647 debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
650 for (y
= start_y
; y
< finish_y
; y
++) {
652 /* avoid accumulating adds as floats don't have the precision to
653 * accurately iterate large triangle edges that way. luckily we
654 * can just multiply these days.
656 * this is all drowned out by the attribute interpolation anyway.
658 int left
= (int)(eleft
->sx
+ y
* eleft
->dxdy
);
659 int right
= (int)(eright
->sx
+ y
* eright
->dxdy
);
661 /* clip left/right */
669 if (block(_y
) != setup
->span
.y
) {
671 setup
->span
.y
= block(_y
);
674 setup
->span
.left
[_y
&1] = left
;
675 setup
->span
.right
[_y
&1] = right
;
676 setup
->span
.y_flags
|= 1<<(_y
&1);
681 /* save the values so that emaj can be restarted:
683 eleft
->sx
+= lines
* eleft
->dxdy
;
684 eright
->sx
+= lines
* eright
->dxdy
;
691 * Recalculate prim's determinant. This is needed as we don't have
692 * get this information through the vbuf_render interface & we must
696 calc_det( const float (*v0
)[4],
697 const float (*v1
)[4],
698 const float (*v2
)[4] )
700 /* edge vectors e = v0 - v2, f = v1 - v2 */
701 const float ex
= v0
[0][0] - v2
[0][0];
702 const float ey
= v0
[0][1] - v2
[0][1];
703 const float fx
= v1
[0][0] - v2
[0][0];
704 const float fy
= v1
[0][1] - v2
[0][1];
706 /* det = cross(e,f).z */
707 return ex
* fy
- ey
* fx
;
712 * Do setup for triangle rasterization, then render the triangle.
714 void setup_tri( struct setup_context
*setup
,
715 const float (*v0
)[4],
716 const float (*v1
)[4],
717 const float (*v2
)[4] )
722 debug_printf("Setup triangle:\n");
723 print_vertex(setup
, v0
);
724 print_vertex(setup
, v1
);
725 print_vertex(setup
, v2
);
728 if (setup
->softpipe
->no_rast
)
731 det
= calc_det(v0
, v1
, v2
);
733 debug_printf("%s\n", __FUNCTION__ );
737 setup
->numFragsEmitted
= 0;
738 setup
->numFragsWritten
= 0;
741 if (cull_tri( setup
, det
))
744 setup_sort_vertices( setup
, det
, v0
, v1
, v2
);
745 setup_tri_coefficients( setup
);
746 setup_tri_edges( setup
);
748 setup
->quad
.prim
= PRIM_TRI
;
751 setup
->span
.y_flags
= 0;
752 setup
->span
.right
[0] = 0;
753 setup
->span
.right
[1] = 0;
754 /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
756 /* init_constant_attribs( setup ); */
758 if (setup
->oneoverarea
< 0.0) {
761 subtriangle( setup
, &setup
->emaj
, &setup
->ebot
, setup
->ebot
.lines
);
762 subtriangle( setup
, &setup
->emaj
, &setup
->etop
, setup
->etop
.lines
);
767 subtriangle( setup
, &setup
->ebot
, &setup
->emaj
, setup
->ebot
.lines
);
768 subtriangle( setup
, &setup
->etop
, &setup
->emaj
, setup
->etop
.lines
);
771 flush_spans( setup
);
774 printf("Tri: %u frags emitted, %u written\n",
775 setup
->numFragsEmitted
,
776 setup
->numFragsWritten
);
783 * Compute a0, dadx and dady for a linearly interpolated coefficient,
787 line_linear_coeff(struct setup_context
*setup
,
788 struct tgsi_interp_coef
*coef
,
789 uint vertSlot
, uint i
)
791 const float da
= setup
->vmax
[vertSlot
][i
] - setup
->vmin
[vertSlot
][i
];
792 const float dadx
= da
* setup
->emaj
.dx
* setup
->oneoverarea
;
793 const float dady
= da
* setup
->emaj
.dy
* setup
->oneoverarea
;
794 coef
->dadx
[i
] = dadx
;
795 coef
->dady
[i
] = dady
;
796 coef
->a0
[i
] = (setup
->vmin
[vertSlot
][i
] -
797 (dadx
* (setup
->vmin
[0][0] - 0.5f
) +
798 dady
* (setup
->vmin
[0][1] - 0.5f
)));
803 * Compute a0, dadx and dady for a perspective-corrected interpolant,
807 line_persp_coeff(struct setup_context
*setup
,
808 struct tgsi_interp_coef
*coef
,
809 uint vertSlot
, uint i
)
811 /* XXX double-check/verify this arithmetic */
812 const float a0
= setup
->vmin
[vertSlot
][i
] * setup
->vmin
[0][3];
813 const float a1
= setup
->vmax
[vertSlot
][i
] * setup
->vmax
[0][3];
814 const float da
= a1
- a0
;
815 const float dadx
= da
* setup
->emaj
.dx
* setup
->oneoverarea
;
816 const float dady
= da
* setup
->emaj
.dy
* setup
->oneoverarea
;
817 coef
->dadx
[i
] = dadx
;
818 coef
->dady
[i
] = dady
;
819 coef
->a0
[i
] = (setup
->vmin
[vertSlot
][i
] -
820 (dadx
* (setup
->vmin
[0][0] - 0.5f
) +
821 dady
* (setup
->vmin
[0][1] - 0.5f
)));
826 * Compute the setup->coef[] array dadx, dady, a0 values.
827 * Must be called after setup->vmin,vmax are initialized.
830 setup_line_coefficients(struct setup_context
*setup
,
831 const float (*v0
)[4],
832 const float (*v1
)[4])
834 struct softpipe_context
*softpipe
= setup
->softpipe
;
835 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
836 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
839 /* use setup->vmin, vmax to point to vertices */
840 setup
->vprovoke
= v1
;
844 setup
->emaj
.dx
= setup
->vmax
[0][0] - setup
->vmin
[0][0];
845 setup
->emaj
.dy
= setup
->vmax
[0][1] - setup
->vmin
[0][1];
846 /* NOTE: this is not really 1/area */
847 setup
->oneoverarea
= 1.0f
/ (setup
->emaj
.dx
* setup
->emaj
.dx
+
848 setup
->emaj
.dy
* setup
->emaj
.dy
);
850 /* z and w are done by linear interpolation:
852 line_linear_coeff(setup
, &setup
->posCoef
, 0, 2);
853 line_linear_coeff(setup
, &setup
->posCoef
, 0, 3);
855 /* setup interpolation for all the remaining attributes:
857 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
858 const uint vertSlot
= vinfo
->src_index
[fragSlot
];
861 switch (vinfo
->interp_mode
[fragSlot
]) {
862 case INTERP_CONSTANT
:
863 for (j
= 0; j
< NUM_CHANNELS
; j
++)
864 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
867 for (j
= 0; j
< NUM_CHANNELS
; j
++)
868 line_linear_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
870 case INTERP_PERSPECTIVE
:
871 for (j
= 0; j
< NUM_CHANNELS
; j
++)
872 line_persp_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
875 setup_fragcoord_coeff(setup
, fragSlot
);
881 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FOG
) {
882 /* FOG.y = front/back facing XXX fix this */
883 setup
->coef
[fragSlot
].a0
[1] = 1.0f
- setup
->quad
.facing
;
884 setup
->coef
[fragSlot
].dadx
[1] = 0.0;
885 setup
->coef
[fragSlot
].dady
[1] = 0.0;
892 * Plot a pixel in a line segment.
895 plot(struct setup_context
*setup
, int x
, int y
)
897 const int iy
= y
& 1;
898 const int ix
= x
& 1;
899 const int quadX
= x
- ix
;
900 const int quadY
= y
- iy
;
901 const int mask
= (1 << ix
) << (2 * iy
);
903 if (quadX
!= setup
->quad
.x0
||
904 quadY
!= setup
->quad
.y0
)
906 /* flush prev quad, start new quad */
908 if (setup
->quad
.x0
!= -1)
909 clip_emit_quad(setup
);
911 setup
->quad
.x0
= quadX
;
912 setup
->quad
.y0
= quadY
;
913 setup
->quad
.mask
= 0x0;
916 setup
->quad
.mask
|= mask
;
921 * Do setup for line rasterization, then render the line.
922 * Single-pixel width, no stipple, etc. We rely on the 'draw' module
923 * to handle stippling and wide lines.
926 setup_line(struct setup_context
*setup
,
927 const float (*v0
)[4],
928 const float (*v1
)[4])
930 int x0
= (int) v0
[0][0];
931 int x1
= (int) v1
[0][0];
932 int y0
= (int) v0
[0][1];
933 int y1
= (int) v1
[0][1];
939 debug_printf("Setup line:\n");
940 print_vertex(setup
, v0
);
941 print_vertex(setup
, v1
);
944 assert(v0
[0][0] < 1.0e9
);
945 assert(v0
[0][1] < 1.0e9
);
946 assert(v1
[0][0] < 1.0e9
);
947 assert(v1
[0][1] < 1.0e9
);
949 if (setup
->softpipe
->no_rast
)
952 if (dx
== 0 && dy
== 0)
955 setup_line_coefficients(setup
, v0
, v1
);
958 dx
= -dx
; /* make positive */
966 dy
= -dy
; /* make positive */
976 setup
->quad
.x0
= setup
->quad
.y0
= -1;
977 setup
->quad
.mask
= 0x0;
978 setup
->quad
.prim
= PRIM_LINE
;
979 /* XXX temporary: set coverage to 1.0 so the line appears
980 * if AA mode happens to be enabled.
982 setup
->quad
.coverage
[0] =
983 setup
->quad
.coverage
[1] =
984 setup
->quad
.coverage
[2] =
985 setup
->quad
.coverage
[3] = 1.0;
988 /*** X-major line ***/
990 const int errorInc
= dy
+ dy
;
991 int error
= errorInc
- dx
;
992 const int errorDec
= error
- dx
;
994 for (i
= 0; i
< dx
; i
++) {
1008 /*** Y-major line ***/
1010 const int errorInc
= dx
+ dx
;
1011 int error
= errorInc
- dy
;
1012 const int errorDec
= error
- dy
;
1014 for (i
= 0; i
< dy
; i
++) {
1015 plot(setup
, x0
, y0
);
1028 /* draw final quad */
1029 if (setup
->quad
.mask
) {
1030 clip_emit_quad(setup
);
1036 point_persp_coeff(struct setup_context
*setup
,
1037 const float (*vert
)[4],
1038 struct tgsi_interp_coef
*coef
,
1039 uint vertSlot
, uint i
)
1042 coef
->dadx
[i
] = 0.0F
;
1043 coef
->dady
[i
] = 0.0F
;
1044 coef
->a0
[i
] = vert
[vertSlot
][i
] * vert
[0][3];
1049 * Do setup for point rasterization, then render the point.
1050 * Round or square points...
1051 * XXX could optimize a lot for 1-pixel points.
1054 setup_point( struct setup_context
*setup
,
1055 const float (*v0
)[4] )
1057 struct softpipe_context
*softpipe
= setup
->softpipe
;
1058 const struct sp_fragment_shader
*spfs
= softpipe
->fs
;
1059 const int sizeAttr
= setup
->softpipe
->psize_slot
;
1061 = sizeAttr
> 0 ? v0
[sizeAttr
][0]
1062 : setup
->softpipe
->rasterizer
->point_size
;
1063 const float halfSize
= 0.5F
* size
;
1064 const boolean round
= (boolean
) setup
->softpipe
->rasterizer
->point_smooth
;
1065 const float x
= v0
[0][0]; /* Note: data[0] is always position */
1066 const float y
= v0
[0][1];
1067 const struct vertex_info
*vinfo
= softpipe_get_vertex_info(softpipe
);
1071 debug_printf("Setup point:\n");
1072 print_vertex(setup
, v0
);
1075 if (softpipe
->no_rast
)
1078 /* For points, all interpolants are constant-valued.
1079 * However, for point sprites, we'll need to setup texcoords appropriately.
1080 * XXX: which coefficients are the texcoords???
1081 * We may do point sprites as textured quads...
1083 * KW: We don't know which coefficients are texcoords - ultimately
1084 * the choice of what interpolation mode to use for each attribute
1085 * should be determined by the fragment program, using
1086 * per-attribute declaration statements that include interpolation
1087 * mode as a parameter. So either the fragment program will have
1088 * to be adjusted for pointsprite vs normal point behaviour, or
1089 * otherwise a special interpolation mode will have to be defined
1090 * which matches the required behaviour for point sprites. But -
1091 * the latter is not a feature of normal hardware, and as such
1092 * probably should be ruled out on that basis.
1094 setup
->vprovoke
= v0
;
1097 const_coeff(setup
, &setup
->posCoef
, 0, 2);
1098 const_coeff(setup
, &setup
->posCoef
, 0, 3);
1100 for (fragSlot
= 0; fragSlot
< spfs
->info
.num_inputs
; fragSlot
++) {
1101 const uint vertSlot
= vinfo
->src_index
[fragSlot
];
1104 switch (vinfo
->interp_mode
[fragSlot
]) {
1105 case INTERP_CONSTANT
:
1108 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1109 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
1111 case INTERP_PERSPECTIVE
:
1112 for (j
= 0; j
< NUM_CHANNELS
; j
++)
1113 point_persp_coeff(setup
, setup
->vprovoke
,
1114 &setup
->coef
[fragSlot
], vertSlot
, j
);
1117 setup_fragcoord_coeff(setup
, fragSlot
);
1123 if (spfs
->info
.input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FOG
) {
1124 /* FOG.y = front/back facing XXX fix this */
1125 setup
->coef
[fragSlot
].a0
[1] = 1.0f
- setup
->quad
.facing
;
1126 setup
->coef
[fragSlot
].dadx
[1] = 0.0;
1127 setup
->coef
[fragSlot
].dady
[1] = 0.0;
1131 setup
->quad
.prim
= PRIM_POINT
;
1133 if (halfSize
<= 0.5 && !round
) {
1134 /* special case for 1-pixel points */
1135 const int ix
= ((int) x
) & 1;
1136 const int iy
= ((int) y
) & 1;
1137 setup
->quad
.x0
= (int) x
- ix
;
1138 setup
->quad
.y0
= (int) y
- iy
;
1139 setup
->quad
.mask
= (1 << ix
) << (2 * iy
);
1140 clip_emit_quad(setup
);
1144 /* rounded points */
1145 const int ixmin
= block((int) (x
- halfSize
));
1146 const int ixmax
= block((int) (x
+ halfSize
));
1147 const int iymin
= block((int) (y
- halfSize
));
1148 const int iymax
= block((int) (y
+ halfSize
));
1149 const float rmin
= halfSize
- 0.7071F
; /* 0.7071 = sqrt(2)/2 */
1150 const float rmax
= halfSize
+ 0.7071F
;
1151 const float rmin2
= MAX2(0.0F
, rmin
* rmin
);
1152 const float rmax2
= rmax
* rmax
;
1153 const float cscale
= 1.0F
/ (rmax2
- rmin2
);
1156 for (iy
= iymin
; iy
<= iymax
; iy
+= 2) {
1157 for (ix
= ixmin
; ix
<= ixmax
; ix
+= 2) {
1158 float dx
, dy
, dist2
, cover
;
1160 setup
->quad
.mask
= 0x0;
1162 dx
= (ix
+ 0.5f
) - x
;
1163 dy
= (iy
+ 0.5f
) - y
;
1164 dist2
= dx
* dx
+ dy
* dy
;
1165 if (dist2
<= rmax2
) {
1166 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1167 setup
->quad
.coverage
[QUAD_TOP_LEFT
] = MIN2(cover
, 1.0f
);
1168 setup
->quad
.mask
|= MASK_TOP_LEFT
;
1171 dx
= (ix
+ 1.5f
) - x
;
1172 dy
= (iy
+ 0.5f
) - y
;
1173 dist2
= dx
* dx
+ dy
* dy
;
1174 if (dist2
<= rmax2
) {
1175 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1176 setup
->quad
.coverage
[QUAD_TOP_RIGHT
] = MIN2(cover
, 1.0f
);
1177 setup
->quad
.mask
|= MASK_TOP_RIGHT
;
1180 dx
= (ix
+ 0.5f
) - x
;
1181 dy
= (iy
+ 1.5f
) - y
;
1182 dist2
= dx
* dx
+ dy
* dy
;
1183 if (dist2
<= rmax2
) {
1184 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1185 setup
->quad
.coverage
[QUAD_BOTTOM_LEFT
] = MIN2(cover
, 1.0f
);
1186 setup
->quad
.mask
|= MASK_BOTTOM_LEFT
;
1189 dx
= (ix
+ 1.5f
) - x
;
1190 dy
= (iy
+ 1.5f
) - y
;
1191 dist2
= dx
* dx
+ dy
* dy
;
1192 if (dist2
<= rmax2
) {
1193 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1194 setup
->quad
.coverage
[QUAD_BOTTOM_RIGHT
] = MIN2(cover
, 1.0f
);
1195 setup
->quad
.mask
|= MASK_BOTTOM_RIGHT
;
1198 if (setup
->quad
.mask
) {
1199 setup
->quad
.x0
= ix
;
1200 setup
->quad
.y0
= iy
;
1201 clip_emit_quad(setup
);
1208 const int xmin
= (int) (x
+ 0.75 - halfSize
);
1209 const int ymin
= (int) (y
+ 0.25 - halfSize
);
1210 const int xmax
= xmin
+ (int) size
;
1211 const int ymax
= ymin
+ (int) size
;
1212 /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
1213 const int ixmin
= block(xmin
);
1214 const int ixmax
= block(xmax
- 1);
1215 const int iymin
= block(ymin
);
1216 const int iymax
= block(ymax
- 1);
1220 debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
1222 for (iy
= iymin
; iy
<= iymax
; iy
+= 2) {
1225 /* above the top edge */
1226 rowMask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
1228 if (iy
+ 1 >= ymax
) {
1229 /* below the bottom edge */
1230 rowMask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
1233 for (ix
= ixmin
; ix
<= ixmax
; ix
+= 2) {
1234 uint mask
= rowMask
;
1237 /* fragment is past left edge of point, turn off left bits */
1238 mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
1240 if (ix
+ 1 >= xmax
) {
1241 /* past the right edge */
1242 mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
1245 setup
->quad
.mask
= mask
;
1246 setup
->quad
.x0
= ix
;
1247 setup
->quad
.y0
= iy
;
1248 clip_emit_quad(setup
);
1255 void setup_prepare( struct setup_context
*setup
)
1257 struct softpipe_context
*sp
= setup
->softpipe
;
1261 softpipe_update_derived(sp
);
1264 /* Mark surfaces as defined now */
1265 for (i
= 0; i
< sp
->framebuffer
.num_cbufs
; i
++){
1266 if (sp
->framebuffer
.cbufs
[i
]) {
1267 sp
->framebuffer
.cbufs
[i
]->status
= PIPE_SURFACE_STATUS_DEFINED
;
1270 if (sp
->framebuffer
.zsbuf
) {
1271 sp
->framebuffer
.zsbuf
->status
= PIPE_SURFACE_STATUS_DEFINED
;
1274 /* Note: nr_attrs is only used for debugging (vertex printing) */
1276 const struct sp_fragment_shader
*fs
= setup
->softpipe
->fs
;
1277 setup
->quad
.nr_attrs
= fs
->info
.num_inputs
+ 1; /* +1 for vert pos */
1280 sp
->quad
.first
->begin(sp
->quad
.first
);
1282 if (sp
->reduced_api_prim
== PIPE_PRIM_TRIANGLES
&&
1283 sp
->rasterizer
->fill_cw
== PIPE_POLYGON_MODE_FILL
&&
1284 sp
->rasterizer
->fill_ccw
== PIPE_POLYGON_MODE_FILL
) {
1285 /* we'll do culling */
1286 setup
->winding
= sp
->rasterizer
->cull_mode
;
1289 /* 'draw' will do culling */
1290 setup
->winding
= PIPE_WINDING_NONE
;
1296 void setup_destroy_context( struct setup_context
*setup
)
1303 * Create a new primitive setup/render stage.
1305 struct setup_context
*setup_create_context( struct softpipe_context
*softpipe
)
1307 struct setup_context
*setup
= CALLOC_STRUCT(setup_context
);
1309 setup
->softpipe
= softpipe
;
1311 setup
->quad
.coef
= setup
->coef
;
1312 setup
->quad
.posCoef
= &setup
->posCoef
;