Replaced Texture.CurrentD[] with separate Texture.Current1/2/3D vars.
[mesa.git] / src / mesa / swrast / s_points.c
1 /* $Id: s_points.c,v 1.7 2000/11/19 23:10:26 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
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
34 #include "s_context.h"
35 #include "s_feedback.h"
36 #include "s_pb.h"
37 #include "s_points.h"
38 #include "s_span.h"
39
40
41 /**********************************************************************/
42 /***** Rasterization *****/
43 /**********************************************************************/
44
45
46 /*
47 * There are 3 pairs (RGBA, CI) of point rendering functions:
48 * 1. simple: size=1 and no special rasterization functions (fastest)
49 * 2. size1: size=1 and any rasterization functions
50 * 3. general: any size and rasterization functions (slowest)
51 *
52 */
53
54
55
56
57
58 /*
59 * CI points with size == 1.0
60 */
61 static void
62 size1_ci_point( GLcontext *ctx, const SWvertex *vert )
63 {
64 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
65 GLint *pbx = PB->x, *pby = PB->y;
66 GLdepth *pbz = PB->z;
67 GLfixed *pbfog = PB->fog;
68 GLuint *pbi = PB->index;
69 GLuint pbcount = PB->count;
70
71 pbx[pbcount] = (GLint) vert->win[0];
72 pby[pbcount] = (GLint) vert->win[1];
73 pbz[pbcount] = (GLint) vert->win[2];
74 pbfog[pbcount] = FloatToFixed(vert->fog);
75 pbi[pbcount] = vert->index;
76
77 PB->count++;
78 PB_CHECK_FLUSH(ctx, PB);
79 }
80
81
82
83 /*
84 * RGBA points with size == 1.0
85 */
86 static void
87 size1_rgba_point( GLcontext *ctx, const SWvertex *vert )
88 {
89 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
90
91 GLint x = (GLint) vert->win[0];
92 GLint y = (GLint) vert->win[1];
93 GLint z = (GLint) (vert->win[2]);
94 GLfixed fog = FloatToFixed( vert->fog );
95 GLubyte red = vert->color[0];
96 GLubyte green = vert->color[1];
97 GLubyte blue = vert->color[2];
98 GLubyte alpha = vert->color[3];
99
100 PB_WRITE_RGBA_PIXEL( PB, x, y, z, fog, red, green, blue, alpha );
101 PB_CHECK_FLUSH(ctx, PB);
102 }
103
104
105
106 /*
107 * General CI points.
108 */
109 static void
110 general_ci_point( GLcontext *ctx, const SWvertex *vert )
111 {
112 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
113 const GLint isize = (GLint) (ctx->Point._Size + 0.5F);
114 GLint radius = isize >> 1;
115
116 GLint x0, x1, y0, y1;
117 GLint ix, iy;
118
119 GLint x = (GLint) vert->win[0];
120 GLint y = (GLint) vert->win[1];
121 GLint z = (GLint) (vert->win[2]);
122
123 GLfixed fog = FloatToFixed( vert->fog );
124
125 if (isize & 1) {
126 /* odd size */
127 x0 = x - radius;
128 x1 = x + radius;
129 y0 = y - radius;
130 y1 = y + radius;
131 }
132 else {
133 /* even size */
134 x0 = (GLint) (x + 1.5F) - radius;
135 x1 = x0 + isize - 1;
136 y0 = (GLint) (y + 1.5F) - radius;
137 y1 = y0 + isize - 1;
138 }
139
140 PB_SET_INDEX( PB, vert->index );
141
142 for (iy = y0; iy <= y1; iy++) {
143 for (ix = x0; ix <= x1; ix++) {
144 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
145 }
146 }
147 PB_CHECK_FLUSH(ctx,PB);
148 }
149
150
151 /*
152 * General RGBA points.
153 */
154 static void
155 general_rgba_point( GLcontext *ctx, const SWvertex *vert )
156 {
157 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
158 GLint isize = (GLint) (ctx->Point._Size + 0.5F);
159 GLint radius = isize >> 1;
160
161 GLint x0, x1, y0, y1;
162 GLint ix, iy;
163
164 GLint x = (GLint) vert->win[0];
165 GLint y = (GLint) vert->win[1];
166 GLint z = (GLint) (vert->win[2]);
167
168 GLfixed fog = FloatToFixed( vert->fog );
169
170 if (isize & 1) {
171 /* odd size */
172 x0 = x - radius;
173 x1 = x + radius;
174 y0 = y - radius;
175 y1 = y + radius;
176 }
177 else {
178 /* even size */
179 x0 = (GLint) (x + 1.5F) - radius;
180 x1 = x0 + isize - 1;
181 y0 = (GLint) (y + 1.5F) - radius;
182 y1 = y0 + isize - 1;
183 }
184
185 PB_SET_COLOR( PB,
186 vert->color[0],
187 vert->color[1],
188 vert->color[2],
189 vert->color[3] );
190
191 for (iy = y0; iy <= y1; iy++) {
192 for (ix = x0; ix <= x1; ix++) {
193 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
194 }
195 }
196 PB_CHECK_FLUSH(ctx,PB);
197 }
198
199
200
201
202 /*
203 * Textured RGBA points.
204 */
205 static void
206 textured_rgba_point( GLcontext *ctx, const SWvertex *vert )
207 {
208 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
209
210 GLint x0, x1, y0, y1;
211 GLint ix, iy, radius;
212 GLint red, green, blue, alpha;
213 GLfloat s, t, u;
214
215 GLint x = (GLint) vert->win[0];
216 GLint y = (GLint) vert->win[1];
217 GLint z = (GLint) (vert->win[2]);
218 GLint isize = (GLint) (ctx->Point._Size + 0.5F);
219
220 GLfixed fog = FloatToFixed( vert->fog );
221
222 if (isize < 1) {
223 isize = 1;
224 }
225 radius = isize >> 1;
226
227 if (isize & 1) {
228 /* odd size */
229 x0 = x - radius;
230 x1 = x + radius;
231 y0 = y - radius;
232 y1 = y + radius;
233 }
234 else {
235 /* even size */
236 x0 = (GLint) (x + 1.5F) - radius;
237 x1 = x0 + isize - 1;
238 y0 = (GLint) (y + 1.5F) - radius;
239 y1 = y0 + isize - 1;
240 }
241
242 red = vert->color[0];
243 green = vert->color[1];
244 blue = vert->color[2];
245 alpha = vert->color[3];
246
247 if (vert->texcoord[0][3] != 1.0) {
248 s = vert->texcoord[0][0]/vert->texcoord[0][3];
249 t = vert->texcoord[0][1]/vert->texcoord[0][3];
250 u = vert->texcoord[0][2]/vert->texcoord[0][3];
251 } else {
252 s = vert->texcoord[0][0];
253 t = vert->texcoord[0][1];
254 u = vert->texcoord[0][2];
255 }
256
257 for (iy = y0; iy <= y1; iy++) {
258 for (ix = x0; ix <= x1; ix++) {
259 PB_WRITE_TEX_PIXEL( PB, ix, iy, z, fog, red, green, blue, alpha,
260 s, t, u );
261 }
262 }
263
264 PB_CHECK_FLUSH(ctx, PB);
265 }
266
267
268
269 /*
270 * Multitextured RGBA points.
271 */
272 static void
273 multitextured_rgba_point( GLcontext *ctx, const SWvertex *vert )
274 {
275 struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB;
276
277 const GLint red = vert->color[0];
278 const GLint green = vert->color[1];
279 const GLint blue = vert->color[2];
280 const GLint alpha = vert->color[3];
281 const GLint sRed = vert->specular[0];
282 const GLint sGreen = vert->specular[1];
283 const GLint sBlue = vert->specular[2];
284 const GLint x = (GLint) vert->win[0];
285 const GLint y = (GLint) vert->win[1];
286 const GLint z = (GLint) (vert->win[2]);
287 GLint x0, x1, y0, y1;
288 GLint ix, iy;
289 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
290 GLint radius, u;
291 GLint isize = (GLint) (ctx->Point._Size + 0.5F);
292
293 GLfixed fog = FloatToFixed( vert->fog );
294
295 if (isize < 1) {
296 isize = 1;
297 }
298 radius = isize >> 1;
299
300 if (isize & 1) {
301 /* odd size */
302 x0 = x - radius;
303 x1 = x + radius;
304 y0 = y - radius;
305 y1 = y + radius;
306 }
307 else {
308 /* even size */
309 x0 = (GLint) (x + 1.5F) - radius;
310 x1 = x0 + isize - 1;
311 y0 = (GLint) (y + 1.5F) - radius;
312 y1 = y0 + isize - 1;
313 }
314
315 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
316 if (ctx->Texture.Unit[u]._ReallyEnabled) {
317 if (vert->texcoord[u][3] != 1.0) {
318 texcoord[u][0] = vert->texcoord[u][0] /
319 vert->texcoord[u][3];
320 texcoord[u][1] = vert->texcoord[u][1] /
321 vert->texcoord[u][3];
322 texcoord[u][2] = vert->texcoord[u][2] /
323 vert->texcoord[u][3];
324 }
325 else {
326 texcoord[u][0] = vert->texcoord[u][0];
327 texcoord[u][1] = vert->texcoord[u][1];
328 texcoord[u][2] = vert->texcoord[u][2];
329 }
330 }
331 }
332
333 for (iy = y0; iy <= y1; iy++) {
334 for (ix = x0; ix <= x1; ix++) {
335 PB_WRITE_MULTITEX_SPEC_PIXEL( PB, ix, iy, z, fog,
336 red, green, blue, alpha,
337 sRed, sGreen, sBlue,
338 texcoord );
339 }
340 }
341 PB_CHECK_FLUSH(ctx, PB);
342 }
343
344
345 /*
346 * NOTES on aa point rasterization:
347 *
348 * Let d = distance of fragment center from vertex.
349 * if d < rmin2 then
350 * fragment has 100% coverage
351 * else if d > rmax2 then
352 * fragment has 0% coverage
353 * else
354 * fragement has % coverage = (d - rmin2) / (rmax2 - rmin2)
355 */
356
357
358 /*
359 * Antialiased points with or without texture mapping.
360 */
361 static void
362 antialiased_rgba_point( GLcontext *ctx, const SWvertex *vert )
363 {
364 SWcontext *swrast = SWRAST_CONTEXT(ctx);
365 struct pixel_buffer *PB = swrast->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 (swrast->_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, const 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, const 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, const SWvertex *vert )
616 {
617 SWcontext *swrast = SWRAST_CONTEXT(ctx);
618 struct pixel_buffer *PB = swrast->PB;
619 const GLfloat psize = ctx->Point._Size;
620 GLfloat dist = attenuation_distance( ctx, vert->eye );
621
622 const GLint x = (GLint) vert->win[0];
623 const GLint y = (GLint) vert->win[1];
624 const GLint z = (GLint) (vert->win[2]);
625 const GLint red = vert->color[0];
626 const GLint green = vert->color[1];
627 const GLint blue = vert->color[2];
628 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
629 GLint x0, x1, y0, y1;
630 GLint ix, iy, alpha, u;
631 GLint isize, radius;
632 GLfloat dsize = psize*dist;
633
634 GLfixed fog = FloatToFixed( vert->fog );
635
636 /* compute point size and alpha */
637 if (dsize >= ctx->Point.Threshold) {
638 isize = (GLint) (MIN2(dsize, ctx->Point.MaxSize) + 0.5F);
639 alpha = vert->color[3];
640 }
641 else {
642 isize = (GLint) (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) + 0.5F);
643 dsize /= ctx->Point.Threshold;
644 alpha = (GLint) (vert->color[3] * (dsize * dsize));
645 }
646 if (isize < 1) {
647 isize = 1;
648 }
649 radius = isize >> 1;
650
651 if (isize & 1) {
652 /* odd size */
653 x0 = x - radius;
654 x1 = x + radius;
655 y0 = y - radius;
656 y1 = y + radius;
657 }
658 else {
659 /* even size */
660 x0 = (GLint) (x + 1.5F) - radius;
661 x1 = x0 + isize - 1;
662 y0 = (GLint) (y + 1.5F) - radius;
663 y1 = y0 + isize - 1;
664 }
665
666 /* get texture coordinates */
667 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
668 if (ctx->Texture.Unit[u]._ReallyEnabled) {
669 if (texcoord[u][3] != 1.0) {
670 texcoord[u][0] = vert->texcoord[u][0] /
671 vert->texcoord[u][3];
672 texcoord[u][1] = vert->texcoord[u][1] /
673 vert->texcoord[u][3];
674 texcoord[u][2] = vert->texcoord[u][2] /
675 vert->texcoord[u][3];
676 }
677 else {
678 texcoord[u][0] = vert->texcoord[u][0];
679 texcoord[u][1] = vert->texcoord[u][1];
680 texcoord[u][2] = vert->texcoord[u][2];
681 }
682 }
683 }
684
685 for (iy = y0; iy <= y1; iy++) {
686 for (ix = x0; ix <= x1; ix++) {
687 if (swrast->_MultiTextureEnabled) {
688 PB_WRITE_MULTITEX_PIXEL( PB, ix, iy, z, fog,
689 red, green, blue, alpha,
690 texcoord );
691 }
692 else {
693 PB_WRITE_TEX_PIXEL( PB, ix, iy, z, fog,
694 red, green, blue, alpha,
695 texcoord[0][0],
696 texcoord[0][1],
697 texcoord[0][2] );
698 }
699 }
700 }
701 PB_CHECK_FLUSH(ctx,PB);
702 }
703
704 /*
705 * Distance Attenuated Antialiased points with or without texture mapping.
706 */
707 static void
708 dist_atten_antialiased_rgba_point( GLcontext *ctx, const SWvertex *vert )
709 {
710 SWcontext *swrast = SWRAST_CONTEXT(ctx);
711 struct pixel_buffer *PB = swrast->PB;
712 const GLfloat psize = ctx->Point._Size;
713 GLfloat dist = attenuation_distance( ctx, vert->eye );
714
715 if (ctx->Texture._ReallyEnabled) {
716 GLfloat radius, rmin, rmax, rmin2, rmax2, cscale, alphaf;
717 GLint xmin, ymin, xmax, ymax;
718 GLint x, y, z;
719 GLint red, green, blue, alpha;
720 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
721 GLfloat dsize = psize * dist;
722 GLint u;
723
724 GLfixed fog = FloatToFixed( vert->fog );
725
726 if (dsize >= ctx->Point.Threshold) {
727 radius = MIN2(dsize, ctx->Point.MaxSize) * 0.5F;
728 alphaf = 1.0F;
729 }
730 else {
731 radius = (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) * 0.5F);
732 dsize /= ctx->Point.Threshold;
733 alphaf = (dsize*dsize);
734 }
735 rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
736 rmax = radius + 0.7071F;
737 rmin2 = MAX2(0.0, rmin * rmin);
738 rmax2 = rmax * rmax;
739 cscale = 256.0F / (rmax2 - rmin2);
740
741 xmin = (GLint) (vert->win[0] - radius);
742 xmax = (GLint) (vert->win[0] + radius);
743 ymin = (GLint) (vert->win[1] - radius);
744 ymax = (GLint) (vert->win[1] + radius);
745 z = (GLint) (vert->win[2]);
746
747 red = vert->color[0];
748 green = vert->color[1];
749 blue = vert->color[2];
750
751 /* get texture coordinates */
752 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
753 if (ctx->Texture.Unit[u]._ReallyEnabled) {
754 if (vert->texcoord[u][3] != 1.0 && vert->texcoord[u][3] != 0.0) {
755 texcoord[u][0] = vert->texcoord[u][0] / vert->texcoord[u][3];
756 texcoord[u][1] = vert->texcoord[u][1] / vert->texcoord[u][3];
757 texcoord[u][2] = vert->texcoord[u][2] / vert->texcoord[u][3];
758 }
759 else {
760 texcoord[u][0] = vert->texcoord[u][0];
761 texcoord[u][1] = vert->texcoord[u][1];
762 texcoord[u][2] = vert->texcoord[u][2];
763 }
764 }
765 }
766
767 for (y = ymin; y <= ymax; y++) {
768 for (x = xmin; x <= xmax; x++) {
769 const GLfloat dx = x + 0.5F - vert->win[0];
770 const GLfloat dy = y + 0.5F - vert->win[1];
771 const GLfloat dist2 = dx*dx + dy*dy;
772 if (dist2 < rmax2) {
773 alpha = vert->color[3];
774 if (dist2 >= rmin2) {
775 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
776 /* coverage is in [0,256] */
777 alpha = (alpha * coverage) >> 8;
778 }
779 alpha = (GLint) (alpha * alphaf);
780 if (swrast->_MultiTextureEnabled) {
781 PB_WRITE_MULTITEX_PIXEL( PB, x, y, z, fog,
782 red, green, blue, alpha,
783 texcoord );
784 }
785 else {
786 PB_WRITE_TEX_PIXEL( PB, x,y,z, fog,
787 red, green, blue, alpha,
788 texcoord[0][0],
789 texcoord[0][1],
790 texcoord[0][2] );
791 }
792 }
793 }
794 }
795 PB_CHECK_FLUSH(ctx,PB);
796 }
797 else {
798 /* Not texture mapped */
799 GLfloat radius, rmin, rmax, rmin2, rmax2, cscale, alphaf;
800 GLint xmin, ymin, xmax, ymax;
801 GLint x, y, z;
802 GLfixed fog;
803 GLint red, green, blue, alpha;
804 GLfloat dsize = psize * dist;
805
806 if (dsize >= ctx->Point.Threshold) {
807 radius = MIN2(dsize, ctx->Point.MaxSize) * 0.5F;
808 alphaf = 1.0F;
809 }
810 else {
811 radius = (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) * 0.5F);
812 dsize /= ctx->Point.Threshold;
813 alphaf = dsize * dsize;
814 }
815 rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
816 rmax = radius + 0.7071F;
817 rmin2 = MAX2(0.0, rmin * rmin);
818 rmax2 = rmax * rmax;
819 cscale = 256.0F / (rmax2 - rmin2);
820
821 xmin = (GLint) (vert->win[0] - radius);
822 xmax = (GLint) (vert->win[0] + radius);
823 ymin = (GLint) (vert->win[1] - radius);
824 ymax = (GLint) (vert->win[1] + radius);
825 z = (GLint) (vert->win[2]);
826
827 fog = FloatToFixed( vert->fog );
828
829 red = vert->color[0];
830 green = vert->color[1];
831 blue = vert->color[2];
832
833 for (y = ymin; y <= ymax; y++) {
834 for (x = xmin; x <= xmax; x++) {
835 const GLfloat dx = x + 0.5F - vert->win[0];
836 const GLfloat dy = y + 0.5F - vert->win[1];
837 const GLfloat dist2 = dx * dx + dy * dy;
838 if (dist2 < rmax2) {
839 alpha = vert->color[3];
840 if (dist2 >= rmin2) {
841 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
842 /* coverage is in [0,256] */
843 alpha = (alpha * coverage) >> 8;
844 }
845 alpha = (GLint) (alpha * alphaf);
846 PB_WRITE_RGBA_PIXEL(PB, x, y, z, fog,
847 red, green, blue, alpha);
848 }
849 }
850 }
851 PB_CHECK_FLUSH(ctx,PB);
852 }
853 }
854
855
856 #ifdef DEBUG
857 extern void
858 _mesa_print_point_function(GLcontext *ctx); /* silence compiler warning */
859 void
860 _mesa_print_point_function(GLcontext *ctx)
861 {
862 SWcontext *swrast = SWRAST_CONTEXT(ctx);
863
864 printf("Point Func == ");
865 if (swrast->Point == size1_ci_point)
866 printf("size1_ci_point\n");
867 else if (swrast->Point == size1_rgba_point)
868 printf("size1_rgba_point\n");
869 else if (swrast->Point == general_ci_point)
870 printf("general_ci_point\n");
871 else if (swrast->Point == general_rgba_point)
872 printf("general_rgba_point\n");
873 else if (swrast->Point == textured_rgba_point)
874 printf("textured_rgba_point\n");
875 else if (swrast->Point == multitextured_rgba_point)
876 printf("multitextured_rgba_point\n");
877 else if (swrast->Point == antialiased_rgba_point)
878 printf("antialiased_rgba_point\n");
879 else if (swrast->Point == dist_atten_general_ci_point)
880 printf("dist_atten_general_ci_point\n");
881 else if (swrast->Point == dist_atten_general_rgba_point)
882 printf("dist_atten_general_rgba_point\n");
883 else if (swrast->Point == dist_atten_textured_rgba_point)
884 printf("dist_atten_textured_rgba_point\n");
885 else if (swrast->Point == dist_atten_antialiased_rgba_point)
886 printf("dist_atten_antialiased_rgba_point\n");
887 else if (!swrast->Point)
888 printf("NULL\n");
889 else
890 printf("Driver func %p\n", swrast->Point);
891 }
892 #endif
893
894
895 /*
896 * Examine the current context to determine which point drawing function
897 * should be used.
898 */
899 void
900 _swrast_choose_point( GLcontext *ctx )
901 {
902 SWcontext *swrast = SWRAST_CONTEXT(ctx);
903 GLboolean rgbmode = ctx->Visual.RGBAflag;
904
905 if (ctx->RenderMode==GL_RENDER) {
906 if (!ctx->Point._Attenuated) {
907 if (ctx->Point.SmoothFlag && rgbmode) {
908 swrast->Point = antialiased_rgba_point;
909 }
910 else if (ctx->Texture._ReallyEnabled) {
911 if (swrast->_MultiTextureEnabled ||
912 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR ||
913 ctx->Fog.ColorSumEnabled) {
914 swrast->Point = multitextured_rgba_point;
915 }
916 else {
917 swrast->Point = textured_rgba_point;
918 }
919 }
920 else if (ctx->Point._Size == 1.0) {
921 /* size=1, any raster ops */
922 if (rgbmode)
923 swrast->Point = size1_rgba_point;
924 else
925 swrast->Point = size1_ci_point;
926 }
927 else {
928 /* every other kind of point rendering */
929 if (rgbmode)
930 swrast->Point = general_rgba_point;
931 else
932 swrast->Point = general_ci_point;
933 }
934 }
935 else if(ctx->Point.SmoothFlag && rgbmode) {
936 swrast->Point = dist_atten_antialiased_rgba_point;
937 }
938 else if (ctx->Texture._ReallyEnabled) {
939 swrast->Point = dist_atten_textured_rgba_point;
940 }
941 else {
942 /* every other kind of point rendering */
943 if (rgbmode)
944 swrast->Point = dist_atten_general_rgba_point;
945 else
946 swrast->Point = dist_atten_general_ci_point;
947 }
948 }
949 else if (ctx->RenderMode==GL_FEEDBACK) {
950 swrast->Point = gl_feedback_point;
951 }
952 else {
953 /* GL_SELECT mode */
954 swrast->Point = gl_select_point;
955 }
956
957 /*_mesa_print_points_function(ctx);*/
958 }
959