Reorganized software rasterizer as a module which manages its own state,
[mesa.git] / src / mesa / swrast / s_points.c
1 /* $Id: s_points.c,v 1.2 2000/11/05 18:24:40 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.4
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "macros.h"
31 #include "mmath.h"
32 #include "texstate.h"
33 #include "vb.h"
34
35 #include "s_context.h"
36 #include "s_feedback.h"
37 #include "s_pb.h"
38 #include "s_points.h"
39 #include "s_span.h"
40
41
42 /**********************************************************************/
43 /***** Rasterization *****/
44 /**********************************************************************/
45
46
47 /*
48 * There are 3 pairs (RGBA, CI) of point rendering functions:
49 * 1. simple: size=1 and no special rasterization functions (fastest)
50 * 2. size1: size=1 and any rasterization functions
51 * 3. general: any size and rasterization functions (slowest)
52 *
53 */
54
55
56
57
58
59 /*
60 * CI points with size == 1.0
61 */
62 static void
63 size1_ci_point( GLcontext *ctx, SWvertex *vert )
64 {
65 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
66 GLint *pbx = PB->x, *pby = PB->y;
67 GLdepth *pbz = PB->z;
68 GLfixed *pbfog = PB->fog;
69 GLuint *pbi = PB->index;
70 GLuint pbcount = PB->count;
71
72 pbx[pbcount] = (GLint) vert->win[0];
73 pby[pbcount] = (GLint) vert->win[1];
74 pbz[pbcount] = (GLint) vert->win[2];
75 pbfog[pbcount] = FloatToFixed(vert->fog);
76 pbi[pbcount] = vert->index;
77
78 PB->count++;
79 PB_CHECK_FLUSH(ctx, PB);
80 }
81
82
83
84 /*
85 * RGBA points with size == 1.0
86 */
87 static void
88 size1_rgba_point( GLcontext *ctx, SWvertex *vert )
89 {
90 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
91
92 GLint x = (GLint) vert->win[0];
93 GLint y = (GLint) vert->win[1];
94 GLint z = (GLint) (vert->win[2]);
95 GLfixed fog = FloatToFixed( vert->fog );
96 GLubyte red = vert->color[0];
97 GLubyte green = vert->color[1];
98 GLubyte blue = vert->color[2];
99 GLubyte alpha = vert->color[3];
100
101 PB_WRITE_RGBA_PIXEL( PB, x, y, z, fog, red, green, blue, alpha );
102 PB_CHECK_FLUSH(ctx, PB);
103 }
104
105
106
107 /*
108 * General CI points.
109 */
110 static void
111 general_ci_point( GLcontext *ctx, SWvertex *vert )
112 {
113 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
114 const GLint isize = (GLint) (ctx->Point.Size + 0.5F);
115 GLint radius = isize >> 1;
116
117 GLint x0, x1, y0, y1;
118 GLint ix, iy;
119
120 GLint x = (GLint) vert->win[0];
121 GLint y = (GLint) vert->win[1];
122 GLint z = (GLint) (vert->win[2]);
123
124 GLfixed fog = FloatToFixed( vert->fog );
125
126 if (isize & 1) {
127 /* odd size */
128 x0 = x - radius;
129 x1 = x + radius;
130 y0 = y - radius;
131 y1 = y + radius;
132 }
133 else {
134 /* even size */
135 x0 = (GLint) (x + 1.5F) - radius;
136 x1 = x0 + isize - 1;
137 y0 = (GLint) (y + 1.5F) - radius;
138 y1 = y0 + isize - 1;
139 }
140
141 PB_SET_INDEX( PB, vert->index );
142
143 for (iy = y0; iy <= y1; iy++) {
144 for (ix = x0; ix <= x1; ix++) {
145 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
146 }
147 }
148 PB_CHECK_FLUSH(ctx,PB);
149 }
150
151
152 /*
153 * General RGBA points.
154 */
155 static void
156 general_rgba_point( GLcontext *ctx, SWvertex *vert )
157 {
158 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
159 GLint isize = (GLint) (ctx->Point.Size + 0.5F);
160 GLint radius = isize >> 1;
161
162 GLint x0, x1, y0, y1;
163 GLint ix, iy;
164
165 GLint x = (GLint) vert->win[0];
166 GLint y = (GLint) vert->win[1];
167 GLint z = (GLint) (vert->win[2]);
168
169 GLfixed fog = FloatToFixed( vert->fog );
170
171 if (isize & 1) {
172 /* odd size */
173 x0 = x - radius;
174 x1 = x + radius;
175 y0 = y - radius;
176 y1 = y + radius;
177 }
178 else {
179 /* even size */
180 x0 = (GLint) (x + 1.5F) - radius;
181 x1 = x0 + isize - 1;
182 y0 = (GLint) (y + 1.5F) - radius;
183 y1 = y0 + isize - 1;
184 }
185
186 PB_SET_COLOR( PB,
187 vert->color[0],
188 vert->color[1],
189 vert->color[2],
190 vert->color[3] );
191
192 for (iy = y0; iy <= y1; iy++) {
193 for (ix = x0; ix <= x1; ix++) {
194 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
195 }
196 }
197 PB_CHECK_FLUSH(ctx,PB);
198 }
199
200
201
202
203 /*
204 * Textured RGBA points.
205 */
206 static void
207 textured_rgba_point( GLcontext *ctx, SWvertex *vert )
208 {
209 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
210
211 GLint x0, x1, y0, y1;
212 GLint ix, iy, radius;
213 GLint red, green, blue, alpha;
214 GLfloat s, t, u;
215
216 GLint x = (GLint) vert->win[0];
217 GLint y = (GLint) vert->win[1];
218 GLint z = (GLint) (vert->win[2]);
219 GLint isize = (GLint) (ctx->Point.Size + 0.5F);
220
221 GLfixed fog = FloatToFixed( vert->fog );
222
223 if (isize < 1) {
224 isize = 1;
225 }
226 radius = isize >> 1;
227
228 if (isize & 1) {
229 /* odd size */
230 x0 = x - radius;
231 x1 = x + radius;
232 y0 = y - radius;
233 y1 = y + radius;
234 }
235 else {
236 /* even size */
237 x0 = (GLint) (x + 1.5F) - radius;
238 x1 = x0 + isize - 1;
239 y0 = (GLint) (y + 1.5F) - radius;
240 y1 = y0 + isize - 1;
241 }
242
243 red = vert->color[0];
244 green = vert->color[1];
245 blue = vert->color[2];
246 alpha = vert->color[3];
247
248 if (vert->texcoord[0][3] != 1.0) {
249 s = vert->texcoord[0][0]/vert->texcoord[0][3];
250 t = vert->texcoord[0][1]/vert->texcoord[0][3];
251 u = vert->texcoord[0][2]/vert->texcoord[0][3];
252 } else {
253 s = vert->texcoord[0][0];
254 t = vert->texcoord[0][1];
255 u = vert->texcoord[0][2];
256 }
257
258 for (iy = y0; iy <= y1; iy++) {
259 for (ix = x0; ix <= x1; ix++) {
260 PB_WRITE_TEX_PIXEL( PB, ix, iy, z, fog, red, green, blue, alpha,
261 s, t, u );
262 }
263 }
264
265 PB_CHECK_FLUSH(ctx, PB);
266 }
267
268
269
270 /*
271 * Multitextured RGBA points.
272 */
273 static void
274 multitextured_rgba_point( GLcontext *ctx, SWvertex *vert )
275 {
276 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
277
278 const GLint red = vert->color[0];
279 const GLint green = vert->color[1];
280 const GLint blue = vert->color[2];
281 const GLint alpha = vert->color[3];
282 const GLint sRed = vert->specular[0];
283 const GLint sGreen = vert->specular[1];
284 const GLint sBlue = vert->specular[2];
285 const GLint x = (GLint) vert->win[0];
286 const GLint y = (GLint) vert->win[1];
287 const GLint z = (GLint) (vert->win[2]);
288 GLint x0, x1, y0, y1;
289 GLint ix, iy;
290 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
291 GLint radius, u;
292 GLint isize = (GLint) (ctx->Point.Size + 0.5F);
293
294 GLfixed fog = FloatToFixed( vert->fog );
295
296 if (isize < 1) {
297 isize = 1;
298 }
299 radius = isize >> 1;
300
301 if (isize & 1) {
302 /* odd size */
303 x0 = x - radius;
304 x1 = x + radius;
305 y0 = y - radius;
306 y1 = y + radius;
307 }
308 else {
309 /* even size */
310 x0 = (GLint) (x + 1.5F) - radius;
311 x1 = x0 + isize - 1;
312 y0 = (GLint) (y + 1.5F) - radius;
313 y1 = y0 + isize - 1;
314 }
315
316 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
317 if (ctx->Texture.Unit[u]._ReallyEnabled) {
318 if (vert->texcoord[u][3] != 1.0) {
319 texcoord[u][0] = vert->texcoord[u][0] /
320 vert->texcoord[u][3];
321 texcoord[u][1] = vert->texcoord[u][1] /
322 vert->texcoord[u][3];
323 texcoord[u][2] = vert->texcoord[u][2] /
324 vert->texcoord[u][3];
325 }
326 else {
327 texcoord[u][0] = vert->texcoord[u][0];
328 texcoord[u][1] = vert->texcoord[u][1];
329 texcoord[u][2] = vert->texcoord[u][2];
330 }
331 }
332 }
333
334 for (iy = y0; iy <= y1; iy++) {
335 for (ix = x0; ix <= x1; ix++) {
336 PB_WRITE_MULTITEX_SPEC_PIXEL( PB, ix, iy, z, fog,
337 red, green, blue, alpha,
338 sRed, sGreen, sBlue,
339 texcoord );
340 }
341 }
342 PB_CHECK_FLUSH(ctx, PB);
343 }
344
345
346 /*
347 * NOTES on aa point rasterization:
348 *
349 * Let d = distance of fragment center from vertex.
350 * if d < rmin2 then
351 * fragment has 100% coverage
352 * else if d > rmax2 then
353 * fragment has 0% coverage
354 * else
355 * fragement has % coverage = (d - rmin2) / (rmax2 - rmin2)
356 */
357
358
359 /*
360 * Antialiased points with or without texture mapping.
361 */
362 static void
363 antialiased_rgba_point( GLcontext *ctx, SWvertex *vert )
364 {
365 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
366 const GLfloat radius = ctx->Point.Size * 0.5F;
367 const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
368 const GLfloat rmax = radius + 0.7071F;
369 const GLfloat rmin2 = MAX2(0.0, rmin * rmin);
370 const GLfloat rmax2 = rmax * rmax;
371 const GLfloat cscale = 256.0F / (rmax2 - rmin2);
372
373 if (ctx->Texture._ReallyEnabled) {
374 GLint x, y;
375 GLfloat vx = vert->win[0];
376 GLfloat vy = vert->win[1];
377 const GLint xmin = (GLint) (vx - radius);
378 const GLint xmax = (GLint) (vx + radius);
379 const GLint ymin = (GLint) (vy - radius);
380 const GLint ymax = (GLint) (vy + radius);
381 const GLint z = (GLint) (vert->win[2]);
382 const GLint red = vert->color[0];
383 const GLint green = vert->color[1];
384 const GLint blue = vert->color[2];
385 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
386 GLint u, alpha;
387
388 GLfixed fog = FloatToFixed( vert->fog );
389
390 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
391 if (ctx->Texture.Unit[u]._ReallyEnabled) {
392 if (texcoord[u][3] != 1.0) {
393 texcoord[u][0] = (vert->texcoord[u][0] /
394 vert->texcoord[u][3]);
395 texcoord[u][1] = (vert->texcoord[u][1] /
396 vert->texcoord[u][3]);
397 texcoord[u][2] = (vert->texcoord[u][2] /
398 vert->texcoord[u][3]);
399 }
400 else {
401 texcoord[u][0] = vert->texcoord[u][0];
402 texcoord[u][1] = vert->texcoord[u][1];
403 texcoord[u][2] = vert->texcoord[u][2];
404 }
405 }
406 }
407
408 /* translate by a half pixel to simplify math below */
409 vx -= 0.5F;
410 vx -= 0.5F;
411
412 for (y = ymin; y <= ymax; y++) {
413 for (x = xmin; x <= xmax; x++) {
414 const GLfloat dx = x - vx;
415 const GLfloat dy = y - vy;
416 const GLfloat dist2 = dx*dx + dy*dy;
417 if (dist2 < rmax2) {
418 alpha = vert->color[3];
419 if (dist2 >= rmin2) {
420 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
421 /* coverage is in [0,256] */
422 alpha = (alpha * coverage) >> 8;
423 }
424 if (ctx->Texture._MultiTextureEnabled) {
425 PB_WRITE_MULTITEX_PIXEL( PB, x,y,z, fog,
426 red, green, blue,
427 alpha, texcoord );
428 }
429 else {
430 PB_WRITE_TEX_PIXEL( PB, x,y,z, fog,
431 red, green, blue, alpha,
432 texcoord[0][0],
433 texcoord[0][1],
434 texcoord[0][2] );
435 }
436 }
437 }
438 }
439
440 PB_CHECK_FLUSH(ctx,PB);
441 }
442 else {
443 /* Not texture mapped */
444 const GLint xmin = (GLint) (vert->win[0] - 0.0 - radius);
445 const GLint xmax = (GLint) (vert->win[0] - 0.0 + radius);
446 const GLint ymin = (GLint) (vert->win[1] - 0.0 - radius);
447 const GLint ymax = (GLint) (vert->win[1] - 0.0 + radius);
448 const GLint red = vert->color[0];
449 const GLint green = vert->color[1];
450 const GLint blue = vert->color[2];
451 const GLint z = (GLint) (vert->win[2]);
452 GLint x, y;
453
454 GLfixed fog = FloatToFixed( vert->fog );
455
456 /*
457 printf("point %g, %g\n", vert->win[0], vert->win[1]);
458 printf("%d..%d X %d..%d\n", xmin, xmax, ymin, ymax);
459 */
460 for (y = ymin; y <= ymax; y++) {
461 for (x = xmin; x <= xmax; x++) {
462 const GLfloat dx = x + 0.5F - vert->win[0];
463 const GLfloat dy = y + 0.5F - vert->win[1];
464 const GLfloat dist2 = dx*dx + dy*dy;
465 if (dist2 < rmax2) {
466 GLint alpha = vert->color[3];
467 if (dist2 >= rmin2) {
468 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
469 /* coverage is in [0,256] */
470 alpha = (alpha * coverage) >> 8;
471 }
472 PB_WRITE_RGBA_PIXEL(PB, x, y, z, fog,
473 red, green, blue, alpha);
474 }
475 }
476 }
477 PB_CHECK_FLUSH(ctx,PB);
478 }
479 }
480
481
482
483 /* Definition of the functions for GL_EXT_point_parameters */
484
485 /* Calculates the distance attenuation formula of a vector of points in
486 * eye space coordinates
487 */
488 static GLfloat attenuation_distance(const GLcontext *ctx, const GLfloat *pos)
489 {
490 GLfloat dist = GL_SQRT(pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]);
491 return 1.0F / (ctx->Point.Params[0] +
492 dist * (ctx->Point.Params[1] +
493 dist * ctx->Point.Params[2]));
494 }
495
496
497
498
499
500 /*
501 * Distance Attenuated General CI points.
502 */
503 static void
504 dist_atten_general_ci_point( GLcontext *ctx, SWvertex *vert )
505 {
506 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
507 const GLfloat psize = ctx->Point.Size;
508 GLfloat dist = attenuation_distance( ctx, vert->eye );
509 GLint x0, x1, y0, y1;
510 GLint ix, iy;
511 GLint isize, radius;
512 GLint x = (GLint) vert->win[0];
513 GLint y = (GLint) vert->win[1];
514 GLint z = (GLint) (vert->win[2]);
515 GLfloat dsize = psize * dist;
516
517 GLfixed fog = FloatToFixed( vert->fog );
518
519 if (dsize >= ctx->Point.Threshold) {
520 isize = (GLint) (MIN2(dsize, ctx->Point.MaxSize) + 0.5F);
521 }
522 else {
523 isize = (GLint) (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) + 0.5F);
524 }
525 radius = isize >> 1;
526
527 if (isize & 1) {
528 /* odd size */
529 x0 = x - radius;
530 x1 = x + radius;
531 y0 = y - radius;
532 y1 = y + radius;
533 }
534 else {
535 /* even size */
536 x0 = (GLint) (x + 1.5F) - radius;
537 x1 = x0 + isize - 1;
538 y0 = (GLint) (y + 1.5F) - radius;
539 y1 = y0 + isize - 1;
540 }
541
542 PB_SET_INDEX( PB, vert->index );
543
544 for (iy=y0;iy<=y1;iy++) {
545 for (ix=x0;ix<=x1;ix++) {
546 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
547 }
548 }
549 PB_CHECK_FLUSH(ctx,PB);
550 }
551
552 /*
553 * Distance Attenuated General RGBA points.
554 */
555 static void
556 dist_atten_general_rgba_point( GLcontext *ctx, SWvertex *vert )
557 {
558 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
559 const GLfloat psize = ctx->Point.Size;
560 GLfloat dist = attenuation_distance( ctx, vert->eye );
561 GLint x0, x1, y0, y1;
562 GLint ix, iy;
563 GLint isize, radius;
564 GLint x = (GLint) vert->win[0];
565 GLint y = (GLint) vert->win[1];
566 GLint z = (GLint) (vert->win[2]);
567 GLfloat dsize=psize*dist;
568 GLchan alpha;
569 GLfixed fog = FloatToFixed( vert->fog );
570
571 if (dsize >= ctx->Point.Threshold) {
572 isize = (GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F);
573 alpha = vert->color[3];
574 }
575 else {
576 isize = (GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F);
577 dsize /= ctx->Point.Threshold;
578 alpha = (GLint) (vert->color[3]* (dsize*dsize));
579 }
580 radius = isize >> 1;
581
582 if (isize & 1) {
583 /* odd size */
584 x0 = x - radius;
585 x1 = x + radius;
586 y0 = y - radius;
587 y1 = y + radius;
588 }
589 else {
590 /* even size */
591 x0 = (GLint) (x + 1.5F) - radius;
592 x1 = x0 + isize - 1;
593 y0 = (GLint) (y + 1.5F) - radius;
594 y1 = y0 + isize - 1;
595 }
596
597 PB_SET_COLOR( PB,
598 vert->color[0],
599 vert->color[1],
600 vert->color[2],
601 alpha );
602
603 for (iy = y0; iy <= y1; iy++) {
604 for (ix = x0; ix <= x1; ix++) {
605 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
606 }
607 }
608 PB_CHECK_FLUSH(ctx,PB);
609 }
610
611 /*
612 * Distance Attenuated Textured RGBA points.
613 */
614 static void
615 dist_atten_textured_rgba_point( GLcontext *ctx, SWvertex *vert )
616 {
617 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
618 const GLfloat psize = ctx->Point.Size;
619 GLfloat dist = attenuation_distance( ctx, vert->eye );
620
621 const GLint x = (GLint) vert->win[0];
622 const GLint y = (GLint) vert->win[1];
623 const GLint z = (GLint) (vert->win[2]);
624 const GLint red = vert->color[0];
625 const GLint green = vert->color[1];
626 const GLint blue = vert->color[2];
627 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
628 GLint x0, x1, y0, y1;
629 GLint ix, iy, alpha, u;
630 GLint isize, radius;
631 GLfloat dsize = psize*dist;
632
633 GLfixed fog = FloatToFixed( vert->fog );
634
635 /* compute point size and alpha */
636 if (dsize >= ctx->Point.Threshold) {
637 isize = (GLint) (MIN2(dsize, ctx->Point.MaxSize) + 0.5F);
638 alpha = vert->color[3];
639 }
640 else {
641 isize = (GLint) (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) + 0.5F);
642 dsize /= ctx->Point.Threshold;
643 alpha = (GLint) (vert->color[3] * (dsize * dsize));
644 }
645 if (isize < 1) {
646 isize = 1;
647 }
648 radius = isize >> 1;
649
650 if (isize & 1) {
651 /* odd size */
652 x0 = x - radius;
653 x1 = x + radius;
654 y0 = y - radius;
655 y1 = y + radius;
656 }
657 else {
658 /* even size */
659 x0 = (GLint) (x + 1.5F) - radius;
660 x1 = x0 + isize - 1;
661 y0 = (GLint) (y + 1.5F) - radius;
662 y1 = y0 + isize - 1;
663 }
664
665 /* get texture coordinates */
666 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
667 if (ctx->Texture.Unit[u]._ReallyEnabled) {
668 if (texcoord[u][3] != 1.0) {
669 texcoord[u][0] = vert->texcoord[u][0] /
670 vert->texcoord[u][3];
671 texcoord[u][1] = vert->texcoord[u][1] /
672 vert->texcoord[u][3];
673 texcoord[u][2] = vert->texcoord[u][2] /
674 vert->texcoord[u][3];
675 }
676 else {
677 texcoord[u][0] = vert->texcoord[u][0];
678 texcoord[u][1] = vert->texcoord[u][1];
679 texcoord[u][2] = vert->texcoord[u][2];
680 }
681 }
682 }
683
684 for (iy = y0; iy <= y1; iy++) {
685 for (ix = x0; ix <= x1; ix++) {
686 if (ctx->Texture._MultiTextureEnabled) {
687 PB_WRITE_MULTITEX_PIXEL( PB, ix, iy, z, fog,
688 red, green, blue, alpha,
689 texcoord );
690 }
691 else {
692 PB_WRITE_TEX_PIXEL( PB, ix, iy, z, fog,
693 red, green, blue, alpha,
694 texcoord[0][0],
695 texcoord[0][1],
696 texcoord[0][2] );
697 }
698 }
699 }
700 PB_CHECK_FLUSH(ctx,PB);
701 }
702
703 /*
704 * Distance Attenuated Antialiased points with or without texture mapping.
705 */
706 static void
707 dist_atten_antialiased_rgba_point( GLcontext *ctx, SWvertex *vert )
708 {
709 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
710 const GLfloat psize = ctx->Point.Size;
711 GLfloat dist = attenuation_distance( ctx, vert->eye );
712
713 if (ctx->Texture._ReallyEnabled) {
714 GLfloat radius, rmin, rmax, rmin2, rmax2, cscale, alphaf;
715 GLint xmin, ymin, xmax, ymax;
716 GLint x, y, z;
717 GLint red, green, blue, alpha;
718 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
719 GLfloat dsize = psize * dist;
720 GLint u;
721
722 GLfixed fog = FloatToFixed( vert->fog );
723
724 if (dsize >= ctx->Point.Threshold) {
725 radius = MIN2(dsize, ctx->Point.MaxSize) * 0.5F;
726 alphaf = 1.0F;
727 }
728 else {
729 radius = (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) * 0.5F);
730 dsize /= ctx->Point.Threshold;
731 alphaf = (dsize*dsize);
732 }
733 rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
734 rmax = radius + 0.7071F;
735 rmin2 = MAX2(0.0, rmin * rmin);
736 rmax2 = rmax * rmax;
737 cscale = 256.0F / (rmax2 - rmin2);
738
739 xmin = (GLint) (vert->win[0] - radius);
740 xmax = (GLint) (vert->win[0] + radius);
741 ymin = (GLint) (vert->win[1] - radius);
742 ymax = (GLint) (vert->win[1] + radius);
743 z = (GLint) (vert->win[2]);
744
745 red = vert->color[0];
746 green = vert->color[1];
747 blue = vert->color[2];
748
749 /* get texture coordinates */
750 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
751 if (ctx->Texture.Unit[u]._ReallyEnabled) {
752 if (vert->texcoord[u][3] != 1.0 && vert->texcoord[u][3] != 0.0) {
753 texcoord[u][0] = vert->texcoord[u][0] / vert->texcoord[u][3];
754 texcoord[u][1] = vert->texcoord[u][1] / vert->texcoord[u][3];
755 texcoord[u][2] = vert->texcoord[u][2] / vert->texcoord[u][3];
756 }
757 else {
758 texcoord[u][0] = vert->texcoord[u][0];
759 texcoord[u][1] = vert->texcoord[u][1];
760 texcoord[u][2] = vert->texcoord[u][2];
761 }
762 }
763 }
764
765 for (y = ymin; y <= ymax; y++) {
766 for (x = xmin; x <= xmax; x++) {
767 const GLfloat dx = x + 0.5F - vert->win[0];
768 const GLfloat dy = y + 0.5F - vert->win[1];
769 const GLfloat dist2 = dx*dx + dy*dy;
770 if (dist2 < rmax2) {
771 alpha = vert->color[3];
772 if (dist2 >= rmin2) {
773 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
774 /* coverage is in [0,256] */
775 alpha = (alpha * coverage) >> 8;
776 }
777 alpha = (GLint) (alpha * alphaf);
778 if (ctx->Texture._MultiTextureEnabled) {
779 PB_WRITE_MULTITEX_PIXEL( PB, x, y, z, fog,
780 red, green, blue, alpha,
781 texcoord );
782 }
783 else {
784 PB_WRITE_TEX_PIXEL( PB, x,y,z, fog,
785 red, green, blue, alpha,
786 texcoord[0][0],
787 texcoord[0][1],
788 texcoord[0][2] );
789 }
790 }
791 }
792 }
793 PB_CHECK_FLUSH(ctx,PB);
794 }
795 else {
796 /* Not texture mapped */
797 GLfloat radius, rmin, rmax, rmin2, rmax2, cscale, alphaf;
798 GLint xmin, ymin, xmax, ymax;
799 GLint x, y, z;
800 GLfixed fog;
801 GLint red, green, blue, alpha;
802 GLfloat dsize = psize * dist;
803
804 if (dsize >= ctx->Point.Threshold) {
805 radius = MIN2(dsize, ctx->Point.MaxSize) * 0.5F;
806 alphaf = 1.0F;
807 }
808 else {
809 radius = (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) * 0.5F);
810 dsize /= ctx->Point.Threshold;
811 alphaf = dsize * dsize;
812 }
813 rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
814 rmax = radius + 0.7071F;
815 rmin2 = MAX2(0.0, rmin * rmin);
816 rmax2 = rmax * rmax;
817 cscale = 256.0F / (rmax2 - rmin2);
818
819 xmin = (GLint) (vert->win[0] - radius);
820 xmax = (GLint) (vert->win[0] + radius);
821 ymin = (GLint) (vert->win[1] - radius);
822 ymax = (GLint) (vert->win[1] + radius);
823 z = (GLint) (vert->win[2]);
824
825 fog = FloatToFixed( vert->fog );
826
827 red = vert->color[0];
828 green = vert->color[1];
829 blue = vert->color[2];
830
831 for (y = ymin; y <= ymax; y++) {
832 for (x = xmin; x <= xmax; x++) {
833 const GLfloat dx = x + 0.5F - vert->win[0];
834 const GLfloat dy = y + 0.5F - vert->win[1];
835 const GLfloat dist2 = dx * dx + dy * dy;
836 if (dist2 < rmax2) {
837 alpha = vert->color[3];
838 if (dist2 >= rmin2) {
839 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
840 /* coverage is in [0,256] */
841 alpha = (alpha * coverage) >> 8;
842 }
843 alpha = (GLint) (alpha * alphaf);
844 PB_WRITE_RGBA_PIXEL(PB, x, y, z, fog,
845 red, green, blue, alpha);
846 }
847 }
848 }
849 PB_CHECK_FLUSH(ctx,PB);
850 }
851 }
852
853
854 #ifdef DEBUG
855 void
856 _mesa_print_point_function(GLcontext *ctx)
857 {
858 SWcontext *swrast = SWRAST_CONTEXT(ctx);
859
860 printf("Point Func == ");
861 if (swrast->Point == size1_ci_point)
862 printf("size1_ci_point\n");
863 else if (swrast->Point == size1_rgba_point)
864 printf("size1_rgba_point\n");
865 else if (swrast->Point == general_ci_point)
866 printf("general_ci_point\n");
867 else if (swrast->Point == general_rgba_point)
868 printf("general_rgba_point\n");
869 else if (swrast->Point == textured_rgba_point)
870 printf("textured_rgba_point\n");
871 else if (swrast->Point == multitextured_rgba_point)
872 printf("multitextured_rgba_point\n");
873 else if (swrast->Point == antialiased_rgba_point)
874 printf("antialiased_rgba_point\n");
875 else if (swrast->Point == dist_atten_general_ci_point)
876 printf("dist_atten_general_ci_point\n");
877 else if (swrast->Point == dist_atten_general_rgba_point)
878 printf("dist_atten_general_rgba_point\n");
879 else if (swrast->Point == dist_atten_textured_rgba_point)
880 printf("dist_atten_textured_rgba_point\n");
881 else if (swrast->Point == dist_atten_antialiased_rgba_point)
882 printf("dist_atten_antialiased_rgba_point\n");
883 else if (!swrast->Point)
884 printf("NULL\n");
885 else
886 printf("Driver func %p\n", swrast->Point);
887 }
888 #endif
889
890
891 /*
892 * Examine the current context to determine which point drawing function
893 * should be used.
894 */
895 void
896 _swrast_choose_point( GLcontext *ctx )
897 {
898 SWcontext *swrast = SWRAST_CONTEXT(ctx);
899 GLboolean rgbmode = ctx->Visual.RGBAflag;
900
901 if (ctx->RenderMode==GL_RENDER) {
902 if (!ctx->Point._Attenuated) {
903 if (ctx->Point.SmoothFlag && rgbmode) {
904 swrast->Point = antialiased_rgba_point;
905 }
906 else if (ctx->Texture._ReallyEnabled) {
907 if (ctx->Texture._MultiTextureEnabled ||
908 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR ||
909 ctx->Fog.ColorSumEnabled) {
910 swrast->Point = multitextured_rgba_point;
911 }
912 else {
913 swrast->Point = textured_rgba_point;
914 }
915 }
916 else if (ctx->Point.Size==1.0) {
917 /* size=1, any raster ops */
918 if (rgbmode)
919 swrast->Point = size1_rgba_point;
920 else
921 swrast->Point = size1_ci_point;
922 }
923 else {
924 /* every other kind of point rendering */
925 if (rgbmode)
926 swrast->Point = general_rgba_point;
927 else
928 swrast->Point = general_ci_point;
929 }
930 }
931 else if(ctx->Point.SmoothFlag && rgbmode) {
932 swrast->Point = dist_atten_antialiased_rgba_point;
933 }
934 else if (ctx->Texture._ReallyEnabled) {
935 swrast->Point = dist_atten_textured_rgba_point;
936 }
937 else {
938 /* every other kind of point rendering */
939 if (rgbmode)
940 swrast->Point = dist_atten_general_rgba_point;
941 else
942 swrast->Point = dist_atten_general_ci_point;
943 }
944 }
945 else if (ctx->RenderMode==GL_FEEDBACK) {
946 swrast->Point = gl_feedback_point;
947 }
948 else {
949 /* GL_SELECT mode */
950 swrast->Point = gl_select_point;
951 }
952
953 /*_mesa_print_points_function(ctx);*/
954 }
955