Clip triangles against softpipe->cliprect which includes scissor and surface bounds.
[mesa.git] / src / mesa / pipe / softpipe / sp_prim_setup.c
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
36 #include "imports.h"
37 #include "macros.h"
38
39 #include "sp_context.h"
40 #include "sp_headers.h"
41 #include "pipe/draw/draw_private.h"
42 #include "sp_quad.h"
43 #include "sp_prim_setup.h"
44
45
46 /**
47 * Triangle edge info
48 */
49 struct edge {
50 GLfloat dx; /* X(v1) - X(v0), used only during setup */
51 GLfloat dy; /* Y(v1) - Y(v0), used only during setup */
52 GLfloat dxdy; /* dx/dy */
53 GLfloat sx; /* first sample point x coord */
54 GLfloat sy;
55 GLint lines; /* number of lines on this edge */
56 };
57
58
59 /**
60 * Triangle setup info (derived from draw_stage).
61 * Also used for line drawing (taking some liberties).
62 */
63 struct setup_stage {
64 struct draw_stage stage; /**< This must be first (base class) */
65
66 /*XXX NEW */
67 struct softpipe_context *softpipe;
68
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.
72 */
73 const struct vertex_header *vmax;
74 const struct vertex_header *vmid;
75 const struct vertex_header *vmin;
76 const struct vertex_header *vprovoke;
77
78 struct edge ebot;
79 struct edge etop;
80 struct edge emaj;
81
82 GLfloat oneoverarea;
83
84 struct setup_coefficient coef[FRAG_ATTRIB_MAX];
85 struct quad_header quad;
86
87 struct {
88 GLint left[2]; /**< [0] = row0, [1] = row1 */
89 GLint right[2];
90 GLint y;
91 GLuint y_flags;
92 GLuint mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
93 } span;
94 };
95
96
97
98 /**
99 * Basically a cast wrapper.
100 */
101 static inline struct setup_stage *setup_stage( struct draw_stage *stage )
102 {
103 return (struct setup_stage *)stage;
104 }
105
106
107 /**
108 * Clip setup->quad against the scissor/surface bounds.
109 */
110 static INLINE void
111 quad_clip(struct setup_stage *setup)
112 {
113 const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
114 if (setup->quad.x0 >= cliprect->maxx ||
115 setup->quad.y0 >= cliprect->maxy ||
116 setup->quad.x0 + 1 < cliprect->minx ||
117 setup->quad.y0 + 1 < cliprect->miny) {
118 /* totally clipped */
119 setup->quad.mask = 0x0;
120 return;
121 }
122 if (setup->quad.x0 < cliprect->minx)
123 setup->quad.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
124 if (setup->quad.y0 < cliprect->miny)
125 setup->quad.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
126 if (setup->quad.x0 == cliprect->maxx - 1)
127 setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
128 if (setup->quad.y0 == cliprect->maxy - 1)
129 setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
130 }
131
132
133 /**
134 * Emit/render a quad.
135 * Called during point/line rendering. For triangles, we call
136 * run_shader_block() which doesn't do clipping (since clipping is
137 * done at a higher level for tris).
138 * This passes the quad to the first stage of per-fragment operations.
139 */
140 static INLINE void
141 quad_emit(struct setup_stage *setup)
142 {
143 quad_clip(setup);
144 if (setup->quad.mask) {
145 struct softpipe_context *sp = setup->softpipe;
146 sp->quad.first->run(sp->quad.first, &setup->quad);
147 }
148 }
149
150
151 /**
152 * Given an X or Y coordinate, return the block/quad coordinate that it
153 * belongs to.
154 */
155 static inline GLint block( GLint x )
156 {
157 return x & ~1;
158 }
159
160
161
162 /**
163 * Run shader on a quad/block.
164 */
165 static void run_shader_block( struct setup_stage *setup,
166 GLint x, GLint y, GLuint mask )
167 {
168 struct softpipe_context *sp = setup->softpipe;
169 setup->quad.x0 = x;
170 setup->quad.y0 = y;
171 setup->quad.mask = mask;
172 sp->quad.first->run(sp->quad.first, &setup->quad);
173 }
174
175
176 /**
177 * Compute mask which indicates which pixels in the 2x2 quad are actually inside
178 * the triangle's bounds.
179 *
180 * this is pretty nasty... may need to rework flush_spans again to
181 * fix it, if possible.
182 */
183 static GLuint calculate_mask( struct setup_stage *setup,
184 GLint x )
185 {
186 GLuint mask = 0;
187
188 if (x >= setup->span.left[0] && x < setup->span.right[0])
189 mask |= MASK_BOTTOM_LEFT;
190
191 if (x >= setup->span.left[1] && x < setup->span.right[1])
192 mask |= MASK_TOP_LEFT;
193
194 if (x+1 >= setup->span.left[0] && x+1 < setup->span.right[0])
195 mask |= MASK_BOTTOM_RIGHT;
196
197 if (x+1 >= setup->span.left[1] && x+1 < setup->span.right[1])
198 mask |= MASK_TOP_RIGHT;
199
200 return mask;
201 }
202
203
204 /**
205 * Render a horizontal span of quads
206 */
207 static void flush_spans( struct setup_stage *setup )
208 {
209 GLint minleft, maxright;
210 GLint x;
211
212 switch (setup->span.y_flags) {
213 case 3:
214 minleft = MIN2(setup->span.left[0], setup->span.left[1]);
215 maxright = MAX2(setup->span.right[0], setup->span.right[1]);
216 break;
217
218 case 1:
219 minleft = setup->span.left[0];
220 maxright = setup->span.right[0];
221 break;
222
223 case 2:
224 minleft = setup->span.left[1];
225 maxright = setup->span.right[1];
226 break;
227
228 default:
229 return;
230 }
231
232
233 for (x = block(minleft); x <= block(maxright); )
234 {
235 run_shader_block( setup, x,
236 setup->span.y,
237 calculate_mask( setup, x ) );
238 x += 2;
239 }
240
241 setup->span.y = 0;
242 setup->span.y_flags = 0;
243 setup->span.right[0] = 0;
244 setup->span.right[1] = 0;
245 }
246
247
248 static GLboolean setup_sort_vertices( struct setup_stage *setup,
249 const struct prim_header *prim )
250 {
251 const struct vertex_header *v0 = prim->v[0];
252 const struct vertex_header *v1 = prim->v[1];
253 const struct vertex_header *v2 = prim->v[2];
254
255 setup->vprovoke = v2;
256
257 /* determine bottom to top order of vertices */
258 {
259 GLfloat y0 = v0->data[0][1];
260 GLfloat y1 = v1->data[0][1];
261 GLfloat y2 = v2->data[0][1];
262 if (y0 <= y1) {
263 if (y1 <= y2) {
264 /* y0<=y1<=y2 */
265 setup->vmin = v0;
266 setup->vmid = v1;
267 setup->vmax = v2;
268 }
269 else if (y2 <= y0) {
270 /* y2<=y0<=y1 */
271 setup->vmin = v2;
272 setup->vmid = v0;
273 setup->vmax = v1;
274 }
275 else {
276 /* y0<=y2<=y1 */
277 setup->vmin = v0;
278 setup->vmid = v2;
279 setup->vmax = v1;
280 }
281 }
282 else {
283 if (y0 <= y2) {
284 /* y1<=y0<=y2 */
285 setup->vmin = v1;
286 setup->vmid = v0;
287 setup->vmax = v2;
288 }
289 else if (y2 <= y1) {
290 /* y2<=y1<=y0 */
291 setup->vmin = v2;
292 setup->vmid = v1;
293 setup->vmax = v0;
294 }
295 else {
296 /* y1<=y2<=y0 */
297 setup->vmin = v1;
298 setup->vmid = v2;
299 setup->vmax = v0;
300 }
301 }
302 }
303
304 setup->ebot.dx = setup->vmid->data[0][0] - setup->vmin->data[0][0];
305 setup->ebot.dy = setup->vmid->data[0][1] - setup->vmin->data[0][1];
306 setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
307 setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
308 setup->etop.dx = setup->vmax->data[0][0] - setup->vmid->data[0][0];
309 setup->etop.dy = setup->vmax->data[0][1] - setup->vmid->data[0][1];
310
311 /*
312 * Compute triangle's area. Use 1/area to compute partial
313 * derivatives of attributes later.
314 *
315 * The area will be the same as prim->det, but the sign may be
316 * different depending on how the vertices get sorted above.
317 *
318 * To determine whether the primitive is front or back facing we
319 * use the prim->det value because its sign is correct.
320 */
321 {
322 const GLfloat area = (setup->emaj.dx * setup->ebot.dy -
323 setup->ebot.dx * setup->emaj.dy);
324
325 setup->oneoverarea = 1.0 / area;
326 /*
327 _mesa_printf("%s one-over-area %f area %f det %f\n",
328 __FUNCTION__, setup->oneoverarea, area, prim->det );
329 */
330 }
331
332 /* We need to know if this is a front or back-facing triangle for:
333 * - the GLSL gl_FrontFacing fragment attribute (bool)
334 * - two-sided stencil test
335 */
336 setup->quad.facing = (prim->det > 0.0) ^ (setup->softpipe->setup.front_winding == PIPE_WINDING_CW);
337
338 return GL_TRUE;
339 }
340
341
342 /**
343 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
344 * The value value comes from vertex->data[slot][i].
345 * The result will be put into setup->coef[slot].a0[i].
346 * \param slot which attribute slot
347 * \param i which component of the slot (0..3)
348 */
349 static void const_coeff( struct setup_stage *setup,
350 GLuint slot,
351 GLuint i )
352 {
353 assert(slot < FRAG_ATTRIB_MAX);
354 assert(i <= 3);
355
356 setup->coef[slot].dadx[i] = 0;
357 setup->coef[slot].dady[i] = 0;
358
359 /* need provoking vertex info!
360 */
361 setup->coef[slot].a0[i] = setup->vprovoke->data[slot][i];
362 }
363
364
365 /**
366 * Compute a0, dadx and dady for a linearly interpolated coefficient,
367 * for a triangle.
368 */
369 static void tri_linear_coeff( struct setup_stage *setup,
370 GLuint slot,
371 GLuint i)
372 {
373 GLfloat botda = setup->vmid->data[slot][i] - setup->vmin->data[slot][i];
374 GLfloat majda = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
375 GLfloat a = setup->ebot.dy * majda - botda * setup->emaj.dy;
376 GLfloat b = setup->emaj.dx * botda - majda * setup->ebot.dx;
377
378 assert(slot < FRAG_ATTRIB_MAX);
379 assert(i <= 3);
380
381 setup->coef[slot].dadx[i] = a * setup->oneoverarea;
382 setup->coef[slot].dady[i] = b * setup->oneoverarea;
383
384 /* calculate a0 as the value which would be sampled for the
385 * fragment at (0,0), taking into account that we want to sample at
386 * pixel centers, in other words (0.5, 0.5).
387 *
388 * this is neat but unfortunately not a good way to do things for
389 * triangles with very large values of dadx or dady as it will
390 * result in the subtraction and re-addition from a0 of a very
391 * large number, which means we'll end up loosing a lot of the
392 * fractional bits and precision from a0. the way to fix this is
393 * to define a0 as the sample at a pixel center somewhere near vmin
394 * instead - i'll switch to this later.
395 */
396 setup->coef[slot].a0[i] = (setup->vmin->data[slot][i] -
397 (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) +
398 setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5)));
399
400 /*
401 _mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n",
402 slot, "xyzw"[i],
403 setup->coef[slot].a0[i],
404 setup->coef[slot].dadx[i],
405 setup->coef[slot].dady[i]);
406 */
407 }
408
409
410 /**
411 * Compute a0, dadx and dady for a perspective-corrected interpolant,
412 * for a triangle.
413 */
414 static void tri_persp_coeff( struct setup_stage *setup,
415 GLuint slot,
416 GLuint i )
417 {
418 /* premultiply by 1/w:
419 */
420 GLfloat mina = setup->vmin->data[slot][i] * setup->vmin->data[0][3];
421 GLfloat mida = setup->vmid->data[slot][i] * setup->vmid->data[0][3];
422 GLfloat maxa = setup->vmax->data[slot][i] * setup->vmax->data[0][3];
423
424 GLfloat botda = mida - mina;
425 GLfloat majda = maxa - mina;
426 GLfloat a = setup->ebot.dy * majda - botda * setup->emaj.dy;
427 GLfloat b = setup->emaj.dx * botda - majda * setup->ebot.dx;
428
429 assert(slot < FRAG_ATTRIB_MAX);
430 assert(i <= 3);
431
432 setup->coef[slot].dadx[i] = a * setup->oneoverarea;
433 setup->coef[slot].dady[i] = b * setup->oneoverarea;
434 setup->coef[slot].a0[i] = (mina -
435 (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) +
436 setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5)));
437 }
438
439
440
441 /**
442 * Compute the setup->coef[] array dadx, dady, a0 values.
443 * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
444 */
445 static void setup_tri_coefficients( struct setup_stage *setup )
446 {
447 const enum interp_mode *interp = setup->softpipe->interp;
448 GLuint slot, j;
449
450 /* z and w are done by linear interpolation:
451 */
452 tri_linear_coeff(setup, 0, 2);
453 tri_linear_coeff(setup, 0, 3);
454
455 /* setup interpolation for all the remaining attributes:
456 */
457 for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
458 switch (interp[slot]) {
459 case INTERP_CONSTANT:
460 for (j = 0; j < NUM_CHANNELS; j++)
461 const_coeff(setup, slot, j);
462 break;
463
464 case INTERP_LINEAR:
465 for (j = 0; j < NUM_CHANNELS; j++)
466 tri_linear_coeff(setup, slot, j);
467 break;
468
469 case INTERP_PERSPECTIVE:
470 for (j = 0; j < NUM_CHANNELS; j++)
471 tri_persp_coeff(setup, slot, j);
472 break;
473 }
474 }
475 }
476
477
478
479 static void setup_tri_edges( struct setup_stage *setup )
480 {
481 GLfloat vmin_x = setup->vmin->data[0][0] + 0.5;
482 GLfloat vmid_x = setup->vmid->data[0][0] + 0.5;
483
484 GLfloat vmin_y = setup->vmin->data[0][1] - 0.5;
485 GLfloat vmid_y = setup->vmid->data[0][1] - 0.5;
486 GLfloat vmax_y = setup->vmax->data[0][1] - 0.5;
487
488 setup->emaj.sy = ceilf(vmin_y);
489 setup->emaj.lines = (GLint) ceilf(vmax_y - setup->emaj.sy);
490 setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
491 setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
492
493 setup->etop.sy = ceilf(vmid_y);
494 setup->etop.lines = (GLint) ceilf(vmax_y - setup->etop.sy);
495 setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
496 setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
497
498 setup->ebot.sy = ceilf(vmin_y);
499 setup->ebot.lines = (GLint) ceilf(vmid_y - setup->ebot.sy);
500 setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
501 setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
502 }
503
504
505 /**
506 * Render the upper or lower half of a triangle.
507 * Scissoring/cliprect is applied here too.
508 */
509 static void subtriangle( struct setup_stage *setup,
510 struct edge *eleft,
511 struct edge *eright,
512 GLuint lines )
513 {
514 const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
515 GLint y, start_y, finish_y;
516 GLint sy = (GLint)eleft->sy;
517
518 assert((GLint)eleft->sy == (GLint) eright->sy);
519
520 /* clip top/bottom */
521 start_y = sy;
522 finish_y = sy + lines;
523
524 if (start_y < cliprect->miny)
525 start_y = cliprect->miny;
526
527 if (finish_y > cliprect->maxy)
528 finish_y = cliprect->maxy;
529
530 start_y -= sy;
531 finish_y -= sy;
532
533 /*
534 _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
535 */
536
537 for (y = start_y; y < finish_y; y++) {
538
539 /* avoid accumulating adds as floats don't have the precision to
540 * accurately iterate large triangle edges that way. luckily we
541 * can just multiply these days.
542 *
543 * this is all drowned out by the attribute interpolation anyway.
544 */
545 GLint left = (GLint)(eleft->sx + y * eleft->dxdy);
546 GLint right = (GLint)(eright->sx + y * eright->dxdy);
547
548 /* clip left/right */
549 if (left < cliprect->minx)
550 left = cliprect->minx;
551 if (right > cliprect->maxx)
552 right = cliprect->maxx;
553
554 if (left < right) {
555 GLint _y = sy+y;
556 if (block(_y) != setup->span.y) {
557 flush_spans(setup);
558 setup->span.y = block(_y);
559 }
560
561 setup->span.left[_y&1] = left;
562 setup->span.right[_y&1] = right;
563 setup->span.y_flags |= 1<<(_y&1);
564 }
565 }
566
567
568 /* save the values so that emaj can be restarted:
569 */
570 eleft->sx += lines * eleft->dxdy;
571 eright->sx += lines * eright->dxdy;
572 eleft->sy += lines;
573 eright->sy += lines;
574 }
575
576
577 /**
578 * Do setup for triangle rasterization, then render the triangle.
579 */
580 static void setup_tri( struct draw_stage *stage,
581 struct prim_header *prim )
582 {
583 struct setup_stage *setup = setup_stage( stage );
584
585 /*
586 _mesa_printf("%s\n", __FUNCTION__ );
587 */
588
589 setup_sort_vertices( setup, prim );
590 setup_tri_coefficients( setup );
591 setup_tri_edges( setup );
592
593 setup->quad.prim = PRIM_TRI;
594
595 setup->span.y = 0;
596 setup->span.y_flags = 0;
597 setup->span.right[0] = 0;
598 setup->span.right[1] = 0;
599 /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
600
601 /* init_constant_attribs( setup ); */
602
603 if (setup->oneoverarea < 0.0) {
604 /* emaj on left:
605 */
606 subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
607 subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
608 }
609 else {
610 /* emaj on right:
611 */
612 subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
613 subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
614 }
615
616 flush_spans( setup );
617 }
618
619
620
621 /**
622 * Compute a0, dadx and dady for a linearly interpolated coefficient,
623 * for a line.
624 */
625 static void
626 line_linear_coeff(struct setup_stage *setup, GLuint slot, GLuint i)
627 {
628 const GLfloat dz = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
629 const GLfloat dadx = dz * setup->emaj.dx * setup->oneoverarea;
630 const GLfloat dady = dz * setup->emaj.dy * setup->oneoverarea;
631 setup->coef[slot].dadx[i] = dadx;
632 setup->coef[slot].dady[i] = dady;
633 setup->coef[slot].a0[i]
634 = (setup->vmin->data[slot][i] -
635 (dadx * (setup->vmin->data[0][0] - 0.5) +
636 dady * (setup->vmin->data[0][1] - 0.5)));
637 }
638
639
640 /**
641 * Compute a0, dadx and dady for a perspective-corrected interpolant,
642 * for a line.
643 */
644 static void
645 line_persp_coeff(struct setup_stage *setup, GLuint slot, GLuint i)
646 {
647 /* XXX to do */
648 line_linear_coeff(setup, slot, i); /* XXX temporary */
649 }
650
651
652 /**
653 * Compute the setup->coef[] array dadx, dady, a0 values.
654 * Must be called after setup->vmin,vmax are initialized.
655 */
656 static INLINE void
657 setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)
658 {
659 const enum interp_mode *interp = setup->softpipe->interp;
660 GLuint slot, j;
661
662 /* use setup->vmin, vmax to point to vertices */
663 setup->vprovoke = prim->v[1];
664 setup->vmin = prim->v[0];
665 setup->vmax = prim->v[1];
666
667 setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
668 setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
669 /* NOTE: this is not really 1/area */
670 setup->oneoverarea = 1.0 / (setup->emaj.dx * setup->emaj.dx +
671 setup->emaj.dy * setup->emaj.dy);
672
673 /* z and w are done by linear interpolation:
674 */
675 line_linear_coeff(setup, 0, 2);
676 line_linear_coeff(setup, 0, 3);
677
678 /* setup interpolation for all the remaining attributes:
679 */
680 for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
681 switch (interp[slot]) {
682 case INTERP_CONSTANT:
683 for (j = 0; j < NUM_CHANNELS; j++)
684 const_coeff(setup, slot, j);
685 break;
686
687 case INTERP_LINEAR:
688 for (j = 0; j < NUM_CHANNELS; j++)
689 line_linear_coeff(setup, slot, j);
690 break;
691
692 case INTERP_PERSPECTIVE:
693 for (j = 0; j < NUM_CHANNELS; j++)
694 line_persp_coeff(setup, slot, j);
695 break;
696 }
697 }
698 }
699
700
701 /**
702 * Plot a pixel in a line segment.
703 */
704 static INLINE void
705 plot(struct setup_stage *setup, GLint x, GLint y)
706 {
707 const GLint iy = y & 1;
708 const GLint ix = x & 1;
709 const GLint quadX = x - ix;
710 const GLint quadY = y - iy;
711 const GLint mask = (1 << ix) << (2 * iy);
712
713 if (quadX != setup->quad.x0 ||
714 quadY != setup->quad.y0)
715 {
716 /* flush prev quad, start new quad */
717
718 if (setup->quad.x0 != -1)
719 quad_emit(setup);
720
721 setup->quad.x0 = quadX;
722 setup->quad.y0 = quadY;
723 setup->quad.mask = 0x0;
724 }
725
726 setup->quad.mask |= mask;
727 }
728
729
730 /**
731 * Determine whether or not to emit a line fragment by checking
732 * line stipple pattern.
733 */
734 static INLINE GLuint
735 stipple_test(GLint counter, GLushort pattern, GLint factor)
736 {
737 GLint b = (counter / factor) & 0xf;
738 return (1 << b) & pattern;
739 }
740
741
742 /**
743 * Do setup for line rasterization, then render the line.
744 * XXX single-pixel width, no stipple, etc
745 */
746 static void
747 setup_line(struct draw_stage *stage, struct prim_header *prim)
748 {
749 const struct vertex_header *v0 = prim->v[0];
750 const struct vertex_header *v1 = prim->v[1];
751 struct setup_stage *setup = setup_stage( stage );
752 struct softpipe_context *sp = setup->softpipe;
753
754 GLint x0 = (GLint) v0->data[0][0];
755 GLint x1 = (GLint) v1->data[0][0];
756 GLint y0 = (GLint) v0->data[0][1];
757 GLint y1 = (GLint) v1->data[0][1];
758 GLint dx = x1 - x0;
759 GLint dy = y1 - y0;
760 GLint xstep, ystep;
761
762 if (dx == 0 && dy == 0)
763 return;
764
765 setup_line_coefficients(setup, prim);
766
767 if (dx < 0) {
768 dx = -dx; /* make positive */
769 xstep = -1;
770 }
771 else {
772 xstep = 1;
773 }
774
775 if (dy < 0) {
776 dy = -dy; /* make positive */
777 ystep = -1;
778 }
779 else {
780 ystep = 1;
781 }
782
783 assert(dx >= 0);
784 assert(dy >= 0);
785
786 setup->quad.x0 = setup->quad.y0 = -1;
787 setup->quad.mask = 0x0;
788 setup->quad.prim = PRIM_LINE;
789 /* XXX temporary: set coverage to 1.0 so the line appears
790 * if AA mode happens to be enabled.
791 */
792 setup->quad.coverage[0] =
793 setup->quad.coverage[1] =
794 setup->quad.coverage[2] =
795 setup->quad.coverage[3] = 1.0;
796
797 if (dx > dy) {
798 /*** X-major line ***/
799 GLint i;
800 const GLint errorInc = dy + dy;
801 GLint error = errorInc - dx;
802 const GLint errorDec = error - dx;
803
804 for (i = 0; i < dx; i++) {
805 if (!sp->setup.line_stipple_enable ||
806 stipple_test(sp->line_stipple_counter,
807 sp->setup.line_stipple_pattern,
808 sp->setup.line_stipple_factor + 1)) {
809 plot(setup, x0, y0);
810 }
811
812 x0 += xstep;
813 if (error < 0) {
814 error += errorInc;
815 }
816 else {
817 error += errorDec;
818 y0 += ystep;
819 }
820
821 sp->line_stipple_counter++;
822 }
823 }
824 else {
825 /*** Y-major line ***/
826 GLint i;
827 const GLint errorInc = dx + dx;
828 GLint error = errorInc - dy;
829 const GLint errorDec = error - dy;
830
831 for (i = 0; i < dy; i++) {
832 if (!sp->setup.line_stipple_enable ||
833 stipple_test(sp->line_stipple_counter,
834 sp->setup.line_stipple_pattern,
835 sp->setup.line_stipple_factor + 1)) {
836 plot(setup, x0, y0);
837 }
838
839 y0 += ystep;
840
841 if (error < 0) {
842 error += errorInc;
843 }
844 else {
845 error += errorDec;
846 x0 += xstep;
847 }
848
849 sp->line_stipple_counter++;
850 }
851 }
852
853 /* draw final quad */
854 if (setup->quad.mask) {
855 quad_emit(setup);
856 }
857 }
858
859
860 /**
861 * Do setup for point rasterization, then render the point.
862 * Round or square points...
863 * XXX could optimize a lot for 1-pixel points.
864 */
865 static void
866 setup_point(struct draw_stage *stage, struct prim_header *prim)
867 {
868 struct setup_stage *setup = setup_stage( stage );
869 /*XXX this should be a vertex attrib! */
870 const GLfloat halfSize = 0.5 * setup->softpipe->setup.point_size;
871 const GLboolean round = setup->softpipe->setup.point_smooth;
872 const struct vertex_header *v0 = prim->v[0];
873 const GLfloat x = v0->data[FRAG_ATTRIB_WPOS][0];
874 const GLfloat y = v0->data[FRAG_ATTRIB_WPOS][1];
875 GLuint slot, j;
876
877 /* For points, all interpolants are constant-valued.
878 * However, for point sprites, we'll need to setup texcoords appropriately.
879 * XXX: which coefficients are the texcoords???
880 * We may do point sprites as textured quads...
881 *
882 * KW: We don't know which coefficients are texcoords - ultimately
883 * the choice of what interpolation mode to use for each attribute
884 * should be determined by the fragment program, using
885 * per-attribute declaration statements that include interpolation
886 * mode as a parameter. So either the fragment program will have
887 * to be adjusted for pointsprite vs normal point behaviour, or
888 * otherwise a special interpolation mode will have to be defined
889 * which matches the required behaviour for point sprites. But -
890 * the latter is not a feature of normal hardware, and as such
891 * probably should be ruled out on that basis.
892 */
893 setup->vprovoke = prim->v[0];
894 const_coeff(setup, 0, 2);
895 const_coeff(setup, 0, 3);
896 for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
897 for (j = 0; j < NUM_CHANNELS; j++)
898 const_coeff(setup, slot, j);
899 }
900
901 setup->quad.prim = PRIM_POINT;
902
903 if (halfSize <= 0.5 && !round) {
904 /* special case for 1-pixel points */
905 const GLint ix = ((GLint) x) & 1;
906 const GLint iy = ((GLint) y) & 1;
907 setup->quad.x0 = x - ix;
908 setup->quad.y0 = y - iy;
909 setup->quad.mask = (1 << ix) << (2 * iy);
910 quad_emit(setup);
911 }
912 else {
913 const GLint ixmin = block((GLint) (x - halfSize));
914 const GLint ixmax = block((GLint) (x + halfSize));
915 const GLint iymin = block((GLint) (y - halfSize));
916 const GLint iymax = block((GLint) (y + halfSize));
917 GLint ix, iy;
918
919 if (round) {
920 /* rounded points */
921 const GLfloat rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
922 const GLfloat rmax = halfSize + 0.7071F;
923 const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
924 const GLfloat rmax2 = rmax * rmax;
925 const GLfloat cscale = 1.0F / (rmax2 - rmin2);
926
927 for (iy = iymin; iy <= iymax; iy += 2) {
928 for (ix = ixmin; ix <= ixmax; ix += 2) {
929 GLfloat dx, dy, dist2, cover;
930
931 setup->quad.mask = 0x0;
932
933 dx = (ix + 0.5) - x;
934 dy = (iy + 0.5) - y;
935 dist2 = dx * dx + dy * dy;
936 if (dist2 <= rmax2) {
937 cover = 1.0F - (dist2 - rmin2) * cscale;
938 setup->quad.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0);
939 setup->quad.mask |= MASK_BOTTOM_LEFT;
940 }
941
942 dx = (ix + 1.5) - x;
943 dy = (iy + 0.5) - y;
944 dist2 = dx * dx + dy * dy;
945 if (dist2 <= rmax2) {
946 cover = 1.0F - (dist2 - rmin2) * cscale;
947 setup->quad.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0);
948 setup->quad.mask |= MASK_BOTTOM_RIGHT;
949 }
950
951 dx = (ix + 0.5) - x;
952 dy = (iy + 1.5) - y;
953 dist2 = dx * dx + dy * dy;
954 if (dist2 <= rmax2) {
955 cover = 1.0F - (dist2 - rmin2) * cscale;
956 setup->quad.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0);
957 setup->quad.mask |= MASK_TOP_LEFT;
958 }
959
960 dx = (ix + 1.5) - x;
961 dy = (iy + 1.5) - y;
962 dist2 = dx * dx + dy * dy;
963 if (dist2 <= rmax2) {
964 cover = 1.0F - (dist2 - rmin2) * cscale;
965 setup->quad.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0);
966 setup->quad.mask |= MASK_TOP_RIGHT;
967 }
968
969 if (setup->quad.mask) {
970 setup->quad.x0 = ix;
971 setup->quad.y0 = iy;
972 quad_emit(setup);
973 }
974 }
975 }
976 }
977 else {
978 /* square points */
979 for (iy = iymin; iy <= iymax; iy += 2) {
980 for (ix = ixmin; ix <= ixmax; ix += 2) {
981 setup->quad.mask = 0xf;
982
983 if (ix + 0.5 < x - halfSize) {
984 /* fragment is past left edge of point, turn off left bits */
985 setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
986 }
987
988 if (ix + 1.5 > x + halfSize) {
989 /* past the right edge */
990 setup->quad.mask &= ~(MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
991 }
992
993 if (iy + 0.5 < y - halfSize) {
994 /* below the bottom edge */
995 setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
996 }
997
998 if (iy + 1.5 > y + halfSize) {
999 /* above the top edge */
1000 setup->quad.mask &= ~(MASK_TOP_LEFT | MASK_TOP_RIGHT);
1001 }
1002
1003 if (setup->quad.mask) {
1004 setup->quad.x0 = ix;
1005 setup->quad.y0 = iy;
1006 quad_emit(setup);
1007 }
1008 }
1009 }
1010 }
1011 }
1012 }
1013
1014
1015
1016 static void setup_begin( struct draw_stage *stage )
1017 {
1018 struct setup_stage *setup = setup_stage(stage);
1019
1020 setup->quad.nr_attrs = setup->softpipe->nr_frag_attrs;
1021
1022 /*
1023 * XXX this is where we might map() the renderbuffers to begin
1024 * s/w rendering.
1025 */
1026 }
1027
1028
1029 static void setup_end( struct draw_stage *stage )
1030 {
1031 /*
1032 * XXX this is where we might unmap() the renderbuffers after
1033 * s/w rendering.
1034 */
1035 }
1036
1037
1038 static void reset_stipple_counter( struct draw_stage *stage )
1039 {
1040 struct setup_stage *setup = setup_stage(stage);
1041 setup->softpipe->line_stipple_counter = 0;
1042 }
1043
1044
1045 /**
1046 * Create a new primitive setup/render stage.
1047 */
1048 struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe )
1049 {
1050 struct setup_stage *setup = CALLOC_STRUCT(setup_stage);
1051
1052 setup->softpipe = softpipe;
1053 setup->stage.draw = softpipe->draw;
1054 setup->stage.begin = setup_begin;
1055 setup->stage.point = setup_point;
1056 setup->stage.line = setup_line;
1057 setup->stage.tri = setup_tri;
1058 setup->stage.end = setup_end;
1059 setup->stage.reset_stipple_counter = reset_stipple_counter;
1060
1061 setup->quad.coef = setup->coef;
1062
1063 return &setup->stage;
1064 }