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