1 /**************************************************************************
3 * Copyright 2007 VMware, Inc.
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 VMWARE 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 <keithw@vmware.com>
35 #include "sp_context.h"
36 #include "sp_screen.h"
38 #include "sp_quad_pipe.h"
41 #include "draw/draw_context.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];
97 struct quad_header quad
[MAX_QUADS
];
98 struct quad_header
*quad_ptrs
[MAX_QUADS
];
101 struct tgsi_interp_coef coef
[PIPE_MAX_SHADER_INPUTS
];
102 struct tgsi_interp_coef posCoef
; /* For Z, W */
105 int left
[2]; /**< [0] = row0, [1] = row1 */
111 uint numFragsEmitted
; /**< per primitive */
112 uint numFragsWritten
; /**< per primitive */
115 unsigned cull_face
; /* which faces cull */
116 unsigned nr_vertex_attrs
;
126 * Clip setup->quad against the scissor/surface bounds.
129 quad_clip(struct setup_context
*setup
, struct quad_header
*quad
)
131 unsigned viewport_index
= quad
[0].input
.viewport_index
;
132 const struct pipe_scissor_state
*cliprect
= &setup
->softpipe
->cliprect
[viewport_index
];
133 const int minx
= (int) cliprect
->minx
;
134 const int maxx
= (int) cliprect
->maxx
;
135 const int miny
= (int) cliprect
->miny
;
136 const int maxy
= (int) cliprect
->maxy
;
138 if (quad
->input
.x0
>= maxx
||
139 quad
->input
.y0
>= maxy
||
140 quad
->input
.x0
+ 1 < minx
||
141 quad
->input
.y0
+ 1 < miny
) {
142 /* totally clipped */
143 quad
->inout
.mask
= 0x0;
146 if (quad
->input
.x0
< minx
)
147 quad
->inout
.mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
148 if (quad
->input
.y0
< miny
)
149 quad
->inout
.mask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
150 if (quad
->input
.x0
== maxx
- 1)
151 quad
->inout
.mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
152 if (quad
->input
.y0
== maxy
- 1)
153 quad
->inout
.mask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
158 * Emit a quad (pass to next stage) with clipping.
161 clip_emit_quad(struct setup_context
*setup
, struct quad_header
*quad
)
163 quad_clip(setup
, quad
);
165 if (quad
->inout
.mask
) {
166 struct softpipe_context
*sp
= setup
->softpipe
;
169 setup
->numFragsEmitted
+= util_bitcount(quad
->inout
.mask
);
172 sp
->quad
.first
->run( sp
->quad
.first
, &quad
, 1 );
179 * Given an X or Y coordinate, return the block/quad coordinate that it
197 * Render a horizontal span of quads
200 flush_spans(struct setup_context
*setup
)
202 const int step
= MAX_QUADS
;
203 const int xleft0
= setup
->span
.left
[0];
204 const int xleft1
= setup
->span
.left
[1];
205 const int xright0
= setup
->span
.right
[0];
206 const int xright1
= setup
->span
.right
[1];
207 struct quad_stage
*pipe
= setup
->softpipe
->quad
.first
;
209 const int minleft
= block_x(MIN2(xleft0
, xleft1
));
210 const int maxright
= MAX2(xright0
, xright1
);
213 /* process quads in horizontal chunks of 16 */
214 for (x
= minleft
; x
< maxright
; x
+= step
) {
215 unsigned skip_left0
= CLAMP(xleft0
- x
, 0, step
);
216 unsigned skip_left1
= CLAMP(xleft1
- x
, 0, step
);
217 unsigned skip_right0
= CLAMP(x
+ step
- xright0
, 0, step
);
218 unsigned skip_right1
= CLAMP(x
+ step
- xright1
, 0, step
);
222 unsigned skipmask_left0
= (1U << skip_left0
) - 1U;
223 unsigned skipmask_left1
= (1U << skip_left1
) - 1U;
225 /* These calculations fail when step == 32 and skip_right == 0.
227 unsigned skipmask_right0
= ~0U << (unsigned)(step
- skip_right0
);
228 unsigned skipmask_right1
= ~0U << (unsigned)(step
- skip_right1
);
230 unsigned mask0
= ~skipmask_left0
& ~skipmask_right0
;
231 unsigned mask1
= ~skipmask_left1
& ~skipmask_right1
;
235 unsigned quadmask
= (mask0
& 3) | ((mask1
& 3) << 2);
237 setup
->quad
[q
].input
.x0
= lx
;
238 setup
->quad
[q
].input
.y0
= setup
->span
.y
;
239 setup
->quad
[q
].input
.facing
= setup
->facing
;
240 setup
->quad
[q
].inout
.mask
= quadmask
;
241 setup
->quad_ptrs
[q
] = &setup
->quad
[q
];
244 setup
->numFragsEmitted
+= util_bitcount(quadmask
);
250 } while (mask0
| mask1
);
252 pipe
->run( pipe
, setup
->quad_ptrs
, q
);
258 setup
->span
.right
[0] = 0;
259 setup
->span
.right
[1] = 0;
260 setup
->span
.left
[0] = 1000000; /* greater than right[0] */
261 setup
->span
.left
[1] = 1000000; /* greater than right[1] */
267 print_vertex(const struct setup_context
*setup
,
271 debug_printf(" Vertex: (%p)\n", (void *) v
);
272 for (i
= 0; i
< setup
->nr_vertex_attrs
; i
++) {
273 debug_printf(" %d: %f %f %f %f\n", i
,
274 v
[i
][0], v
[i
][1], v
[i
][2], v
[i
][3]);
275 if (util_is_inf_or_nan(v
[i
][0])) {
276 debug_printf(" NaN!\n");
284 * Sort the vertices from top to bottom order, setting up the triangle
285 * edge fields (ebot, emaj, etop).
286 * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
289 setup_sort_vertices(struct setup_context
*setup
,
291 const float (*v0
)[4],
292 const float (*v1
)[4],
293 const float (*v2
)[4])
295 if (setup
->softpipe
->rasterizer
->flatshade_first
)
296 setup
->vprovoke
= v0
;
298 setup
->vprovoke
= v2
;
300 /* determine bottom to top order of vertices */
347 setup
->ebot
.dx
= setup
->vmid
[0][0] - setup
->vmin
[0][0];
348 setup
->ebot
.dy
= setup
->vmid
[0][1] - setup
->vmin
[0][1];
349 setup
->emaj
.dx
= setup
->vmax
[0][0] - setup
->vmin
[0][0];
350 setup
->emaj
.dy
= setup
->vmax
[0][1] - setup
->vmin
[0][1];
351 setup
->etop
.dx
= setup
->vmax
[0][0] - setup
->vmid
[0][0];
352 setup
->etop
.dy
= setup
->vmax
[0][1] - setup
->vmid
[0][1];
355 * Compute triangle's area. Use 1/area to compute partial
356 * derivatives of attributes later.
358 * The area will be the same as prim->det, but the sign may be
359 * different depending on how the vertices get sorted above.
361 * To determine whether the primitive is front or back facing we
362 * use the prim->det value because its sign is correct.
365 const float area
= (setup
->emaj
.dx
* setup
->ebot
.dy
-
366 setup
->ebot
.dx
* setup
->emaj
.dy
);
368 setup
->oneoverarea
= 1.0f
/ area
;
371 debug_printf("%s one-over-area %f area %f det %f\n",
372 __FUNCTION__, setup->oneoverarea, area, det );
374 if (util_is_inf_or_nan(setup
->oneoverarea
))
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
381 * 0 = front-facing, 1 = back-facing
385 (setup
->softpipe
->rasterizer
->front_ccw
));
388 unsigned face
= setup
->facing
== 0 ? PIPE_FACE_FRONT
: PIPE_FACE_BACK
;
390 if (face
& setup
->cull_face
)
398 /* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
399 * Input coordinates must be in [0, 1] range, otherwise results are undefined.
400 * Some combinations of coordinates produce invalid results,
401 * but this behaviour is acceptable.
404 tri_apply_cylindrical_wrap(float v0
,
407 uint cylindrical_wrap
,
410 if (cylindrical_wrap
) {
417 else if (delta
< -0.5f
) {
425 else if (delta
< -0.5f
) {
433 else if (delta
< -0.5f
) {
445 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
446 * The value value comes from vertex[slot][i].
447 * The result will be put into setup->coef[slot].a0[i].
448 * \param slot which attribute slot
449 * \param i which component of the slot (0..3)
452 const_coeff(struct setup_context
*setup
,
453 struct tgsi_interp_coef
*coef
,
454 uint vertSlot
, uint i
)
461 /* need provoking vertex info!
463 coef
->a0
[i
] = setup
->vprovoke
[vertSlot
][i
];
468 * Compute a0, dadx and dady for a linearly interpolated coefficient,
470 * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
473 tri_linear_coeff(struct setup_context
*setup
,
474 struct tgsi_interp_coef
*coef
,
478 float botda
= v
[1] - v
[0];
479 float majda
= v
[2] - v
[0];
480 float a
= setup
->ebot
.dy
* majda
- botda
* setup
->emaj
.dy
;
481 float b
= setup
->emaj
.dx
* botda
- majda
* setup
->ebot
.dx
;
482 float dadx
= a
* setup
->oneoverarea
;
483 float dady
= b
* setup
->oneoverarea
;
487 coef
->dadx
[i
] = dadx
;
488 coef
->dady
[i
] = dady
;
490 /* calculate a0 as the value which would be sampled for the
491 * fragment at (0,0), taking into account that we want to sample at
492 * pixel centers, in other words (pixel_offset, pixel_offset).
494 * this is neat but unfortunately not a good way to do things for
495 * triangles with very large values of dadx or dady as it will
496 * result in the subtraction and re-addition from a0 of a very
497 * large number, which means we'll end up loosing a lot of the
498 * fractional bits and precision from a0. the way to fix this is
499 * to define a0 as the sample at a pixel center somewhere near vmin
500 * instead - i'll switch to this later.
502 coef
->a0
[i
] = (v
[0] -
503 (dadx
* (setup
->vmin
[0][0] - setup
->pixel_offset
) +
504 dady
* (setup
->vmin
[0][1] - setup
->pixel_offset
)));
509 * Compute a0, dadx and dady for a perspective-corrected interpolant,
511 * We basically multiply the vertex value by 1/w before computing
512 * the plane coefficients (a0, dadx, dady).
513 * Later, when we compute the value at a particular fragment position we'll
514 * divide the interpolated value by the interpolated W at that fragment.
515 * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
518 tri_persp_coeff(struct setup_context
*setup
,
519 struct tgsi_interp_coef
*coef
,
523 /* premultiply by 1/w (v[0][3] is always W):
525 float mina
= v
[0] * setup
->vmin
[0][3];
526 float mida
= v
[1] * setup
->vmid
[0][3];
527 float maxa
= v
[2] * setup
->vmax
[0][3];
528 float botda
= mida
- mina
;
529 float majda
= maxa
- mina
;
530 float a
= setup
->ebot
.dy
* majda
- botda
* setup
->emaj
.dy
;
531 float b
= setup
->emaj
.dx
* botda
- majda
* setup
->ebot
.dx
;
532 float dadx
= a
* setup
->oneoverarea
;
533 float dady
= b
* setup
->oneoverarea
;
537 coef
->dadx
[i
] = dadx
;
538 coef
->dady
[i
] = dady
;
539 coef
->a0
[i
] = (mina
-
540 (dadx
* (setup
->vmin
[0][0] - setup
->pixel_offset
) +
541 dady
* (setup
->vmin
[0][1] - setup
->pixel_offset
)));
546 * Special coefficient setup for gl_FragCoord.
547 * X and Y are trivial, though Y may have to be inverted for OpenGL.
548 * Z and W are copied from posCoef which should have already been computed.
549 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
552 setup_fragcoord_coeff(struct setup_context
*setup
, uint slot
)
554 const struct tgsi_shader_info
*fsInfo
= &setup
->softpipe
->fs_variant
->info
;
555 boolean origin_lower_left
=
556 fsInfo
->properties
[TGSI_PROPERTY_FS_COORD_ORIGIN
];
557 boolean pixel_center_integer
=
558 fsInfo
->properties
[TGSI_PROPERTY_FS_COORD_PIXEL_CENTER
];
561 setup
->coef
[slot
].a0
[0] = pixel_center_integer
? 0.0f
: 0.5f
;
562 setup
->coef
[slot
].dadx
[0] = 1.0f
;
563 setup
->coef
[slot
].dady
[0] = 0.0f
;
565 setup
->coef
[slot
].a0
[1] =
566 (origin_lower_left
? setup
->softpipe
->framebuffer
.height
-1 : 0)
567 + (pixel_center_integer
? 0.0f
: 0.5f
);
568 setup
->coef
[slot
].dadx
[1] = 0.0f
;
569 setup
->coef
[slot
].dady
[1] = origin_lower_left
? -1.0f
: 1.0f
;
571 setup
->coef
[slot
].a0
[2] = setup
->posCoef
.a0
[2];
572 setup
->coef
[slot
].dadx
[2] = setup
->posCoef
.dadx
[2];
573 setup
->coef
[slot
].dady
[2] = setup
->posCoef
.dady
[2];
575 setup
->coef
[slot
].a0
[3] = setup
->posCoef
.a0
[3];
576 setup
->coef
[slot
].dadx
[3] = setup
->posCoef
.dadx
[3];
577 setup
->coef
[slot
].dady
[3] = setup
->posCoef
.dady
[3];
583 * Compute the setup->coef[] array dadx, dady, a0 values.
584 * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
587 setup_tri_coefficients(struct setup_context
*setup
)
589 struct softpipe_context
*softpipe
= setup
->softpipe
;
590 const struct tgsi_shader_info
*fsInfo
= &setup
->softpipe
->fs_variant
->info
;
591 const struct sp_setup_info
*sinfo
= &softpipe
->setup_info
;
595 assert(sinfo
->valid
);
597 /* z and w are done by linear interpolation:
599 v
[0] = setup
->vmin
[0][2];
600 v
[1] = setup
->vmid
[0][2];
601 v
[2] = setup
->vmax
[0][2];
602 tri_linear_coeff(setup
, &setup
->posCoef
, 2, v
);
604 v
[0] = setup
->vmin
[0][3];
605 v
[1] = setup
->vmid
[0][3];
606 v
[2] = setup
->vmax
[0][3];
607 tri_linear_coeff(setup
, &setup
->posCoef
, 3, v
);
609 /* setup interpolation for all the remaining attributes:
611 for (fragSlot
= 0; fragSlot
< fsInfo
->num_inputs
; fragSlot
++) {
612 const uint vertSlot
= sinfo
->attrib
[fragSlot
].src_index
;
615 switch (sinfo
->attrib
[fragSlot
].interp
) {
616 case SP_INTERP_CONSTANT
:
617 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++) {
618 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
621 case SP_INTERP_LINEAR
:
622 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++) {
623 tri_apply_cylindrical_wrap(setup
->vmin
[vertSlot
][j
],
624 setup
->vmid
[vertSlot
][j
],
625 setup
->vmax
[vertSlot
][j
],
626 fsInfo
->input_cylindrical_wrap
[fragSlot
] & (1 << j
),
628 tri_linear_coeff(setup
, &setup
->coef
[fragSlot
], j
, v
);
631 case SP_INTERP_PERSPECTIVE
:
632 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++) {
633 tri_apply_cylindrical_wrap(setup
->vmin
[vertSlot
][j
],
634 setup
->vmid
[vertSlot
][j
],
635 setup
->vmax
[vertSlot
][j
],
636 fsInfo
->input_cylindrical_wrap
[fragSlot
] & (1 << j
),
638 tri_persp_coeff(setup
, &setup
->coef
[fragSlot
], j
, v
);
642 setup_fragcoord_coeff(setup
, fragSlot
);
648 if (fsInfo
->input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FACE
) {
649 /* convert 0 to 1.0 and 1 to -1.0 */
650 setup
->coef
[fragSlot
].a0
[0] = setup
->facing
* -2.0f
+ 1.0f
;
651 setup
->coef
[fragSlot
].dadx
[0] = 0.0;
652 setup
->coef
[fragSlot
].dady
[0] = 0.0;
656 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++) {
657 debug_printf("attr[%d].%c: a0:%f dx:%f dy:%f\n",
659 setup
->coef
[fragSlot
].a0
[j
],
660 setup
->coef
[fragSlot
].dadx
[j
],
661 setup
->coef
[fragSlot
].dady
[j
]);
669 setup_tri_edges(struct setup_context
*setup
)
671 float vmin_x
= setup
->vmin
[0][0] + setup
->pixel_offset
;
672 float vmid_x
= setup
->vmid
[0][0] + setup
->pixel_offset
;
674 float vmin_y
= setup
->vmin
[0][1] - setup
->pixel_offset
;
675 float vmid_y
= setup
->vmid
[0][1] - setup
->pixel_offset
;
676 float vmax_y
= setup
->vmax
[0][1] - setup
->pixel_offset
;
678 setup
->emaj
.sy
= ceilf(vmin_y
);
679 setup
->emaj
.lines
= (int) ceilf(vmax_y
- setup
->emaj
.sy
);
680 setup
->emaj
.dxdy
= setup
->emaj
.dy
? setup
->emaj
.dx
/ setup
->emaj
.dy
: .0f
;
681 setup
->emaj
.sx
= vmin_x
+ (setup
->emaj
.sy
- vmin_y
) * setup
->emaj
.dxdy
;
683 setup
->etop
.sy
= ceilf(vmid_y
);
684 setup
->etop
.lines
= (int) ceilf(vmax_y
- setup
->etop
.sy
);
685 setup
->etop
.dxdy
= setup
->etop
.dy
? setup
->etop
.dx
/ setup
->etop
.dy
: .0f
;
686 setup
->etop
.sx
= vmid_x
+ (setup
->etop
.sy
- vmid_y
) * setup
->etop
.dxdy
;
688 setup
->ebot
.sy
= ceilf(vmin_y
);
689 setup
->ebot
.lines
= (int) ceilf(vmid_y
- setup
->ebot
.sy
);
690 setup
->ebot
.dxdy
= setup
->ebot
.dy
? setup
->ebot
.dx
/ setup
->ebot
.dy
: .0f
;
691 setup
->ebot
.sx
= vmin_x
+ (setup
->ebot
.sy
- vmin_y
) * setup
->ebot
.dxdy
;
696 * Render the upper or lower half of a triangle.
697 * Scissoring/cliprect is applied here too.
700 subtriangle(struct setup_context
*setup
,
704 unsigned viewport_index
)
706 const struct pipe_scissor_state
*cliprect
= &setup
->softpipe
->cliprect
[viewport_index
];
707 const int minx
= (int) cliprect
->minx
;
708 const int maxx
= (int) cliprect
->maxx
;
709 const int miny
= (int) cliprect
->miny
;
710 const int maxy
= (int) cliprect
->maxy
;
711 int y
, start_y
, finish_y
;
712 int sy
= (int)eleft
->sy
;
714 assert((int)eleft
->sy
== (int) eright
->sy
);
717 /* clip top/bottom */
722 finish_y
= sy
+ lines
;
730 debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
733 for (y
= start_y
; y
< finish_y
; y
++) {
735 /* avoid accumulating adds as floats don't have the precision to
736 * accurately iterate large triangle edges that way. luckily we
737 * can just multiply these days.
739 * this is all drowned out by the attribute interpolation anyway.
741 int left
= (int)(eleft
->sx
+ y
* eleft
->dxdy
);
742 int right
= (int)(eright
->sx
+ y
* eright
->dxdy
);
744 /* clip left/right */
752 if (block(_y
) != setup
->span
.y
) {
754 setup
->span
.y
= block(_y
);
757 setup
->span
.left
[_y
&1] = left
;
758 setup
->span
.right
[_y
&1] = right
;
763 /* save the values so that emaj can be restarted:
765 eleft
->sx
+= lines
* eleft
->dxdy
;
766 eright
->sx
+= lines
* eright
->dxdy
;
773 * Recalculate prim's determinant. This is needed as we don't have
774 * get this information through the vbuf_render interface & we must
778 calc_det(const float (*v0
)[4],
779 const float (*v1
)[4],
780 const float (*v2
)[4])
782 /* edge vectors e = v0 - v2, f = v1 - v2 */
783 const float ex
= v0
[0][0] - v2
[0][0];
784 const float ey
= v0
[0][1] - v2
[0][1];
785 const float fx
= v1
[0][0] - v2
[0][0];
786 const float fy
= v1
[0][1] - v2
[0][1];
788 /* det = cross(e,f).z */
789 return ex
* fy
- ey
* fx
;
794 * Do setup for triangle rasterization, then render the triangle.
797 sp_setup_tri(struct setup_context
*setup
,
798 const float (*v0
)[4],
799 const float (*v1
)[4],
800 const float (*v2
)[4])
804 unsigned viewport_index
= 0;
806 debug_printf("Setup triangle:\n");
807 print_vertex(setup
, v0
);
808 print_vertex(setup
, v1
);
809 print_vertex(setup
, v2
);
812 if (unlikely(sp_debug
& SP_DBG_NO_RAST
) ||
813 setup
->softpipe
->rasterizer
->rasterizer_discard
)
816 det
= calc_det(v0
, v1
, v2
);
818 debug_printf("%s\n", __FUNCTION__ );
822 setup
->numFragsEmitted
= 0;
823 setup
->numFragsWritten
= 0;
826 if (!setup_sort_vertices( setup
, det
, v0
, v1
, v2
))
829 setup_tri_coefficients( setup
);
830 setup_tri_edges( setup
);
832 assert(setup
->softpipe
->reduced_prim
== PIPE_PRIM_TRIANGLES
);
835 setup
->span
.right
[0] = 0;
836 setup
->span
.right
[1] = 0;
837 /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
838 if (setup
->softpipe
->layer_slot
> 0) {
839 layer
= *(unsigned *)setup
->vprovoke
[setup
->softpipe
->layer_slot
];
840 layer
= MIN2(layer
, setup
->max_layer
);
842 setup
->quad
[0].input
.layer
= layer
;
844 if (setup
->softpipe
->viewport_index_slot
> 0) {
845 unsigned *udata
= (unsigned*)v0
[setup
->softpipe
->viewport_index_slot
];
846 viewport_index
= sp_clamp_viewport_idx(*udata
);
848 setup
->quad
[0].input
.viewport_index
= viewport_index
;
850 /* init_constant_attribs( setup ); */
852 if (setup
->oneoverarea
< 0.0) {
855 subtriangle(setup
, &setup
->emaj
, &setup
->ebot
, setup
->ebot
.lines
, viewport_index
);
856 subtriangle(setup
, &setup
->emaj
, &setup
->etop
, setup
->etop
.lines
, viewport_index
);
861 subtriangle(setup
, &setup
->ebot
, &setup
->emaj
, setup
->ebot
.lines
, viewport_index
);
862 subtriangle(setup
, &setup
->etop
, &setup
->emaj
, setup
->etop
.lines
, viewport_index
);
865 flush_spans( setup
);
867 if (setup
->softpipe
->active_statistics_queries
) {
868 setup
->softpipe
->pipeline_statistics
.c_primitives
++;
872 printf("Tri: %u frags emitted, %u written\n",
873 setup
->numFragsEmitted
,
874 setup
->numFragsWritten
);
879 /* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
880 * Input coordinates must be in [0, 1] range, otherwise results are undefined.
883 line_apply_cylindrical_wrap(float v0
,
885 uint cylindrical_wrap
,
888 if (cylindrical_wrap
) {
895 else if (delta
< -0.5f
) {
906 * Compute a0, dadx and dady for a linearly interpolated coefficient,
908 * v[0] and v[1] are vmin and vmax, respectively.
911 line_linear_coeff(const struct setup_context
*setup
,
912 struct tgsi_interp_coef
*coef
,
916 const float da
= v
[1] - v
[0];
917 const float dadx
= da
* setup
->emaj
.dx
* setup
->oneoverarea
;
918 const float dady
= da
* setup
->emaj
.dy
* setup
->oneoverarea
;
919 coef
->dadx
[i
] = dadx
;
920 coef
->dady
[i
] = dady
;
921 coef
->a0
[i
] = (v
[0] -
922 (dadx
* (setup
->vmin
[0][0] - setup
->pixel_offset
) +
923 dady
* (setup
->vmin
[0][1] - setup
->pixel_offset
)));
928 * Compute a0, dadx and dady for a perspective-corrected interpolant,
930 * v[0] and v[1] are vmin and vmax, respectively.
933 line_persp_coeff(const struct setup_context
*setup
,
934 struct tgsi_interp_coef
*coef
,
938 const float a0
= v
[0] * setup
->vmin
[0][3];
939 const float a1
= v
[1] * setup
->vmax
[0][3];
940 const float da
= a1
- a0
;
941 const float dadx
= da
* setup
->emaj
.dx
* setup
->oneoverarea
;
942 const float dady
= da
* setup
->emaj
.dy
* setup
->oneoverarea
;
943 coef
->dadx
[i
] = dadx
;
944 coef
->dady
[i
] = dady
;
946 (dadx
* (setup
->vmin
[0][0] - setup
->pixel_offset
) +
947 dady
* (setup
->vmin
[0][1] - setup
->pixel_offset
)));
952 * Compute the setup->coef[] array dadx, dady, a0 values.
953 * Must be called after setup->vmin,vmax are initialized.
956 setup_line_coefficients(struct setup_context
*setup
,
957 const float (*v0
)[4],
958 const float (*v1
)[4])
960 struct softpipe_context
*softpipe
= setup
->softpipe
;
961 const struct tgsi_shader_info
*fsInfo
= &setup
->softpipe
->fs_variant
->info
;
962 const struct sp_setup_info
*sinfo
= &softpipe
->setup_info
;
967 assert(sinfo
->valid
);
969 /* use setup->vmin, vmax to point to vertices */
970 if (softpipe
->rasterizer
->flatshade_first
)
971 setup
->vprovoke
= v0
;
973 setup
->vprovoke
= v1
;
977 setup
->emaj
.dx
= setup
->vmax
[0][0] - setup
->vmin
[0][0];
978 setup
->emaj
.dy
= setup
->vmax
[0][1] - setup
->vmin
[0][1];
980 /* NOTE: this is not really area but something proportional to it */
981 area
= setup
->emaj
.dx
* setup
->emaj
.dx
+ setup
->emaj
.dy
* setup
->emaj
.dy
;
982 if (area
== 0.0f
|| util_is_inf_or_nan(area
))
984 setup
->oneoverarea
= 1.0f
/ area
;
986 /* z and w are done by linear interpolation:
988 v
[0] = setup
->vmin
[0][2];
989 v
[1] = setup
->vmax
[0][2];
990 line_linear_coeff(setup
, &setup
->posCoef
, 2, v
);
992 v
[0] = setup
->vmin
[0][3];
993 v
[1] = setup
->vmax
[0][3];
994 line_linear_coeff(setup
, &setup
->posCoef
, 3, v
);
996 /* setup interpolation for all the remaining attributes:
998 for (fragSlot
= 0; fragSlot
< fsInfo
->num_inputs
; fragSlot
++) {
999 const uint vertSlot
= sinfo
->attrib
[fragSlot
].src_index
;
1002 switch (sinfo
->attrib
[fragSlot
].interp
) {
1003 case SP_INTERP_CONSTANT
:
1004 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++)
1005 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
1007 case SP_INTERP_LINEAR
:
1008 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++) {
1009 line_apply_cylindrical_wrap(setup
->vmin
[vertSlot
][j
],
1010 setup
->vmax
[vertSlot
][j
],
1011 fsInfo
->input_cylindrical_wrap
[fragSlot
] & (1 << j
),
1013 line_linear_coeff(setup
, &setup
->coef
[fragSlot
], j
, v
);
1016 case SP_INTERP_PERSPECTIVE
:
1017 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++) {
1018 line_apply_cylindrical_wrap(setup
->vmin
[vertSlot
][j
],
1019 setup
->vmax
[vertSlot
][j
],
1020 fsInfo
->input_cylindrical_wrap
[fragSlot
] & (1 << j
),
1022 line_persp_coeff(setup
, &setup
->coef
[fragSlot
], j
, v
);
1026 setup_fragcoord_coeff(setup
, fragSlot
);
1032 if (fsInfo
->input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FACE
) {
1033 /* convert 0 to 1.0 and 1 to -1.0 */
1034 setup
->coef
[fragSlot
].a0
[0] = setup
->facing
* -2.0f
+ 1.0f
;
1035 setup
->coef
[fragSlot
].dadx
[0] = 0.0;
1036 setup
->coef
[fragSlot
].dady
[0] = 0.0;
1044 * Plot a pixel in a line segment.
1047 plot(struct setup_context
*setup
, int x
, int y
)
1049 const int iy
= y
& 1;
1050 const int ix
= x
& 1;
1051 const int quadX
= x
- ix
;
1052 const int quadY
= y
- iy
;
1053 const int mask
= (1 << ix
) << (2 * iy
);
1055 if (quadX
!= setup
->quad
[0].input
.x0
||
1056 quadY
!= setup
->quad
[0].input
.y0
)
1058 /* flush prev quad, start new quad */
1060 if (setup
->quad
[0].input
.x0
!= -1)
1061 clip_emit_quad(setup
, &setup
->quad
[0]);
1063 setup
->quad
[0].input
.x0
= quadX
;
1064 setup
->quad
[0].input
.y0
= quadY
;
1065 setup
->quad
[0].inout
.mask
= 0x0;
1068 setup
->quad
[0].inout
.mask
|= mask
;
1073 * Do setup for line rasterization, then render the line.
1074 * Single-pixel width, no stipple, etc. We rely on the 'draw' module
1075 * to handle stippling and wide lines.
1078 sp_setup_line(struct setup_context
*setup
,
1079 const float (*v0
)[4],
1080 const float (*v1
)[4])
1082 int x0
= (int) v0
[0][0];
1083 int x1
= (int) v1
[0][0];
1084 int y0
= (int) v0
[0][1];
1085 int y1
= (int) v1
[0][1];
1090 unsigned viewport_index
= 0;
1093 debug_printf("Setup line:\n");
1094 print_vertex(setup
, v0
);
1095 print_vertex(setup
, v1
);
1098 if (unlikely(sp_debug
& SP_DBG_NO_RAST
) ||
1099 setup
->softpipe
->rasterizer
->rasterizer_discard
)
1102 if (dx
== 0 && dy
== 0)
1105 if (!setup_line_coefficients(setup
, v0
, v1
))
1108 assert(v0
[0][0] < 1.0e9
);
1109 assert(v0
[0][1] < 1.0e9
);
1110 assert(v1
[0][0] < 1.0e9
);
1111 assert(v1
[0][1] < 1.0e9
);
1114 dx
= -dx
; /* make positive */
1122 dy
= -dy
; /* make positive */
1131 assert(setup
->softpipe
->reduced_prim
== PIPE_PRIM_LINES
);
1133 setup
->quad
[0].input
.x0
= setup
->quad
[0].input
.y0
= -1;
1134 setup
->quad
[0].inout
.mask
= 0x0;
1135 if (setup
->softpipe
->layer_slot
> 0) {
1136 layer
= *(unsigned *)setup
->vprovoke
[setup
->softpipe
->layer_slot
];
1137 layer
= MIN2(layer
, setup
->max_layer
);
1139 setup
->quad
[0].input
.layer
= layer
;
1141 if (setup
->softpipe
->viewport_index_slot
> 0) {
1142 unsigned *udata
= (unsigned*)setup
->vprovoke
[setup
->softpipe
->viewport_index_slot
];
1143 viewport_index
= sp_clamp_viewport_idx(*udata
);
1145 setup
->quad
[0].input
.viewport_index
= viewport_index
;
1147 /* XXX temporary: set coverage to 1.0 so the line appears
1148 * if AA mode happens to be enabled.
1150 setup
->quad
[0].input
.coverage
[0] =
1151 setup
->quad
[0].input
.coverage
[1] =
1152 setup
->quad
[0].input
.coverage
[2] =
1153 setup
->quad
[0].input
.coverage
[3] = 1.0;
1156 /*** X-major line ***/
1158 const int errorInc
= dy
+ dy
;
1159 int error
= errorInc
- dx
;
1160 const int errorDec
= error
- dx
;
1162 for (i
= 0; i
< dx
; i
++) {
1163 plot(setup
, x0
, y0
);
1176 /*** Y-major line ***/
1178 const int errorInc
= dx
+ dx
;
1179 int error
= errorInc
- dy
;
1180 const int errorDec
= error
- dy
;
1182 for (i
= 0; i
< dy
; i
++) {
1183 plot(setup
, x0
, y0
);
1196 /* draw final quad */
1197 if (setup
->quad
[0].inout
.mask
) {
1198 clip_emit_quad(setup
, &setup
->quad
[0]);
1204 point_persp_coeff(const struct setup_context
*setup
,
1205 const float (*vert
)[4],
1206 struct tgsi_interp_coef
*coef
,
1207 uint vertSlot
, uint i
)
1210 coef
->dadx
[i
] = 0.0F
;
1211 coef
->dady
[i
] = 0.0F
;
1212 coef
->a0
[i
] = vert
[vertSlot
][i
] * vert
[0][3];
1217 * Do setup for point rasterization, then render the point.
1218 * Round or square points...
1219 * XXX could optimize a lot for 1-pixel points.
1222 sp_setup_point(struct setup_context
*setup
,
1223 const float (*v0
)[4])
1225 struct softpipe_context
*softpipe
= setup
->softpipe
;
1226 const struct tgsi_shader_info
*fsInfo
= &setup
->softpipe
->fs_variant
->info
;
1227 const int sizeAttr
= setup
->softpipe
->psize_slot
;
1229 = sizeAttr
> 0 ? v0
[sizeAttr
][0]
1230 : setup
->softpipe
->rasterizer
->point_size
;
1231 const float halfSize
= 0.5F
* size
;
1232 const boolean round
= (boolean
) setup
->softpipe
->rasterizer
->point_smooth
;
1233 const float x
= v0
[0][0]; /* Note: data[0] is always position */
1234 const float y
= v0
[0][1];
1235 const struct sp_setup_info
*sinfo
= &softpipe
->setup_info
;
1238 unsigned viewport_index
= 0;
1240 debug_printf("Setup point:\n");
1241 print_vertex(setup
, v0
);
1244 assert(sinfo
->valid
);
1246 if (unlikely(sp_debug
& SP_DBG_NO_RAST
) ||
1247 setup
->softpipe
->rasterizer
->rasterizer_discard
)
1250 assert(setup
->softpipe
->reduced_prim
== PIPE_PRIM_POINTS
);
1252 if (setup
->softpipe
->layer_slot
> 0) {
1253 layer
= *(unsigned *)v0
[setup
->softpipe
->layer_slot
];
1254 layer
= MIN2(layer
, setup
->max_layer
);
1256 setup
->quad
[0].input
.layer
= layer
;
1258 if (setup
->softpipe
->viewport_index_slot
> 0) {
1259 unsigned *udata
= (unsigned*)v0
[setup
->softpipe
->viewport_index_slot
];
1260 viewport_index
= sp_clamp_viewport_idx(*udata
);
1262 setup
->quad
[0].input
.viewport_index
= viewport_index
;
1264 /* For points, all interpolants are constant-valued.
1265 * However, for point sprites, we'll need to setup texcoords appropriately.
1266 * XXX: which coefficients are the texcoords???
1267 * We may do point sprites as textured quads...
1269 * KW: We don't know which coefficients are texcoords - ultimately
1270 * the choice of what interpolation mode to use for each attribute
1271 * should be determined by the fragment program, using
1272 * per-attribute declaration statements that include interpolation
1273 * mode as a parameter. So either the fragment program will have
1274 * to be adjusted for pointsprite vs normal point behaviour, or
1275 * otherwise a special interpolation mode will have to be defined
1276 * which matches the required behaviour for point sprites. But -
1277 * the latter is not a feature of normal hardware, and as such
1278 * probably should be ruled out on that basis.
1280 setup
->vprovoke
= v0
;
1283 const_coeff(setup
, &setup
->posCoef
, 0, 2);
1284 const_coeff(setup
, &setup
->posCoef
, 0, 3);
1286 for (fragSlot
= 0; fragSlot
< fsInfo
->num_inputs
; fragSlot
++) {
1287 const uint vertSlot
= sinfo
->attrib
[fragSlot
].src_index
;
1290 switch (sinfo
->attrib
[fragSlot
].interp
) {
1291 case SP_INTERP_CONSTANT
:
1293 case SP_INTERP_LINEAR
:
1294 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++)
1295 const_coeff(setup
, &setup
->coef
[fragSlot
], vertSlot
, j
);
1297 case SP_INTERP_PERSPECTIVE
:
1298 for (j
= 0; j
< TGSI_NUM_CHANNELS
; j
++)
1299 point_persp_coeff(setup
, setup
->vprovoke
,
1300 &setup
->coef
[fragSlot
], vertSlot
, j
);
1303 setup_fragcoord_coeff(setup
, fragSlot
);
1309 if (fsInfo
->input_semantic_name
[fragSlot
] == TGSI_SEMANTIC_FACE
) {
1310 /* convert 0 to 1.0 and 1 to -1.0 */
1311 setup
->coef
[fragSlot
].a0
[0] = setup
->facing
* -2.0f
+ 1.0f
;
1312 setup
->coef
[fragSlot
].dadx
[0] = 0.0;
1313 setup
->coef
[fragSlot
].dady
[0] = 0.0;
1318 if (halfSize
<= 0.5 && !round
) {
1319 /* special case for 1-pixel points */
1320 const int ix
= ((int) x
) & 1;
1321 const int iy
= ((int) y
) & 1;
1322 setup
->quad
[0].input
.x0
= (int) x
- ix
;
1323 setup
->quad
[0].input
.y0
= (int) y
- iy
;
1324 setup
->quad
[0].inout
.mask
= (1 << ix
) << (2 * iy
);
1325 clip_emit_quad(setup
, &setup
->quad
[0]);
1329 /* rounded points */
1330 const int ixmin
= block((int) (x
- halfSize
));
1331 const int ixmax
= block((int) (x
+ halfSize
));
1332 const int iymin
= block((int) (y
- halfSize
));
1333 const int iymax
= block((int) (y
+ halfSize
));
1334 const float rmin
= halfSize
- 0.7071F
; /* 0.7071 = sqrt(2)/2 */
1335 const float rmax
= halfSize
+ 0.7071F
;
1336 const float rmin2
= MAX2(0.0F
, rmin
* rmin
);
1337 const float rmax2
= rmax
* rmax
;
1338 const float cscale
= 1.0F
/ (rmax2
- rmin2
);
1341 for (iy
= iymin
; iy
<= iymax
; iy
+= 2) {
1342 for (ix
= ixmin
; ix
<= ixmax
; ix
+= 2) {
1343 float dx
, dy
, dist2
, cover
;
1345 setup
->quad
[0].inout
.mask
= 0x0;
1347 dx
= (ix
+ 0.5f
) - x
;
1348 dy
= (iy
+ 0.5f
) - y
;
1349 dist2
= dx
* dx
+ dy
* dy
;
1350 if (dist2
<= rmax2
) {
1351 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1352 setup
->quad
[0].input
.coverage
[QUAD_TOP_LEFT
] = MIN2(cover
, 1.0f
);
1353 setup
->quad
[0].inout
.mask
|= MASK_TOP_LEFT
;
1356 dx
= (ix
+ 1.5f
) - x
;
1357 dy
= (iy
+ 0.5f
) - y
;
1358 dist2
= dx
* dx
+ dy
* dy
;
1359 if (dist2
<= rmax2
) {
1360 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1361 setup
->quad
[0].input
.coverage
[QUAD_TOP_RIGHT
] = MIN2(cover
, 1.0f
);
1362 setup
->quad
[0].inout
.mask
|= MASK_TOP_RIGHT
;
1365 dx
= (ix
+ 0.5f
) - x
;
1366 dy
= (iy
+ 1.5f
) - y
;
1367 dist2
= dx
* dx
+ dy
* dy
;
1368 if (dist2
<= rmax2
) {
1369 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1370 setup
->quad
[0].input
.coverage
[QUAD_BOTTOM_LEFT
] = MIN2(cover
, 1.0f
);
1371 setup
->quad
[0].inout
.mask
|= MASK_BOTTOM_LEFT
;
1374 dx
= (ix
+ 1.5f
) - x
;
1375 dy
= (iy
+ 1.5f
) - y
;
1376 dist2
= dx
* dx
+ dy
* dy
;
1377 if (dist2
<= rmax2
) {
1378 cover
= 1.0F
- (dist2
- rmin2
) * cscale
;
1379 setup
->quad
[0].input
.coverage
[QUAD_BOTTOM_RIGHT
] = MIN2(cover
, 1.0f
);
1380 setup
->quad
[0].inout
.mask
|= MASK_BOTTOM_RIGHT
;
1383 if (setup
->quad
[0].inout
.mask
) {
1384 setup
->quad
[0].input
.x0
= ix
;
1385 setup
->quad
[0].input
.y0
= iy
;
1386 clip_emit_quad(setup
, &setup
->quad
[0]);
1393 const int xmin
= (int) (x
+ 0.75 - halfSize
);
1394 const int ymin
= (int) (y
+ 0.25 - halfSize
);
1395 const int xmax
= xmin
+ (int) size
;
1396 const int ymax
= ymin
+ (int) size
;
1397 /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
1398 const int ixmin
= block(xmin
);
1399 const int ixmax
= block(xmax
- 1);
1400 const int iymin
= block(ymin
);
1401 const int iymax
= block(ymax
- 1);
1405 debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
1407 for (iy
= iymin
; iy
<= iymax
; iy
+= 2) {
1410 /* above the top edge */
1411 rowMask
&= (MASK_BOTTOM_LEFT
| MASK_BOTTOM_RIGHT
);
1413 if (iy
+ 1 >= ymax
) {
1414 /* below the bottom edge */
1415 rowMask
&= (MASK_TOP_LEFT
| MASK_TOP_RIGHT
);
1418 for (ix
= ixmin
; ix
<= ixmax
; ix
+= 2) {
1419 uint mask
= rowMask
;
1422 /* fragment is past left edge of point, turn off left bits */
1423 mask
&= (MASK_BOTTOM_RIGHT
| MASK_TOP_RIGHT
);
1425 if (ix
+ 1 >= xmax
) {
1426 /* past the right edge */
1427 mask
&= (MASK_BOTTOM_LEFT
| MASK_TOP_LEFT
);
1430 setup
->quad
[0].inout
.mask
= mask
;
1431 setup
->quad
[0].input
.x0
= ix
;
1432 setup
->quad
[0].input
.y0
= iy
;
1433 clip_emit_quad(setup
, &setup
->quad
[0]);
1442 * Called by vbuf code just before we start buffering primitives.
1445 sp_setup_prepare(struct setup_context
*setup
)
1447 struct softpipe_context
*sp
= setup
->softpipe
;
1449 unsigned max_layer
= ~0;
1451 softpipe_update_derived(sp
, sp
->reduced_api_prim
);
1454 /* Note: nr_attrs is only used for debugging (vertex printing) */
1455 setup
->nr_vertex_attrs
= draw_num_shader_outputs(sp
->draw
);
1458 * Determine how many layers the fb has (used for clamping layer value).
1459 * OpenGL (but not d3d10) permits different amount of layers per rt, however
1460 * results are undefined if layer exceeds the amount of layers of ANY
1461 * attachment hence don't need separate per cbuf and zsbuf max.
1463 for (i
= 0; i
< setup
->softpipe
->framebuffer
.nr_cbufs
; i
++) {
1464 struct pipe_surface
*cbuf
= setup
->softpipe
->framebuffer
.cbufs
[i
];
1466 max_layer
= MIN2(max_layer
,
1467 cbuf
->u
.tex
.last_layer
- cbuf
->u
.tex
.first_layer
);
1472 /* Prepare pixel offset for rasterisation:
1473 * - pixel center (0.5, 0.5) for GL, or
1474 * - assume (0.0, 0.0) for other APIs.
1476 if (setup
->softpipe
->rasterizer
->half_pixel_center
) {
1477 setup
->pixel_offset
= 0.5f
;
1479 setup
->pixel_offset
= 0.0f
;
1482 setup
->max_layer
= max_layer
;
1484 sp
->quad
.first
->begin( sp
->quad
.first
);
1486 if (sp
->reduced_api_prim
== PIPE_PRIM_TRIANGLES
&&
1487 sp
->rasterizer
->fill_front
== PIPE_POLYGON_MODE_FILL
&&
1488 sp
->rasterizer
->fill_back
== PIPE_POLYGON_MODE_FILL
) {
1489 /* we'll do culling */
1490 setup
->cull_face
= sp
->rasterizer
->cull_face
;
1493 /* 'draw' will do culling */
1494 setup
->cull_face
= PIPE_FACE_NONE
;
1500 sp_setup_destroy_context(struct setup_context
*setup
)
1507 * Create a new primitive setup/render stage.
1509 struct setup_context
*
1510 sp_setup_create_context(struct softpipe_context
*softpipe
)
1512 struct setup_context
*setup
= CALLOC_STRUCT(setup_context
);
1515 setup
->softpipe
= softpipe
;
1517 for (i
= 0; i
< MAX_QUADS
; i
++) {
1518 setup
->quad
[i
].coef
= setup
->coef
;
1519 setup
->quad
[i
].posCoef
= &setup
->posCoef
;
1522 setup
->span
.left
[0] = 1000000; /* greater than right[0] */
1523 setup
->span
.left
[1] = 1000000; /* greater than right[1] */