1 /**************************************************************************
2  *
3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  *
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:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
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.
25  *
26  **************************************************************************/
27 
28 /**
29  * \brief  Primitive rasterization/rendering (points, lines, triangles)
30  *
31  * \author  Keith Whitwell <keith@tungstengraphics.com>
32  * \author  Brian Paul
33  */
34 
35 #include "sp_context.h"
36 #include "sp_quad.h"
37 #include "sp_quad_pipe.h"
38 #include "sp_setup.h"
39 #include "sp_state.h"
40 #include "draw/draw_context.h"
41 #include "draw/draw_vertex.h"
42 #include "pipe/p_shader_tokens.h"
43 #include "util/u_math.h"
44 #include "util/u_memory.h"
45 
46 
47 #define DEBUG_VERTS 0
48 #define DEBUG_FRAGS 0
49 
50 
51 /**
52  * Triangle edge info
53  */
54 struct edge {
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 */
60 };
61 
62 
63 /**
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).
67  */
68 #define MAX_QUADS 16
69 
70 
71 /**
72  * Triangle setup info.
73  * Also used for line drawing (taking some liberties).
74  */
75 struct setup_context {
76    struct softpipe_context *softpipe;
77 
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.
81     */
82    const float (*vmax)[4];
83    const float (*vmid)[4];
84    const float (*vmin)[4];
85    const float (*vprovoke)[4];
86 
87    struct edge ebot;
88    struct edge etop;
89    struct edge emaj;
90 
91    float oneoverarea;
92    int facing;
93 
94    float pixel_offset;
95 
96    struct quad_header quad[MAX_QUADS];
97    struct quad_header *quad_ptrs[MAX_QUADS];
98    unsigned count;
99 
100    struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
101    struct tgsi_interp_coef posCoef;  /* For Z, W */
102 
103    struct {
104       int left[2];   /**< [0] = row0, [1] = row1 */
105       int right[2];
106       int y;
107    } span;
108 
109 #if DEBUG_FRAGS
110    uint numFragsEmitted;  /**< per primitive */
111    uint numFragsWritten;  /**< per primitive */
112 #endif
113 
114    unsigned cull_face;		/* which faces cull */
115    unsigned nr_vertex_attrs;
116 };
117 
118 
119 
120 
121 
122 
123 
124 /**
125  * Clip setup->quad against the scissor/surface bounds.
126  */
127 static INLINE void
quad_clip(struct setup_context * setup,struct quad_header * quad)128 quad_clip(struct setup_context *setup, struct quad_header *quad)
129 {
130    const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
131    const int minx = (int) cliprect->minx;
132    const int maxx = (int) cliprect->maxx;
133    const int miny = (int) cliprect->miny;
134    const int maxy = (int) cliprect->maxy;
135 
136    if (quad->input.x0 >= maxx ||
137        quad->input.y0 >= maxy ||
138        quad->input.x0 + 1 < minx ||
139        quad->input.y0 + 1 < miny) {
140       /* totally clipped */
141       quad->inout.mask = 0x0;
142       return;
143    }
144    if (quad->input.x0 < minx)
145       quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
146    if (quad->input.y0 < miny)
147       quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
148    if (quad->input.x0 == maxx - 1)
149       quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
150    if (quad->input.y0 == maxy - 1)
151       quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
152 }
153 
154 
155 /**
156  * Emit a quad (pass to next stage) with clipping.
157  */
158 static INLINE void
clip_emit_quad(struct setup_context * setup,struct quad_header * quad)159 clip_emit_quad(struct setup_context *setup, struct quad_header *quad)
160 {
161    quad_clip( setup, quad );
162 
163    if (quad->inout.mask) {
164       struct softpipe_context *sp = setup->softpipe;
165 
166 #if DEBUG_FRAGS
167       setup->numFragsEmitted += util_bitcount(quad->inout.mask);
168 #endif
169 
170       sp->quad.first->run( sp->quad.first, &quad, 1 );
171    }
172 }
173 
174 
175 
176 /**
177  * Given an X or Y coordinate, return the block/quad coordinate that it
178  * belongs to.
179  */
180 static INLINE int
block(int x)181 block(int x)
182 {
183    return x & ~(2-1);
184 }
185 
186 
187 static INLINE int
block_x(int x)188 block_x(int x)
189 {
190    return x & ~(16-1);
191 }
192 
193 
194 /**
195  * Render a horizontal span of quads
196  */
197 static void
flush_spans(struct setup_context * setup)198 flush_spans(struct setup_context *setup)
199 {
200    const int step = MAX_QUADS;
201    const int xleft0 = setup->span.left[0];
202    const int xleft1 = setup->span.left[1];
203    const int xright0 = setup->span.right[0];
204    const int xright1 = setup->span.right[1];
205    struct quad_stage *pipe = setup->softpipe->quad.first;
206 
207    const int minleft = block_x(MIN2(xleft0, xleft1));
208    const int maxright = MAX2(xright0, xright1);
209    int x;
210 
211    /* process quads in horizontal chunks of 16 */
212    for (x = minleft; x < maxright; x += step) {
213       unsigned skip_left0 = CLAMP(xleft0 - x, 0, step);
214       unsigned skip_left1 = CLAMP(xleft1 - x, 0, step);
215       unsigned skip_right0 = CLAMP(x + step - xright0, 0, step);
216       unsigned skip_right1 = CLAMP(x + step - xright1, 0, step);
217       unsigned lx = x;
218       unsigned q = 0;
219 
220       unsigned skipmask_left0 = (1U << skip_left0) - 1U;
221       unsigned skipmask_left1 = (1U << skip_left1) - 1U;
222 
223       /* These calculations fail when step == 32 and skip_right == 0.
224        */
225       unsigned skipmask_right0 = ~0U << (unsigned)(step - skip_right0);
226       unsigned skipmask_right1 = ~0U << (unsigned)(step - skip_right1);
227 
228       unsigned mask0 = ~skipmask_left0 & ~skipmask_right0;
229       unsigned mask1 = ~skipmask_left1 & ~skipmask_right1;
230 
231       if (mask0 | mask1) {
232          do {
233             unsigned quadmask = (mask0 & 3) | ((mask1 & 3) << 2);
234             if (quadmask) {
235                setup->quad[q].input.x0 = lx;
236                setup->quad[q].input.y0 = setup->span.y;
237                setup->quad[q].input.facing = setup->facing;
238                setup->quad[q].inout.mask = quadmask;
239                setup->quad_ptrs[q] = &setup->quad[q];
240                q++;
241 #if DEBUG_FRAGS
242                setup->numFragsEmitted += util_bitcount(quadmask);
243 #endif
244             }
245             mask0 >>= 2;
246             mask1 >>= 2;
247             lx += 2;
248          } while (mask0 | mask1);
249 
250          pipe->run( pipe, setup->quad_ptrs, q );
251       }
252    }
253 
254 
255    setup->span.y = 0;
256    setup->span.right[0] = 0;
257    setup->span.right[1] = 0;
258    setup->span.left[0] = 1000000;     /* greater than right[0] */
259    setup->span.left[1] = 1000000;     /* greater than right[1] */
260 }
261 
262 
263 #if DEBUG_VERTS
264 static void
print_vertex(const struct setup_context * setup,const float (* v)[4])265 print_vertex(const struct setup_context *setup,
266              const float (*v)[4])
267 {
268    int i;
269    debug_printf("   Vertex: (%p)\n", (void *) v);
270    for (i = 0; i < setup->nr_vertex_attrs; i++) {
271       debug_printf("     %d: %f %f %f %f\n",  i,
272               v[i][0], v[i][1], v[i][2], v[i][3]);
273       if (util_is_inf_or_nan(v[i][0])) {
274          debug_printf("   NaN!\n");
275       }
276    }
277 }
278 #endif
279 
280 
281 /**
282  * Sort the vertices from top to bottom order, setting up the triangle
283  * edge fields (ebot, emaj, etop).
284  * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
285  */
286 static boolean
setup_sort_vertices(struct setup_context * setup,float det,const float (* v0)[4],const float (* v1)[4],const float (* v2)[4])287 setup_sort_vertices(struct setup_context *setup,
288                     float det,
289                     const float (*v0)[4],
290                     const float (*v1)[4],
291                     const float (*v2)[4])
292 {
293    if (setup->softpipe->rasterizer->flatshade_first)
294       setup->vprovoke = v0;
295    else
296       setup->vprovoke = v2;
297 
298    /* determine bottom to top order of vertices */
299    {
300       float y0 = v0[0][1];
301       float y1 = v1[0][1];
302       float y2 = v2[0][1];
303       if (y0 <= y1) {
304 	 if (y1 <= y2) {
305 	    /* y0<=y1<=y2 */
306 	    setup->vmin = v0;
307 	    setup->vmid = v1;
308 	    setup->vmax = v2;
309 	 }
310 	 else if (y2 <= y0) {
311 	    /* y2<=y0<=y1 */
312 	    setup->vmin = v2;
313 	    setup->vmid = v0;
314 	    setup->vmax = v1;
315 	 }
316 	 else {
317 	    /* y0<=y2<=y1 */
318 	    setup->vmin = v0;
319 	    setup->vmid = v2;
320 	    setup->vmax = v1;
321 	 }
322       }
323       else {
324 	 if (y0 <= y2) {
325 	    /* y1<=y0<=y2 */
326 	    setup->vmin = v1;
327 	    setup->vmid = v0;
328 	    setup->vmax = v2;
329 	 }
330 	 else if (y2 <= y1) {
331 	    /* y2<=y1<=y0 */
332 	    setup->vmin = v2;
333 	    setup->vmid = v1;
334 	    setup->vmax = v0;
335 	 }
336 	 else {
337 	    /* y1<=y2<=y0 */
338 	    setup->vmin = v1;
339 	    setup->vmid = v2;
340 	    setup->vmax = v0;
341 	 }
342       }
343    }
344 
345    setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0];
346    setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1];
347    setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
348    setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
349    setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0];
350    setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1];
351 
352    /*
353     * Compute triangle's area.  Use 1/area to compute partial
354     * derivatives of attributes later.
355     *
356     * The area will be the same as prim->det, but the sign may be
357     * different depending on how the vertices get sorted above.
358     *
359     * To determine whether the primitive is front or back facing we
360     * use the prim->det value because its sign is correct.
361     */
362    {
363       const float area = (setup->emaj.dx * setup->ebot.dy -
364 			    setup->ebot.dx * setup->emaj.dy);
365 
366       setup->oneoverarea = 1.0f / area;
367 
368       /*
369       debug_printf("%s one-over-area %f  area %f  det %f\n",
370                    __FUNCTION__, setup->oneoverarea, area, det );
371       */
372       if (util_is_inf_or_nan(setup->oneoverarea))
373          return FALSE;
374    }
375 
376    /* We need to know if this is a front or back-facing triangle for:
377     *  - the GLSL gl_FrontFacing fragment attribute (bool)
378     *  - two-sided stencil test
379     * 0 = front-facing, 1 = back-facing
380     */
381    setup->facing =
382       ((det < 0.0) ^
383        (setup->softpipe->rasterizer->front_ccw));
384 
385    {
386       unsigned face = setup->facing == 0 ? PIPE_FACE_FRONT : PIPE_FACE_BACK;
387 
388       if (face & setup->cull_face)
389 	 return FALSE;
390    }
391 
392 
393    /* Prepare pixel offset for rasterisation:
394     *  - pixel center (0.5, 0.5) for GL, or
395     *  - assume (0.0, 0.0) for other APIs.
396     */
397    if (setup->softpipe->rasterizer->gl_rasterization_rules) {
398       setup->pixel_offset = 0.5f;
399    } else {
400       setup->pixel_offset = 0.0f;
401    }
402 
403    return TRUE;
404 }
405 
406 
407 /* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
408  * Input coordinates must be in [0, 1] range, otherwise results are undefined.
409  * Some combinations of coordinates produce invalid results,
410  * but this behaviour is acceptable.
411  */
412 static void
tri_apply_cylindrical_wrap(float v0,float v1,float v2,uint cylindrical_wrap,float output[3])413 tri_apply_cylindrical_wrap(float v0,
414                            float v1,
415                            float v2,
416                            uint cylindrical_wrap,
417                            float output[3])
418 {
419    if (cylindrical_wrap) {
420       float delta;
421 
422       delta = v1 - v0;
423       if (delta > 0.5f) {
424          v0 += 1.0f;
425       }
426       else if (delta < -0.5f) {
427          v1 += 1.0f;
428       }
429 
430       delta = v2 - v1;
431       if (delta > 0.5f) {
432          v1 += 1.0f;
433       }
434       else if (delta < -0.5f) {
435          v2 += 1.0f;
436       }
437 
438       delta = v0 - v2;
439       if (delta > 0.5f) {
440          v2 += 1.0f;
441       }
442       else if (delta < -0.5f) {
443          v0 += 1.0f;
444       }
445    }
446 
447    output[0] = v0;
448    output[1] = v1;
449    output[2] = v2;
450 }
451 
452 
453 /**
454  * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
455  * The value value comes from vertex[slot][i].
456  * The result will be put into setup->coef[slot].a0[i].
457  * \param slot  which attribute slot
458  * \param i  which component of the slot (0..3)
459  */
460 static void
const_coeff(struct setup_context * setup,struct tgsi_interp_coef * coef,uint vertSlot,uint i)461 const_coeff(struct setup_context *setup,
462             struct tgsi_interp_coef *coef,
463             uint vertSlot, uint i)
464 {
465    assert(i <= 3);
466 
467    coef->dadx[i] = 0;
468    coef->dady[i] = 0;
469 
470    /* need provoking vertex info!
471     */
472    coef->a0[i] = setup->vprovoke[vertSlot][i];
473 }
474 
475 
476 /**
477  * Compute a0, dadx and dady for a linearly interpolated coefficient,
478  * for a triangle.
479  * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
480  */
481 static void
tri_linear_coeff(struct setup_context * setup,struct tgsi_interp_coef * coef,uint i,const float v[3])482 tri_linear_coeff(struct setup_context *setup,
483                  struct tgsi_interp_coef *coef,
484                  uint i,
485                  const float v[3])
486 {
487    float botda = v[1] - v[0];
488    float majda = v[2] - v[0];
489    float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
490    float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
491    float dadx = a * setup->oneoverarea;
492    float dady = b * setup->oneoverarea;
493 
494    assert(i <= 3);
495 
496    coef->dadx[i] = dadx;
497    coef->dady[i] = dady;
498 
499    /* calculate a0 as the value which would be sampled for the
500     * fragment at (0,0), taking into account that we want to sample at
501     * pixel centers, in other words (pixel_offset, pixel_offset).
502     *
503     * this is neat but unfortunately not a good way to do things for
504     * triangles with very large values of dadx or dady as it will
505     * result in the subtraction and re-addition from a0 of a very
506     * large number, which means we'll end up loosing a lot of the
507     * fractional bits and precision from a0.  the way to fix this is
508     * to define a0 as the sample at a pixel center somewhere near vmin
509     * instead - i'll switch to this later.
510     */
511    coef->a0[i] = (v[0] -
512                   (dadx * (setup->vmin[0][0] - setup->pixel_offset) +
513                    dady * (setup->vmin[0][1] - setup->pixel_offset)));
514 
515    /*
516    debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
517 		slot, "xyzw"[i],
518 		setup->coef[slot].a0[i],
519 		setup->coef[slot].dadx[i],
520 		setup->coef[slot].dady[i]);
521    */
522 }
523 
524 
525 /**
526  * Compute a0, dadx and dady for a perspective-corrected interpolant,
527  * for a triangle.
528  * We basically multiply the vertex value by 1/w before computing
529  * the plane coefficients (a0, dadx, dady).
530  * Later, when we compute the value at a particular fragment position we'll
531  * divide the interpolated value by the interpolated W at that fragment.
532  * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
533  */
534 static void
tri_persp_coeff(struct setup_context * setup,struct tgsi_interp_coef * coef,uint i,const float v[3])535 tri_persp_coeff(struct setup_context *setup,
536                 struct tgsi_interp_coef *coef,
537                 uint i,
538                 const float v[3])
539 {
540    /* premultiply by 1/w  (v[0][3] is always W):
541     */
542    float mina = v[0] * setup->vmin[0][3];
543    float mida = v[1] * setup->vmid[0][3];
544    float maxa = v[2] * setup->vmax[0][3];
545    float botda = mida - mina;
546    float majda = maxa - mina;
547    float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
548    float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
549    float dadx = a * setup->oneoverarea;
550    float dady = b * setup->oneoverarea;
551 
552    /*
553    debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
554           	setup->vmin[vertSlot][i],
555           	setup->vmid[vertSlot][i],
556        		setup->vmax[vertSlot][i]
557           );
558    */
559    assert(i <= 3);
560 
561    coef->dadx[i] = dadx;
562    coef->dady[i] = dady;
563    coef->a0[i] = (mina -
564                   (dadx * (setup->vmin[0][0] - setup->pixel_offset) +
565                    dady * (setup->vmin[0][1] - setup->pixel_offset)));
566 }
567 
568 
569 /**
570  * Special coefficient setup for gl_FragCoord.
571  * X and Y are trivial, though Y may have to be inverted for OpenGL.
572  * Z and W are copied from posCoef which should have already been computed.
573  * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
574  */
575 static void
setup_fragcoord_coeff(struct setup_context * setup,uint slot)576 setup_fragcoord_coeff(struct setup_context *setup, uint slot)
577 {
578    const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
579 
580    /*X*/
581    setup->coef[slot].a0[0] = fsInfo->pixel_center_integer ? 0.0 : 0.5;
582    setup->coef[slot].dadx[0] = 1.0;
583    setup->coef[slot].dady[0] = 0.0;
584    /*Y*/
585    setup->coef[slot].a0[1] =
586 		   (fsInfo->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
587 		   + (fsInfo->pixel_center_integer ? 0.0 : 0.5);
588    setup->coef[slot].dadx[1] = 0.0;
589    setup->coef[slot].dady[1] = fsInfo->origin_lower_left ? -1.0 : 1.0;
590    /*Z*/
591    setup->coef[slot].a0[2] = setup->posCoef.a0[2];
592    setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
593    setup->coef[slot].dady[2] = setup->posCoef.dady[2];
594    /*W*/
595    setup->coef[slot].a0[3] = setup->posCoef.a0[3];
596    setup->coef[slot].dadx[3] = setup->posCoef.dadx[3];
597    setup->coef[slot].dady[3] = setup->posCoef.dady[3];
598 }
599 
600 
601 
602 /**
603  * Compute the setup->coef[] array dadx, dady, a0 values.
604  * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
605  */
606 static void
setup_tri_coefficients(struct setup_context * setup)607 setup_tri_coefficients(struct setup_context *setup)
608 {
609    struct softpipe_context *softpipe = setup->softpipe;
610    const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
611    const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
612    uint fragSlot;
613    float v[3];
614 
615    /* z and w are done by linear interpolation:
616     */
617    v[0] = setup->vmin[0][2];
618    v[1] = setup->vmid[0][2];
619    v[2] = setup->vmax[0][2];
620    tri_linear_coeff(setup, &setup->posCoef, 2, v);
621 
622    v[0] = setup->vmin[0][3];
623    v[1] = setup->vmid[0][3];
624    v[2] = setup->vmax[0][3];
625    tri_linear_coeff(setup, &setup->posCoef, 3, v);
626 
627    /* setup interpolation for all the remaining attributes:
628     */
629    for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
630       const uint vertSlot = vinfo->attrib[fragSlot].src_index;
631       uint j;
632 
633       switch (vinfo->attrib[fragSlot].interp_mode) {
634       case INTERP_CONSTANT:
635          for (j = 0; j < TGSI_NUM_CHANNELS; j++)
636             const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
637          break;
638       case INTERP_LINEAR:
639          for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
640             tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
641                                        setup->vmid[vertSlot][j],
642                                        setup->vmax[vertSlot][j],
643                                        fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
644                                        v);
645             tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
646          }
647          break;
648       case INTERP_PERSPECTIVE:
649          for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
650             tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
651                                        setup->vmid[vertSlot][j],
652                                        setup->vmax[vertSlot][j],
653                                        fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
654                                        v);
655             tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
656          }
657          break;
658       case INTERP_POS:
659          setup_fragcoord_coeff(setup, fragSlot);
660          break;
661       default:
662          assert(0);
663       }
664 
665       if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
666          /* convert 0 to 1.0 and 1 to -1.0 */
667          setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
668          setup->coef[fragSlot].dadx[0] = 0.0;
669          setup->coef[fragSlot].dady[0] = 0.0;
670       }
671    }
672 }
673 
674 
675 static void
setup_tri_edges(struct setup_context * setup)676 setup_tri_edges(struct setup_context *setup)
677 {
678    float vmin_x = setup->vmin[0][0] + setup->pixel_offset;
679    float vmid_x = setup->vmid[0][0] + setup->pixel_offset;
680 
681    float vmin_y = setup->vmin[0][1] - setup->pixel_offset;
682    float vmid_y = setup->vmid[0][1] - setup->pixel_offset;
683    float vmax_y = setup->vmax[0][1] - setup->pixel_offset;
684 
685    setup->emaj.sy = ceilf(vmin_y);
686    setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
687    setup->emaj.dxdy = setup->emaj.dy ? setup->emaj.dx / setup->emaj.dy : .0f;
688    setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
689 
690    setup->etop.sy = ceilf(vmid_y);
691    setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
692    setup->etop.dxdy = setup->etop.dy ? setup->etop.dx / setup->etop.dy : .0f;
693    setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
694 
695    setup->ebot.sy = ceilf(vmin_y);
696    setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
697    setup->ebot.dxdy = setup->ebot.dy ? setup->ebot.dx / setup->ebot.dy : .0f;
698    setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
699 }
700 
701 
702 /**
703  * Render the upper or lower half of a triangle.
704  * Scissoring/cliprect is applied here too.
705  */
706 static void
subtriangle(struct setup_context * setup,struct edge * eleft,struct edge * eright,int lines)707 subtriangle(struct setup_context *setup,
708             struct edge *eleft,
709             struct edge *eright,
710             int lines)
711 {
712    const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
713    const int minx = (int) cliprect->minx;
714    const int maxx = (int) cliprect->maxx;
715    const int miny = (int) cliprect->miny;
716    const int maxy = (int) cliprect->maxy;
717    int y, start_y, finish_y;
718    int sy = (int)eleft->sy;
719 
720    assert((int)eleft->sy == (int) eright->sy);
721    assert(lines >= 0);
722 
723    /* clip top/bottom */
724    start_y = sy;
725    if (start_y < miny)
726       start_y = miny;
727 
728    finish_y = sy + lines;
729    if (finish_y > maxy)
730       finish_y = maxy;
731 
732    start_y -= sy;
733    finish_y -= sy;
734 
735    /*
736    debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
737    */
738 
739    for (y = start_y; y < finish_y; y++) {
740 
741       /* avoid accumulating adds as floats don't have the precision to
742        * accurately iterate large triangle edges that way.  luckily we
743        * can just multiply these days.
744        *
745        * this is all drowned out by the attribute interpolation anyway.
746        */
747       int left = (int)(eleft->sx + y * eleft->dxdy);
748       int right = (int)(eright->sx + y * eright->dxdy);
749 
750       /* clip left/right */
751       if (left < minx)
752          left = minx;
753       if (right > maxx)
754          right = maxx;
755 
756       if (left < right) {
757          int _y = sy + y;
758          if (block(_y) != setup->span.y) {
759             flush_spans(setup);
760             setup->span.y = block(_y);
761          }
762 
763          setup->span.left[_y&1] = left;
764          setup->span.right[_y&1] = right;
765       }
766    }
767 
768 
769    /* save the values so that emaj can be restarted:
770     */
771    eleft->sx += lines * eleft->dxdy;
772    eright->sx += lines * eright->dxdy;
773    eleft->sy += lines;
774    eright->sy += lines;
775 }
776 
777 
778 /**
779  * Recalculate prim's determinant.  This is needed as we don't have
780  * get this information through the vbuf_render interface & we must
781  * calculate it here.
782  */
783 static float
calc_det(const float (* v0)[4],const float (* v1)[4],const float (* v2)[4])784 calc_det(const float (*v0)[4],
785          const float (*v1)[4],
786          const float (*v2)[4])
787 {
788    /* edge vectors e = v0 - v2, f = v1 - v2 */
789    const float ex = v0[0][0] - v2[0][0];
790    const float ey = v0[0][1] - v2[0][1];
791    const float fx = v1[0][0] - v2[0][0];
792    const float fy = v1[0][1] - v2[0][1];
793 
794    /* det = cross(e,f).z */
795    return ex * fy - ey * fx;
796 }
797 
798 
799 /**
800  * Do setup for triangle rasterization, then render the triangle.
801  */
802 void
sp_setup_tri(struct setup_context * setup,const float (* v0)[4],const float (* v1)[4],const float (* v2)[4])803 sp_setup_tri(struct setup_context *setup,
804              const float (*v0)[4],
805              const float (*v1)[4],
806              const float (*v2)[4])
807 {
808    float det;
809 
810 #if DEBUG_VERTS
811    debug_printf("Setup triangle:\n");
812    print_vertex(setup, v0);
813    print_vertex(setup, v1);
814    print_vertex(setup, v2);
815 #endif
816 
817    if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
818       return;
819 
820    det = calc_det(v0, v1, v2);
821    /*
822    debug_printf("%s\n", __FUNCTION__ );
823    */
824 
825 #if DEBUG_FRAGS
826    setup->numFragsEmitted = 0;
827    setup->numFragsWritten = 0;
828 #endif
829 
830    if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
831       return;
832 
833    setup_tri_coefficients( setup );
834    setup_tri_edges( setup );
835 
836    assert(setup->softpipe->reduced_prim == PIPE_PRIM_TRIANGLES);
837 
838    setup->span.y = 0;
839    setup->span.right[0] = 0;
840    setup->span.right[1] = 0;
841    /*   setup->span.z_mode = tri_z_mode( setup->ctx ); */
842 
843    /*   init_constant_attribs( setup ); */
844 
845    if (setup->oneoverarea < 0.0) {
846       /* emaj on left:
847        */
848       subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
849       subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
850    }
851    else {
852       /* emaj on right:
853        */
854       subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
855       subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
856    }
857 
858    flush_spans( setup );
859 
860 #if DEBUG_FRAGS
861    printf("Tri: %u frags emitted, %u written\n",
862           setup->numFragsEmitted,
863           setup->numFragsWritten);
864 #endif
865 }
866 
867 
868 /* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
869  * Input coordinates must be in [0, 1] range, otherwise results are undefined.
870  */
871 static void
line_apply_cylindrical_wrap(float v0,float v1,uint cylindrical_wrap,float output[2])872 line_apply_cylindrical_wrap(float v0,
873                             float v1,
874                             uint cylindrical_wrap,
875                             float output[2])
876 {
877    if (cylindrical_wrap) {
878       float delta;
879 
880       delta = v1 - v0;
881       if (delta > 0.5f) {
882          v0 += 1.0f;
883       }
884       else if (delta < -0.5f) {
885          v1 += 1.0f;
886       }
887    }
888 
889    output[0] = v0;
890    output[1] = v1;
891 }
892 
893 
894 /**
895  * Compute a0, dadx and dady for a linearly interpolated coefficient,
896  * for a line.
897  * v[0] and v[1] are vmin and vmax, respectively.
898  */
899 static void
line_linear_coeff(const struct setup_context * setup,struct tgsi_interp_coef * coef,uint i,const float v[2])900 line_linear_coeff(const struct setup_context *setup,
901                   struct tgsi_interp_coef *coef,
902                   uint i,
903                   const float v[2])
904 {
905    const float da = v[1] - v[0];
906    const float dadx = da * setup->emaj.dx * setup->oneoverarea;
907    const float dady = da * setup->emaj.dy * setup->oneoverarea;
908    coef->dadx[i] = dadx;
909    coef->dady[i] = dady;
910    coef->a0[i] = (v[0] -
911                   (dadx * (setup->vmin[0][0] - setup->pixel_offset) +
912                    dady * (setup->vmin[0][1] - setup->pixel_offset)));
913 }
914 
915 
916 /**
917  * Compute a0, dadx and dady for a perspective-corrected interpolant,
918  * for a line.
919  * v[0] and v[1] are vmin and vmax, respectively.
920  */
921 static void
line_persp_coeff(const struct setup_context * setup,struct tgsi_interp_coef * coef,uint i,const float v[2])922 line_persp_coeff(const struct setup_context *setup,
923                  struct tgsi_interp_coef *coef,
924                  uint i,
925                  const float v[2])
926 {
927    const float a0 = v[0] * setup->vmin[0][3];
928    const float a1 = v[1] * setup->vmax[0][3];
929    const float da = a1 - a0;
930    const float dadx = da * setup->emaj.dx * setup->oneoverarea;
931    const float dady = da * setup->emaj.dy * setup->oneoverarea;
932    coef->dadx[i] = dadx;
933    coef->dady[i] = dady;
934    coef->a0[i] = (a0 -
935                   (dadx * (setup->vmin[0][0] - setup->pixel_offset) +
936                    dady * (setup->vmin[0][1] - setup->pixel_offset)));
937 }
938 
939 
940 /**
941  * Compute the setup->coef[] array dadx, dady, a0 values.
942  * Must be called after setup->vmin,vmax are initialized.
943  */
944 static boolean
setup_line_coefficients(struct setup_context * setup,const float (* v0)[4],const float (* v1)[4])945 setup_line_coefficients(struct setup_context *setup,
946                         const float (*v0)[4],
947                         const float (*v1)[4])
948 {
949    struct softpipe_context *softpipe = setup->softpipe;
950    const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
951    const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
952    uint fragSlot;
953    float area;
954    float v[2];
955 
956    /* use setup->vmin, vmax to point to vertices */
957    if (softpipe->rasterizer->flatshade_first)
958       setup->vprovoke = v0;
959    else
960       setup->vprovoke = v1;
961    setup->vmin = v0;
962    setup->vmax = v1;
963 
964    setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
965    setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
966 
967    /* NOTE: this is not really area but something proportional to it */
968    area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy;
969    if (area == 0.0f || util_is_inf_or_nan(area))
970       return FALSE;
971    setup->oneoverarea = 1.0f / area;
972 
973    /* z and w are done by linear interpolation:
974     */
975    v[0] = setup->vmin[0][2];
976    v[1] = setup->vmax[0][2];
977    line_linear_coeff(setup, &setup->posCoef, 2, v);
978 
979    v[0] = setup->vmin[0][3];
980    v[1] = setup->vmax[0][3];
981    line_linear_coeff(setup, &setup->posCoef, 3, v);
982 
983    /* setup interpolation for all the remaining attributes:
984     */
985    for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
986       const uint vertSlot = vinfo->attrib[fragSlot].src_index;
987       uint j;
988 
989       switch (vinfo->attrib[fragSlot].interp_mode) {
990       case INTERP_CONSTANT:
991          for (j = 0; j < TGSI_NUM_CHANNELS; j++)
992             const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
993          break;
994       case INTERP_LINEAR:
995          for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
996             line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
997                                         setup->vmax[vertSlot][j],
998                                         fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
999                                         v);
1000             line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
1001          }
1002          break;
1003       case INTERP_PERSPECTIVE:
1004          for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
1005             line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
1006                                         setup->vmax[vertSlot][j],
1007                                         fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
1008                                         v);
1009             line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
1010          }
1011          break;
1012       case INTERP_POS:
1013          setup_fragcoord_coeff(setup, fragSlot);
1014          break;
1015       default:
1016          assert(0);
1017       }
1018 
1019       if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
1020          /* convert 0 to 1.0 and 1 to -1.0 */
1021          setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
1022          setup->coef[fragSlot].dadx[0] = 0.0;
1023          setup->coef[fragSlot].dady[0] = 0.0;
1024       }
1025    }
1026    return TRUE;
1027 }
1028 
1029 
1030 /**
1031  * Plot a pixel in a line segment.
1032  */
1033 static INLINE void
plot(struct setup_context * setup,int x,int y)1034 plot(struct setup_context *setup, int x, int y)
1035 {
1036    const int iy = y & 1;
1037    const int ix = x & 1;
1038    const int quadX = x - ix;
1039    const int quadY = y - iy;
1040    const int mask = (1 << ix) << (2 * iy);
1041 
1042    if (quadX != setup->quad[0].input.x0 ||
1043        quadY != setup->quad[0].input.y0)
1044    {
1045       /* flush prev quad, start new quad */
1046 
1047       if (setup->quad[0].input.x0 != -1)
1048          clip_emit_quad( setup, &setup->quad[0] );
1049 
1050       setup->quad[0].input.x0 = quadX;
1051       setup->quad[0].input.y0 = quadY;
1052       setup->quad[0].inout.mask = 0x0;
1053    }
1054 
1055    setup->quad[0].inout.mask |= mask;
1056 }
1057 
1058 
1059 /**
1060  * Do setup for line rasterization, then render the line.
1061  * Single-pixel width, no stipple, etc.  We rely on the 'draw' module
1062  * to handle stippling and wide lines.
1063  */
1064 void
sp_setup_line(struct setup_context * setup,const float (* v0)[4],const float (* v1)[4])1065 sp_setup_line(struct setup_context *setup,
1066               const float (*v0)[4],
1067               const float (*v1)[4])
1068 {
1069    int x0 = (int) v0[0][0];
1070    int x1 = (int) v1[0][0];
1071    int y0 = (int) v0[0][1];
1072    int y1 = (int) v1[0][1];
1073    int dx = x1 - x0;
1074    int dy = y1 - y0;
1075    int xstep, ystep;
1076 
1077 #if DEBUG_VERTS
1078    debug_printf("Setup line:\n");
1079    print_vertex(setup, v0);
1080    print_vertex(setup, v1);
1081 #endif
1082 
1083    if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
1084       return;
1085 
1086    if (dx == 0 && dy == 0)
1087       return;
1088 
1089    if (!setup_line_coefficients(setup, v0, v1))
1090       return;
1091 
1092    assert(v0[0][0] < 1.0e9);
1093    assert(v0[0][1] < 1.0e9);
1094    assert(v1[0][0] < 1.0e9);
1095    assert(v1[0][1] < 1.0e9);
1096 
1097    if (dx < 0) {
1098       dx = -dx;   /* make positive */
1099       xstep = -1;
1100    }
1101    else {
1102       xstep = 1;
1103    }
1104 
1105    if (dy < 0) {
1106       dy = -dy;   /* make positive */
1107       ystep = -1;
1108    }
1109    else {
1110       ystep = 1;
1111    }
1112 
1113    assert(dx >= 0);
1114    assert(dy >= 0);
1115    assert(setup->softpipe->reduced_prim == PIPE_PRIM_LINES);
1116 
1117    setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1;
1118    setup->quad[0].inout.mask = 0x0;
1119 
1120    /* XXX temporary: set coverage to 1.0 so the line appears
1121     * if AA mode happens to be enabled.
1122     */
1123    setup->quad[0].input.coverage[0] =
1124    setup->quad[0].input.coverage[1] =
1125    setup->quad[0].input.coverage[2] =
1126    setup->quad[0].input.coverage[3] = 1.0;
1127 
1128    if (dx > dy) {
1129       /*** X-major line ***/
1130       int i;
1131       const int errorInc = dy + dy;
1132       int error = errorInc - dx;
1133       const int errorDec = error - dx;
1134 
1135       for (i = 0; i < dx; i++) {
1136          plot(setup, x0, y0);
1137 
1138          x0 += xstep;
1139          if (error < 0) {
1140             error += errorInc;
1141          }
1142          else {
1143             error += errorDec;
1144             y0 += ystep;
1145          }
1146       }
1147    }
1148    else {
1149       /*** Y-major line ***/
1150       int i;
1151       const int errorInc = dx + dx;
1152       int error = errorInc - dy;
1153       const int errorDec = error - dy;
1154 
1155       for (i = 0; i < dy; i++) {
1156          plot(setup, x0, y0);
1157 
1158          y0 += ystep;
1159          if (error < 0) {
1160             error += errorInc;
1161          }
1162          else {
1163             error += errorDec;
1164             x0 += xstep;
1165          }
1166       }
1167    }
1168 
1169    /* draw final quad */
1170    if (setup->quad[0].inout.mask) {
1171       clip_emit_quad( setup, &setup->quad[0] );
1172    }
1173 }
1174 
1175 
1176 static void
point_persp_coeff(const struct setup_context * setup,const float (* vert)[4],struct tgsi_interp_coef * coef,uint vertSlot,uint i)1177 point_persp_coeff(const struct setup_context *setup,
1178                   const float (*vert)[4],
1179                   struct tgsi_interp_coef *coef,
1180                   uint vertSlot, uint i)
1181 {
1182    assert(i <= 3);
1183    coef->dadx[i] = 0.0F;
1184    coef->dady[i] = 0.0F;
1185    coef->a0[i] = vert[vertSlot][i] * vert[0][3];
1186 }
1187 
1188 
1189 /**
1190  * Do setup for point rasterization, then render the point.
1191  * Round or square points...
1192  * XXX could optimize a lot for 1-pixel points.
1193  */
1194 void
sp_setup_point(struct setup_context * setup,const float (* v0)[4])1195 sp_setup_point(struct setup_context *setup,
1196                const float (*v0)[4])
1197 {
1198    struct softpipe_context *softpipe = setup->softpipe;
1199    const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
1200    const int sizeAttr = setup->softpipe->psize_slot;
1201    const float size
1202       = sizeAttr > 0 ? v0[sizeAttr][0]
1203       : setup->softpipe->rasterizer->point_size;
1204    const float halfSize = 0.5F * size;
1205    const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth;
1206    const float x = v0[0][0];  /* Note: data[0] is always position */
1207    const float y = v0[0][1];
1208    const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
1209    uint fragSlot;
1210 
1211 #if DEBUG_VERTS
1212    debug_printf("Setup point:\n");
1213    print_vertex(setup, v0);
1214 #endif
1215 
1216    if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
1217       return;
1218 
1219    assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS);
1220 
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...
1225     *
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.
1236     */
1237    setup->vprovoke = v0;
1238 
1239    /* setup Z, W */
1240    const_coeff(setup, &setup->posCoef, 0, 2);
1241    const_coeff(setup, &setup->posCoef, 0, 3);
1242 
1243    for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
1244       const uint vertSlot = vinfo->attrib[fragSlot].src_index;
1245       uint j;
1246 
1247       switch (vinfo->attrib[fragSlot].interp_mode) {
1248       case INTERP_CONSTANT:
1249          /* fall-through */
1250       case INTERP_LINEAR:
1251          for (j = 0; j < TGSI_NUM_CHANNELS; j++)
1252             const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
1253          break;
1254       case INTERP_PERSPECTIVE:
1255          for (j = 0; j < TGSI_NUM_CHANNELS; j++)
1256             point_persp_coeff(setup, setup->vprovoke,
1257                               &setup->coef[fragSlot], vertSlot, j);
1258          break;
1259       case INTERP_POS:
1260          setup_fragcoord_coeff(setup, fragSlot);
1261          break;
1262       default:
1263          assert(0);
1264       }
1265 
1266       if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
1267          /* convert 0 to 1.0 and 1 to -1.0 */
1268          setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
1269          setup->coef[fragSlot].dadx[0] = 0.0;
1270          setup->coef[fragSlot].dady[0] = 0.0;
1271       }
1272    }
1273 
1274 
1275    if (halfSize <= 0.5 && !round) {
1276       /* special case for 1-pixel points */
1277       const int ix = ((int) x) & 1;
1278       const int iy = ((int) y) & 1;
1279       setup->quad[0].input.x0 = (int) x - ix;
1280       setup->quad[0].input.y0 = (int) y - iy;
1281       setup->quad[0].inout.mask = (1 << ix) << (2 * iy);
1282       clip_emit_quad( setup, &setup->quad[0] );
1283    }
1284    else {
1285       if (round) {
1286          /* rounded points */
1287          const int ixmin = block((int) (x - halfSize));
1288          const int ixmax = block((int) (x + halfSize));
1289          const int iymin = block((int) (y - halfSize));
1290          const int iymax = block((int) (y + halfSize));
1291          const float rmin = halfSize - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
1292          const float rmax = halfSize + 0.7071F;
1293          const float rmin2 = MAX2(0.0F, rmin * rmin);
1294          const float rmax2 = rmax * rmax;
1295          const float cscale = 1.0F / (rmax2 - rmin2);
1296          int ix, iy;
1297 
1298          for (iy = iymin; iy <= iymax; iy += 2) {
1299             for (ix = ixmin; ix <= ixmax; ix += 2) {
1300                float dx, dy, dist2, cover;
1301 
1302                setup->quad[0].inout.mask = 0x0;
1303 
1304                dx = (ix + 0.5f) - x;
1305                dy = (iy + 0.5f) - y;
1306                dist2 = dx * dx + dy * dy;
1307                if (dist2 <= rmax2) {
1308                   cover = 1.0F - (dist2 - rmin2) * cscale;
1309                   setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
1310                   setup->quad[0].inout.mask |= MASK_TOP_LEFT;
1311                }
1312 
1313                dx = (ix + 1.5f) - x;
1314                dy = (iy + 0.5f) - y;
1315                dist2 = dx * dx + dy * dy;
1316                if (dist2 <= rmax2) {
1317                   cover = 1.0F - (dist2 - rmin2) * cscale;
1318                   setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
1319                   setup->quad[0].inout.mask |= MASK_TOP_RIGHT;
1320                }
1321 
1322                dx = (ix + 0.5f) - x;
1323                dy = (iy + 1.5f) - y;
1324                dist2 = dx * dx + dy * dy;
1325                if (dist2 <= rmax2) {
1326                   cover = 1.0F - (dist2 - rmin2) * cscale;
1327                   setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
1328                   setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT;
1329                }
1330 
1331                dx = (ix + 1.5f) - x;
1332                dy = (iy + 1.5f) - y;
1333                dist2 = dx * dx + dy * dy;
1334                if (dist2 <= rmax2) {
1335                   cover = 1.0F - (dist2 - rmin2) * cscale;
1336                   setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
1337                   setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT;
1338                }
1339 
1340                if (setup->quad[0].inout.mask) {
1341                   setup->quad[0].input.x0 = ix;
1342                   setup->quad[0].input.y0 = iy;
1343                   clip_emit_quad( setup, &setup->quad[0] );
1344                }
1345             }
1346          }
1347       }
1348       else {
1349          /* square points */
1350          const int xmin = (int) (x + 0.75 - halfSize);
1351          const int ymin = (int) (y + 0.25 - halfSize);
1352          const int xmax = xmin + (int) size;
1353          const int ymax = ymin + (int) size;
1354          /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
1355          const int ixmin = block(xmin);
1356          const int ixmax = block(xmax - 1);
1357          const int iymin = block(ymin);
1358          const int iymax = block(ymax - 1);
1359          int ix, iy;
1360 
1361          /*
1362          debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
1363          */
1364          for (iy = iymin; iy <= iymax; iy += 2) {
1365             uint rowMask = 0xf;
1366             if (iy < ymin) {
1367                /* above the top edge */
1368                rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
1369             }
1370             if (iy + 1 >= ymax) {
1371                /* below the bottom edge */
1372                rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
1373             }
1374 
1375             for (ix = ixmin; ix <= ixmax; ix += 2) {
1376                uint mask = rowMask;
1377 
1378                if (ix < xmin) {
1379                   /* fragment is past left edge of point, turn off left bits */
1380                   mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
1381                }
1382                if (ix + 1 >= xmax) {
1383                   /* past the right edge */
1384                   mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
1385                }
1386 
1387                setup->quad[0].inout.mask = mask;
1388                setup->quad[0].input.x0 = ix;
1389                setup->quad[0].input.y0 = iy;
1390                clip_emit_quad( setup, &setup->quad[0] );
1391             }
1392          }
1393       }
1394    }
1395 }
1396 
1397 
1398 /**
1399  * Called by vbuf code just before we start buffering primitives.
1400  */
1401 void
sp_setup_prepare(struct setup_context * setup)1402 sp_setup_prepare(struct setup_context *setup)
1403 {
1404    struct softpipe_context *sp = setup->softpipe;
1405 
1406    if (sp->dirty) {
1407       softpipe_update_derived(sp, sp->reduced_api_prim);
1408    }
1409 
1410    /* Note: nr_attrs is only used for debugging (vertex printing) */
1411    setup->nr_vertex_attrs = draw_num_shader_outputs(sp->draw);
1412 
1413    sp->quad.first->begin( sp->quad.first );
1414 
1415    if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
1416        sp->rasterizer->fill_front == PIPE_POLYGON_MODE_FILL &&
1417        sp->rasterizer->fill_back == PIPE_POLYGON_MODE_FILL) {
1418       /* we'll do culling */
1419       setup->cull_face = sp->rasterizer->cull_face;
1420    }
1421    else {
1422       /* 'draw' will do culling */
1423       setup->cull_face = PIPE_FACE_NONE;
1424    }
1425 }
1426 
1427 
1428 void
sp_setup_destroy_context(struct setup_context * setup)1429 sp_setup_destroy_context(struct setup_context *setup)
1430 {
1431    FREE( setup );
1432 }
1433 
1434 
1435 /**
1436  * Create a new primitive setup/render stage.
1437  */
1438 struct setup_context *
sp_setup_create_context(struct softpipe_context * softpipe)1439 sp_setup_create_context(struct softpipe_context *softpipe)
1440 {
1441    struct setup_context *setup = CALLOC_STRUCT(setup_context);
1442    unsigned i;
1443 
1444    setup->softpipe = softpipe;
1445 
1446    for (i = 0; i < MAX_QUADS; i++) {
1447       setup->quad[i].coef = setup->coef;
1448       setup->quad[i].posCoef = &setup->posCoef;
1449    }
1450 
1451    setup->span.left[0] = 1000000;     /* greater than right[0] */
1452    setup->span.left[1] = 1000000;     /* greater than right[1] */
1453 
1454    return setup;
1455 }
1456