Moved software rasterizer functionality to new directory.
[mesa.git] / src / mesa / swrast / s_points.c
1 /* $Id: s_points.c,v 1.1 2000/10/31 18:00:04 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 "feedback.h"
31 #include "macros.h"
32 #include "mmath.h"
33 #include "texstate.h"
34 #include "vb.h"
35
36 #include "s_pb.h"
37 #include "s_span.h"
38
39
40 /**********************************************************************/
41 /***** Rasterization *****/
42 /**********************************************************************/
43
44
45 /*
46 * There are 3 pairs (RGBA, CI) of point rendering functions:
47 * 1. simple: size=1 and no special rasterization functions (fastest)
48 * 2. size1: size=1 and any rasterization functions
49 * 3. general: any size and rasterization functions (slowest)
50 *
51 * All point rendering functions take the same two arguments: first and
52 * last which specify that the points specified by VB[first] through
53 * VB[last] are to be rendered.
54 */
55
56
57
58
59
60 /*
61 * CI points with size == 1.0
62 */
63 static void
64 size1_ci_points( GLcontext *ctx, GLuint first, GLuint last )
65 {
66 struct vertex_buffer *VB = ctx->VB;
67 struct pixel_buffer *PB = ctx->PB;
68 GLfloat *win, *fog;
69 GLint *pbx = PB->x, *pby = PB->y;
70 GLdepth *pbz = PB->z;
71 GLfixed *pbfog = PB->fog;
72 GLuint *pbi = PB->index;
73 GLuint pbcount = PB->count;
74 GLuint i;
75
76 win = &VB->Win.data[first][0];
77 fog = &VB->FogCoordPtr->data[first];
78
79 for (i = first; i <= last; i++) {
80 if (VB->ClipMask[i] == 0) {
81 pbx[pbcount] = (GLint) win[0];
82 pby[pbcount] = (GLint) win[1];
83 pbz[pbcount] = (GLint) (win[2] + ctx->PointZoffset);
84 pbfog[pbcount] = FloatToFixed(fog[i]);
85 pbi[pbcount] = VB->IndexPtr->data[i];
86 pbcount++;
87 }
88 win += 3;
89 }
90 PB->count = pbcount;
91 PB_CHECK_FLUSH(ctx, PB);
92 }
93
94
95
96 /*
97 * RGBA points with size == 1.0
98 */
99 static void
100 size1_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
101 {
102 struct vertex_buffer *VB = ctx->VB;
103 struct pixel_buffer *PB = ctx->PB;
104 GLuint i;
105
106 for (i = first; i <= last; i++) {
107 if (VB->ClipMask[i] == 0) {
108 GLint x, y, z;
109 GLint fog;
110 GLint red, green, blue, alpha;
111
112 x = (GLint) VB->Win.data[i][0];
113 y = (GLint) VB->Win.data[i][1];
114 z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
115
116 fog = FloatToFixed( VB->FogCoordPtr->data[i] );
117
118 red = VB->ColorPtr->data[i][0];
119 green = VB->ColorPtr->data[i][1];
120 blue = VB->ColorPtr->data[i][2];
121 alpha = VB->ColorPtr->data[i][3];
122
123 PB_WRITE_RGBA_PIXEL( PB, x, y, z, fog, red, green, blue, alpha );
124 }
125 }
126 PB_CHECK_FLUSH(ctx, PB);
127 }
128
129
130
131 /*
132 * General CI points.
133 */
134 static void
135 general_ci_points( GLcontext *ctx, GLuint first, GLuint last )
136 {
137 struct vertex_buffer *VB = ctx->VB;
138 struct pixel_buffer *PB = ctx->PB;
139 const GLint isize = (GLint) (ctx->Point.Size + 0.5F);
140 GLint radius = isize >> 1;
141 GLuint i;
142
143 for (i = first; i <= last; i++) {
144 if (VB->ClipMask[i] == 0) {
145 GLint x0, x1, y0, y1;
146 GLint ix, iy;
147
148 GLint x = (GLint) VB->Win.data[i][0];
149 GLint y = (GLint) VB->Win.data[i][1];
150 GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
151
152 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
153
154 if (isize & 1) {
155 /* odd size */
156 x0 = x - radius;
157 x1 = x + radius;
158 y0 = y - radius;
159 y1 = y + radius;
160 }
161 else {
162 /* even size */
163 x0 = (GLint) (x + 1.5F) - radius;
164 x1 = x0 + isize - 1;
165 y0 = (GLint) (y + 1.5F) - radius;
166 y1 = y0 + isize - 1;
167 }
168
169 PB_SET_INDEX( PB, VB->IndexPtr->data[i] );
170
171 for (iy = y0; iy <= y1; iy++) {
172 for (ix = x0; ix <= x1; ix++) {
173 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
174 }
175 }
176 PB_CHECK_FLUSH(ctx,PB);
177 }
178 }
179 }
180
181
182 /*
183 * General RGBA points.
184 */
185 static void
186 general_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
187 {
188 struct vertex_buffer *VB = ctx->VB;
189 struct pixel_buffer *PB = ctx->PB;
190 GLint isize = (GLint) (ctx->Point.Size + 0.5F);
191 GLint radius = isize >> 1;
192 GLuint i;
193
194 for (i = first; i <= last; i++) {
195 if (VB->ClipMask[i] == 0) {
196 GLint x0, x1, y0, y1;
197 GLint ix, iy;
198
199 GLint x = (GLint) VB->Win.data[i][0];
200 GLint y = (GLint) VB->Win.data[i][1];
201 GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
202
203 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
204
205 if (isize & 1) {
206 /* odd size */
207 x0 = x - radius;
208 x1 = x + radius;
209 y0 = y - radius;
210 y1 = y + radius;
211 }
212 else {
213 /* even size */
214 x0 = (GLint) (x + 1.5F) - radius;
215 x1 = x0 + isize - 1;
216 y0 = (GLint) (y + 1.5F) - radius;
217 y1 = y0 + isize - 1;
218 }
219
220 PB_SET_COLOR( PB,
221 VB->ColorPtr->data[i][0],
222 VB->ColorPtr->data[i][1],
223 VB->ColorPtr->data[i][2],
224 VB->ColorPtr->data[i][3] );
225
226 for (iy = y0; iy <= y1; iy++) {
227 for (ix = x0; ix <= x1; ix++) {
228 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
229 }
230 }
231 PB_CHECK_FLUSH(ctx,PB);
232 }
233 }
234 }
235
236
237
238
239 /*
240 * Textured RGBA points.
241 */
242 static void
243 textured_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
244 {
245 struct vertex_buffer *VB = ctx->VB;
246 struct pixel_buffer *PB = ctx->PB;
247 GLuint i;
248
249 for (i = first; i <= last; i++) {
250 if (VB->ClipMask[i] == 0) {
251 GLint x0, x1, y0, y1;
252 GLint ix, iy, radius;
253 GLint red, green, blue, alpha;
254 GLfloat s, t, u;
255
256 GLint x = (GLint) VB->Win.data[i][0];
257 GLint y = (GLint) VB->Win.data[i][1];
258 GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
259 GLint isize = (GLint) (ctx->Point.Size + 0.5F);
260
261 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
262
263 if (isize < 1) {
264 isize = 1;
265 }
266 radius = isize >> 1;
267
268 if (isize & 1) {
269 /* odd size */
270 x0 = x - radius;
271 x1 = x + radius;
272 y0 = y - radius;
273 y1 = y + radius;
274 }
275 else {
276 /* even size */
277 x0 = (GLint) (x + 1.5F) - radius;
278 x1 = x0 + isize - 1;
279 y0 = (GLint) (y + 1.5F) - radius;
280 y1 = y0 + isize - 1;
281 }
282
283 red = VB->ColorPtr->data[i][0];
284 green = VB->ColorPtr->data[i][1];
285 blue = VB->ColorPtr->data[i][2];
286 alpha = VB->ColorPtr->data[i][3];
287
288 switch (VB->TexCoordPtr[0]->size) {
289 case 4:
290 s = VB->TexCoordPtr[0]->data[i][0]/VB->TexCoordPtr[0]->data[i][3];
291 t = VB->TexCoordPtr[0]->data[i][1]/VB->TexCoordPtr[0]->data[i][3];
292 u = VB->TexCoordPtr[0]->data[i][2]/VB->TexCoordPtr[0]->data[i][3];
293 break;
294 case 3:
295 s = VB->TexCoordPtr[0]->data[i][0];
296 t = VB->TexCoordPtr[0]->data[i][1];
297 u = VB->TexCoordPtr[0]->data[i][2];
298 break;
299 case 2:
300 s = VB->TexCoordPtr[0]->data[i][0];
301 t = VB->TexCoordPtr[0]->data[i][1];
302 u = 0.0;
303 break;
304 case 1:
305 s = VB->TexCoordPtr[0]->data[i][0];
306 t = 0.0;
307 u = 0.0;
308 break;
309 default:
310 /* should never get here */
311 s = t = u = 0.0;
312 gl_problem(ctx, "unexpected texcoord size in textured_rgba_points()");
313 }
314
315 for (iy = y0; iy <= y1; iy++) {
316 for (ix = x0; ix <= x1; ix++) {
317 PB_WRITE_TEX_PIXEL( PB, ix, iy, z, fog, red, green, blue, alpha,
318 s, t, u );
319 }
320 }
321
322 PB_CHECK_FLUSH(ctx, PB);
323 }
324 }
325 }
326
327
328 /*
329 * Multitextured RGBA points.
330 */
331 static void
332 multitextured_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
333 {
334 struct vertex_buffer *VB = ctx->VB;
335 struct pixel_buffer *PB = ctx->PB;
336 GLuint i;
337
338 for (i = first; i <= last; i++) {
339 if (VB->ClipMask[i] == 0) {
340 const GLint red = VB->ColorPtr->data[i][0];
341 const GLint green = VB->ColorPtr->data[i][1];
342 const GLint blue = VB->ColorPtr->data[i][2];
343 const GLint alpha = VB->ColorPtr->data[i][3];
344 const GLint sRed = VB->SecondaryColorPtr->data ? VB->SecondaryColorPtr->data[i][0] : 0;
345 const GLint sGreen = VB->SecondaryColorPtr->data ? VB->SecondaryColorPtr->data[i][1] : 0;
346 const GLint sBlue = VB->SecondaryColorPtr->data ? VB->SecondaryColorPtr->data[i][2] : 0;
347 const GLint x = (GLint) VB->Win.data[i][0];
348 const GLint y = (GLint) VB->Win.data[i][1];
349 const GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
350 GLint x0, x1, y0, y1;
351 GLint ix, iy;
352 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
353 GLint radius, u;
354 GLint isize = (GLint) (ctx->Point.Size + 0.5F);
355
356 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
357
358 if (isize < 1) {
359 isize = 1;
360 }
361 radius = isize >> 1;
362
363 if (isize & 1) {
364 /* odd size */
365 x0 = x - radius;
366 x1 = x + radius;
367 y0 = y - radius;
368 y1 = y + radius;
369 }
370 else {
371 /* even size */
372 x0 = (GLint) (x + 1.5F) - radius;
373 x1 = x0 + isize - 1;
374 y0 = (GLint) (y + 1.5F) - radius;
375 y1 = y0 + isize - 1;
376 }
377
378 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
379 if (ctx->Texture.Unit[u].ReallyEnabled) {
380 switch (VB->TexCoordPtr[0]->size) {
381 case 4:
382 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0] /
383 VB->TexCoordPtr[u]->data[i][3];
384 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1] /
385 VB->TexCoordPtr[u]->data[i][3];
386 texcoord[u][2] = VB->TexCoordPtr[u]->data[i][2] /
387 VB->TexCoordPtr[u]->data[i][3];
388 break;
389 case 3:
390 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
391 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1];
392 texcoord[u][2] = VB->TexCoordPtr[u]->data[i][2];
393 break;
394 case 2:
395 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
396 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1];
397 texcoord[u][2] = 0.0;
398 break;
399 case 1:
400 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
401 texcoord[u][1] = 0.0;
402 texcoord[u][2] = 0.0;
403 break;
404 default:
405 /* should never get here */
406 gl_problem(ctx, "unexpected texcoord size");
407 }
408 }
409 }
410
411 for (iy = y0; iy <= y1; iy++) {
412 for (ix = x0; ix <= x1; ix++) {
413 PB_WRITE_MULTITEX_SPEC_PIXEL( PB, ix, iy, z, fog,
414 red, green, blue, alpha,
415 sRed, sGreen, sBlue,
416 texcoord );
417 }
418 }
419 PB_CHECK_FLUSH(ctx, PB);
420 }
421 }
422 }
423
424
425 /*
426 * NOTES on aa point rasterization:
427 *
428 * Let d = distance of fragment center from vertex.
429 * if d < rmin2 then
430 * fragment has 100% coverage
431 * else if d > rmax2 then
432 * fragment has 0% coverage
433 * else
434 * fragement has % coverage = (d - rmin2) / (rmax2 - rmin2)
435 */
436
437
438 /*
439 * Antialiased points with or without texture mapping.
440 */
441 static void
442 antialiased_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
443 {
444 struct vertex_buffer *VB = ctx->VB;
445 struct pixel_buffer *PB = ctx->PB;
446 const GLfloat radius = ctx->Point.Size * 0.5F;
447 const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
448 const GLfloat rmax = radius + 0.7071F;
449 const GLfloat rmin2 = MAX2(0.0, rmin * rmin);
450 const GLfloat rmax2 = rmax * rmax;
451 const GLfloat cscale = 256.0F / (rmax2 - rmin2);
452 GLuint i;
453
454 if (ctx->Texture.ReallyEnabled) {
455 for (i = first; i <= last; i++) {
456 if (VB->ClipMask[i] == 0) {
457 GLint x, y;
458 GLfloat vx = VB->Win.data[i][0];
459 GLfloat vy = VB->Win.data[i][1];
460 const GLint xmin = (GLint) (vx - radius);
461 const GLint xmax = (GLint) (vx + radius);
462 const GLint ymin = (GLint) (vy - radius);
463 const GLint ymax = (GLint) (vy + radius);
464 const GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
465 const GLint red = VB->ColorPtr->data[i][0];
466 const GLint green = VB->ColorPtr->data[i][1];
467 const GLint blue = VB->ColorPtr->data[i][2];
468 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
469 GLint u, alpha;
470
471 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
472
473 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
474 if (ctx->Texture.Unit[u].ReallyEnabled) {
475 switch (VB->TexCoordPtr[0]->size) {
476 case 4:
477 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0] /
478 VB->TexCoordPtr[u]->data[i][3];
479 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1] /
480 VB->TexCoordPtr[u]->data[i][3];
481 texcoord[u][2] = VB->TexCoordPtr[u]->data[i][2] /
482 VB->TexCoordPtr[u]->data[i][3];
483 break;
484 case 3:
485 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
486 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1];
487 texcoord[u][2] = VB->TexCoordPtr[u]->data[i][2];
488 break;
489 case 2:
490 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
491 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1];
492 texcoord[u][2] = 0.0;
493 break;
494 case 1:
495 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
496 texcoord[u][1] = 0.0;
497 texcoord[u][2] = 0.0;
498 break;
499 default:
500 /* should never get here */
501 gl_problem(ctx, "unexpected texcoord size in antialiased_rgba_points()");
502 }
503 }
504 }
505
506 /* translate by a half pixel to simplify math below */
507 vx -= 0.5F;
508 vx -= 0.5F;
509
510 for (y = ymin; y <= ymax; y++) {
511 for (x = xmin; x <= xmax; x++) {
512 const GLfloat dx = x - vx;
513 const GLfloat dy = y - vy;
514 const GLfloat dist2 = dx*dx + dy*dy;
515 if (dist2 < rmax2) {
516 alpha = VB->ColorPtr->data[i][3];
517 if (dist2 >= rmin2) {
518 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
519 /* coverage is in [0,256] */
520 alpha = (alpha * coverage) >> 8;
521 }
522 if (ctx->Texture.MultiTextureEnabled) {
523 PB_WRITE_MULTITEX_PIXEL( PB, x,y,z, fog,
524 red, green, blue,
525 alpha, texcoord );
526 }
527 else {
528 PB_WRITE_TEX_PIXEL( PB, x,y,z, fog,
529 red, green, blue, alpha,
530 texcoord[0][0],
531 texcoord[0][1],
532 texcoord[0][2] );
533 }
534 }
535 }
536 }
537
538 PB_CHECK_FLUSH(ctx,PB);
539 }
540 }
541 }
542 else {
543 /* Not texture mapped */
544 for (i=first;i<=last;i++) {
545 if (VB->ClipMask[i]==0) {
546 const GLint xmin = (GLint) (VB->Win.data[i][0] - 0.0 - radius);
547 const GLint xmax = (GLint) (VB->Win.data[i][0] - 0.0 + radius);
548 const GLint ymin = (GLint) (VB->Win.data[i][1] - 0.0 - radius);
549 const GLint ymax = (GLint) (VB->Win.data[i][1] - 0.0 + radius);
550 const GLint red = VB->ColorPtr->data[i][0];
551 const GLint green = VB->ColorPtr->data[i][1];
552 const GLint blue = VB->ColorPtr->data[i][2];
553 const GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
554 GLint x, y;
555
556 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
557
558 /*
559 printf("point %g, %g\n", VB->Win.data[i][0], VB->Win.data[i][1]);
560 printf("%d..%d X %d..%d\n", xmin, xmax, ymin, ymax);
561 */
562 for (y = ymin; y <= ymax; y++) {
563 for (x = xmin; x <= xmax; x++) {
564 const GLfloat dx = x + 0.5F - VB->Win.data[i][0];
565 const GLfloat dy = y + 0.5F - VB->Win.data[i][1];
566 const GLfloat dist2 = dx*dx + dy*dy;
567 if (dist2 < rmax2) {
568 GLint alpha = VB->ColorPtr->data[i][3];
569 if (dist2 >= rmin2) {
570 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
571 /* coverage is in [0,256] */
572 alpha = (alpha * coverage) >> 8;
573 }
574 PB_WRITE_RGBA_PIXEL(PB, x, y, z, fog,
575 red, green, blue, alpha);
576 }
577 }
578 }
579 PB_CHECK_FLUSH(ctx,PB);
580 }
581 }
582 }
583 }
584
585
586
587 /*
588 * Null rasterizer for measuring transformation speed.
589 */
590 static void
591 null_points( GLcontext *ctx, GLuint first, GLuint last )
592 {
593 (void) ctx;
594 (void) first;
595 (void) last;
596 }
597
598
599
600 /* Definition of the functions for GL_EXT_point_parameters */
601
602 /* Calculates the distance attenuation formula of a vector of points in
603 * eye space coordinates
604 */
605 static void
606 dist3(GLfloat *out, GLuint first, GLuint last,
607 const GLcontext *ctx, const GLvector4f *v)
608 {
609 GLuint stride = v->stride;
610 const GLfloat *p = VEC_ELT(v, GLfloat, first);
611 GLuint i;
612
613 for (i = first ; i <= last ; i++, STRIDE_F(p, stride) ) {
614 GLfloat dist = GL_SQRT(p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);
615 out[i] = 1.0F / (ctx->Point.Params[0] +
616 dist * (ctx->Point.Params[1] +
617 dist * ctx->Point.Params[2]));
618 }
619 }
620
621
622 static void
623 dist2(GLfloat *out, GLuint first, GLuint last,
624 const GLcontext *ctx, const GLvector4f *v)
625 {
626 GLuint stride = v->stride;
627 const GLfloat *p = VEC_ELT(v, GLfloat, first);
628 GLuint i;
629
630 for (i = first ; i <= last ; i++, STRIDE_F(p, stride) ) {
631 GLfloat dist = GL_SQRT(p[0]*p[0]+p[1]*p[1]);
632 out[i] = 1.0F / (ctx->Point.Params[0] +
633 dist * (ctx->Point.Params[1] +
634 dist * ctx->Point.Params[2]));
635 }
636 }
637
638
639 typedef void (*dist_func)(GLfloat *out, GLuint first, GLuint last,
640 const GLcontext *ctx, const GLvector4f *v);
641
642
643 static dist_func eye_dist_tab[5] = {
644 0,
645 0,
646 dist2,
647 dist3,
648 dist3
649 };
650
651
652
653 /*
654 * Distance Attenuated General CI points.
655 */
656 static void
657 dist_atten_general_ci_points( GLcontext *ctx, GLuint first, GLuint last )
658 {
659 struct vertex_buffer *VB = ctx->VB;
660 struct pixel_buffer *PB = ctx->PB;
661 GLfloat dist[VB_SIZE];
662 const GLfloat psize = ctx->Point.Size;
663 GLuint i;
664
665 ASSERT(ctx->NeedEyeCoords);
666 (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr );
667
668
669 for (i=first;i<=last;i++) {
670 if (VB->ClipMask[i]==0) {
671 GLint x0, x1, y0, y1;
672 GLint ix, iy;
673 GLint isize, radius;
674 GLint x = (GLint) VB->Win.data[i][0];
675 GLint y = (GLint) VB->Win.data[i][1];
676 GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
677 GLfloat dsize = psize * dist[i];
678
679 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
680
681 if (dsize >= ctx->Point.Threshold) {
682 isize = (GLint) (MIN2(dsize, ctx->Point.MaxSize) + 0.5F);
683 }
684 else {
685 isize = (GLint) (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) + 0.5F);
686 }
687 radius = isize >> 1;
688
689 if (isize & 1) {
690 /* odd size */
691 x0 = x - radius;
692 x1 = x + radius;
693 y0 = y - radius;
694 y1 = y + radius;
695 }
696 else {
697 /* even size */
698 x0 = (GLint) (x + 1.5F) - radius;
699 x1 = x0 + isize - 1;
700 y0 = (GLint) (y + 1.5F) - radius;
701 y1 = y0 + isize - 1;
702 }
703
704 PB_SET_INDEX( PB, VB->IndexPtr->data[i] );
705
706 for (iy=y0;iy<=y1;iy++) {
707 for (ix=x0;ix<=x1;ix++) {
708 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
709 }
710 }
711 PB_CHECK_FLUSH(ctx,PB);
712 }
713 }
714 }
715
716 /*
717 * Distance Attenuated General RGBA points.
718 */
719 static void
720 dist_atten_general_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
721 {
722 struct vertex_buffer *VB = ctx->VB;
723 struct pixel_buffer *PB = ctx->PB;
724 GLfloat dist[VB_SIZE];
725 const GLfloat psize = ctx->Point.Size;
726 GLuint i;
727
728 ASSERT (ctx->NeedEyeCoords);
729 (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr );
730
731 for (i=first;i<=last;i++) {
732 if (VB->ClipMask[i]==0) {
733 GLint x0, x1, y0, y1;
734 GLint ix, iy;
735 GLint isize, radius;
736 GLint x = (GLint) VB->Win.data[i][0];
737 GLint y = (GLint) VB->Win.data[i][1];
738 GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
739 GLfloat dsize=psize*dist[i];
740 GLchan alpha;
741 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
742
743 if (dsize >= ctx->Point.Threshold) {
744 isize = (GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F);
745 alpha = VB->ColorPtr->data[i][3];
746 }
747 else {
748 isize = (GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F);
749 dsize /= ctx->Point.Threshold;
750 alpha = (GLint) (VB->ColorPtr->data[i][3]* (dsize*dsize));
751 }
752 radius = isize >> 1;
753
754 if (isize & 1) {
755 /* odd size */
756 x0 = x - radius;
757 x1 = x + radius;
758 y0 = y - radius;
759 y1 = y + radius;
760 }
761 else {
762 /* even size */
763 x0 = (GLint) (x + 1.5F) - radius;
764 x1 = x0 + isize - 1;
765 y0 = (GLint) (y + 1.5F) - radius;
766 y1 = y0 + isize - 1;
767 }
768
769 PB_SET_COLOR( PB,
770 VB->ColorPtr->data[i][0],
771 VB->ColorPtr->data[i][1],
772 VB->ColorPtr->data[i][2],
773 alpha );
774
775 for (iy = y0; iy <= y1; iy++) {
776 for (ix = x0; ix <= x1; ix++) {
777 PB_WRITE_PIXEL( PB, ix, iy, z, fog );
778 }
779 }
780 PB_CHECK_FLUSH(ctx,PB);
781 }
782 }
783 }
784
785 /*
786 * Distance Attenuated Textured RGBA points.
787 */
788 static void
789 dist_atten_textured_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
790 {
791 struct vertex_buffer *VB = ctx->VB;
792 struct pixel_buffer *PB = ctx->PB;
793 GLfloat dist[VB_SIZE];
794 const GLfloat psize = ctx->Point.Size;
795 GLuint i;
796
797 ASSERT(ctx->NeedEyeCoords);
798 (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr );
799
800 for (i=first;i<=last;i++) {
801 if (VB->ClipMask[i]==0) {
802 const GLint x = (GLint) VB->Win.data[i][0];
803 const GLint y = (GLint) VB->Win.data[i][1];
804 const GLint z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
805 const GLint red = VB->ColorPtr->data[i][0];
806 const GLint green = VB->ColorPtr->data[i][1];
807 const GLint blue = VB->ColorPtr->data[i][2];
808 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
809 GLint x0, x1, y0, y1;
810 GLint ix, iy, alpha, u;
811 GLint isize, radius;
812 GLfloat dsize = psize*dist[i];
813
814 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
815
816 /* compute point size and alpha */
817 if (dsize >= ctx->Point.Threshold) {
818 isize = (GLint) (MIN2(dsize, ctx->Point.MaxSize) + 0.5F);
819 alpha = VB->ColorPtr->data[i][3];
820 }
821 else {
822 isize = (GLint) (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) + 0.5F);
823 dsize /= ctx->Point.Threshold;
824 alpha = (GLint) (VB->ColorPtr->data[i][3] * (dsize * dsize));
825 }
826 if (isize < 1) {
827 isize = 1;
828 }
829 radius = isize >> 1;
830
831 if (isize & 1) {
832 /* odd size */
833 x0 = x - radius;
834 x1 = x + radius;
835 y0 = y - radius;
836 y1 = y + radius;
837 }
838 else {
839 /* even size */
840 x0 = (GLint) (x + 1.5F) - radius;
841 x1 = x0 + isize - 1;
842 y0 = (GLint) (y + 1.5F) - radius;
843 y1 = y0 + isize - 1;
844 }
845
846 /* get texture coordinates */
847 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
848 if (ctx->Texture.Unit[u].ReallyEnabled) {
849 switch (VB->TexCoordPtr[0]->size) {
850 case 4:
851 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0] /
852 VB->TexCoordPtr[u]->data[i][3];
853 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1] /
854 VB->TexCoordPtr[u]->data[i][3];
855 texcoord[u][2] = VB->TexCoordPtr[u]->data[i][2] /
856 VB->TexCoordPtr[u]->data[i][3];
857 break;
858 case 3:
859 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
860 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1];
861 texcoord[u][2] = VB->TexCoordPtr[u]->data[i][2];
862 break;
863 case 2:
864 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
865 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1];
866 texcoord[u][2] = 0.0;
867 break;
868 case 1:
869 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
870 texcoord[u][1] = 0.0;
871 texcoord[u][2] = 0.0;
872 break;
873 default:
874 /* should never get here */
875 gl_problem(ctx, "unexpected texcoord size");
876 }
877 }
878 }
879
880 for (iy = y0; iy <= y1; iy++) {
881 for (ix = x0; ix <= x1; ix++) {
882 if (ctx->Texture.MultiTextureEnabled) {
883 PB_WRITE_MULTITEX_PIXEL( PB, ix, iy, z, fog,
884 red, green, blue, alpha,
885 texcoord );
886 }
887 else {
888 PB_WRITE_TEX_PIXEL( PB, ix, iy, z, fog,
889 red, green, blue, alpha,
890 texcoord[0][0],
891 texcoord[0][1],
892 texcoord[0][2] );
893 }
894 }
895 }
896 PB_CHECK_FLUSH(ctx,PB);
897 }
898 }
899 }
900
901 /*
902 * Distance Attenuated Antialiased points with or without texture mapping.
903 */
904 static void
905 dist_atten_antialiased_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
906 {
907 struct vertex_buffer *VB = ctx->VB;
908 struct pixel_buffer *PB = ctx->PB;
909 GLfloat dist[VB_SIZE];
910 const GLfloat psize = ctx->Point.Size;
911 GLuint i;
912
913 ASSERT(ctx->NeedEyeCoords);
914 (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr );
915
916 if (ctx->Texture.ReallyEnabled) {
917 for (i=first;i<=last;i++) {
918 if (VB->ClipMask[i]==0) {
919 GLfloat radius, rmin, rmax, rmin2, rmax2, cscale, alphaf;
920 GLint xmin, ymin, xmax, ymax;
921 GLint x, y, z;
922 GLint red, green, blue, alpha;
923 GLfloat texcoord[MAX_TEXTURE_UNITS][4];
924 GLfloat dsize = psize * dist[i];
925 GLint u;
926
927 GLfixed fog = FloatToFixed( VB->FogCoordPtr->data[i] );
928
929 if (dsize >= ctx->Point.Threshold) {
930 radius = MIN2(dsize, ctx->Point.MaxSize) * 0.5F;
931 alphaf = 1.0F;
932 }
933 else {
934 radius = (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) * 0.5F);
935 dsize /= ctx->Point.Threshold;
936 alphaf = (dsize*dsize);
937 }
938 rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
939 rmax = radius + 0.7071F;
940 rmin2 = MAX2(0.0, rmin * rmin);
941 rmax2 = rmax * rmax;
942 cscale = 256.0F / (rmax2 - rmin2);
943
944 xmin = (GLint) (VB->Win.data[i][0] - radius);
945 xmax = (GLint) (VB->Win.data[i][0] + radius);
946 ymin = (GLint) (VB->Win.data[i][1] - radius);
947 ymax = (GLint) (VB->Win.data[i][1] + radius);
948 z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
949
950 red = VB->ColorPtr->data[i][0];
951 green = VB->ColorPtr->data[i][1];
952 blue = VB->ColorPtr->data[i][2];
953
954 /* get texture coordinates */
955 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
956 if (ctx->Texture.Unit[u].ReallyEnabled) {
957 switch (VB->TexCoordPtr[0]->size) {
958 case 4:
959 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0] /
960 VB->TexCoordPtr[u]->data[i][3];
961 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1] /
962 VB->TexCoordPtr[u]->data[i][3];
963 texcoord[u][2] = VB->TexCoordPtr[u]->data[i][2] /
964 VB->TexCoordPtr[u]->data[i][3];
965 break;
966 case 3:
967 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
968 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1];
969 texcoord[u][2] = VB->TexCoordPtr[u]->data[i][2];
970 break;
971 case 2:
972 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
973 texcoord[u][1] = VB->TexCoordPtr[u]->data[i][1];
974 texcoord[u][2] = 0.0;
975 break;
976 case 1:
977 texcoord[u][0] = VB->TexCoordPtr[u]->data[i][0];
978 texcoord[u][1] = 0.0;
979 texcoord[u][2] = 0.0;
980 break;
981 default:
982 /* should never get here */
983 gl_problem(ctx, "unexpected texcoord size");
984 }
985 }
986 }
987
988 for (y = ymin; y <= ymax; y++) {
989 for (x = xmin; x <= xmax; x++) {
990 const GLfloat dx = x + 0.5F - VB->Win.data[i][0];
991 const GLfloat dy = y + 0.5F - VB->Win.data[i][1];
992 const GLfloat dist2 = dx*dx + dy*dy;
993 if (dist2 < rmax2) {
994 alpha = VB->ColorPtr->data[i][3];
995 if (dist2 >= rmin2) {
996 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
997 /* coverage is in [0,256] */
998 alpha = (alpha * coverage) >> 8;
999 }
1000 alpha = (GLint) (alpha * alphaf);
1001 if (ctx->Texture.MultiTextureEnabled) {
1002 PB_WRITE_MULTITEX_PIXEL( PB, x, y, z, fog,
1003 red, green, blue, alpha,
1004 texcoord );
1005 }
1006 else {
1007 PB_WRITE_TEX_PIXEL( PB, x,y,z, fog,
1008 red, green, blue, alpha,
1009 texcoord[0][0],
1010 texcoord[0][1],
1011 texcoord[0][2] );
1012 }
1013 }
1014 }
1015 }
1016 PB_CHECK_FLUSH(ctx,PB);
1017 }
1018 }
1019 }
1020 else {
1021 /* Not texture mapped */
1022 for (i = first; i <= last; i++) {
1023 if (VB->ClipMask[i] == 0) {
1024 GLfloat radius, rmin, rmax, rmin2, rmax2, cscale, alphaf;
1025 GLint xmin, ymin, xmax, ymax;
1026 GLint x, y, z;
1027 GLfixed fog;
1028 GLint red, green, blue, alpha;
1029 GLfloat dsize = psize * dist[i];
1030
1031 if (dsize >= ctx->Point.Threshold) {
1032 radius = MIN2(dsize, ctx->Point.MaxSize) * 0.5F;
1033 alphaf = 1.0F;
1034 }
1035 else {
1036 radius = (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) * 0.5F);
1037 dsize /= ctx->Point.Threshold;
1038 alphaf = dsize * dsize;
1039 }
1040 rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
1041 rmax = radius + 0.7071F;
1042 rmin2 = MAX2(0.0, rmin * rmin);
1043 rmax2 = rmax * rmax;
1044 cscale = 256.0F / (rmax2 - rmin2);
1045
1046 xmin = (GLint) (VB->Win.data[i][0] - radius);
1047 xmax = (GLint) (VB->Win.data[i][0] + radius);
1048 ymin = (GLint) (VB->Win.data[i][1] - radius);
1049 ymax = (GLint) (VB->Win.data[i][1] + radius);
1050 z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
1051
1052 fog = FloatToFixed( VB->FogCoordPtr->data[i] );
1053
1054 red = VB->ColorPtr->data[i][0];
1055 green = VB->ColorPtr->data[i][1];
1056 blue = VB->ColorPtr->data[i][2];
1057
1058 for (y = ymin; y <= ymax; y++) {
1059 for (x = xmin; x <= xmax; x++) {
1060 const GLfloat dx = x + 0.5F - VB->Win.data[i][0];
1061 const GLfloat dy = y + 0.5F - VB->Win.data[i][1];
1062 const GLfloat dist2 = dx * dx + dy * dy;
1063 if (dist2 < rmax2) {
1064 alpha = VB->ColorPtr->data[i][3];
1065 if (dist2 >= rmin2) {
1066 GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale);
1067 /* coverage is in [0,256] */
1068 alpha = (alpha * coverage) >> 8;
1069 }
1070 alpha = (GLint) (alpha * alphaf);
1071 PB_WRITE_RGBA_PIXEL(PB, x, y, z, fog,
1072 red, green, blue, alpha);
1073 }
1074 }
1075 }
1076 PB_CHECK_FLUSH(ctx,PB);
1077 }
1078 }
1079 }
1080 }
1081
1082
1083 #ifdef DEBUG
1084 void
1085 _mesa_print_points_function(GLcontext *ctx)
1086 {
1087 printf("Point Func == ");
1088 if (ctx->Driver.PointsFunc == size1_ci_points)
1089 printf("size1_ci_points\n");
1090 else if (ctx->Driver.PointsFunc == size1_rgba_points)
1091 printf("size1_rgba_points\n");
1092 else if (ctx->Driver.PointsFunc == general_ci_points)
1093 printf("general_ci_points\n");
1094 else if (ctx->Driver.PointsFunc == general_rgba_points)
1095 printf("general_rgba_points\n");
1096 else if (ctx->Driver.PointsFunc == textured_rgba_points)
1097 printf("textured_rgba_points\n");
1098 else if (ctx->Driver.PointsFunc == multitextured_rgba_points)
1099 printf("multitextured_rgba_points\n");
1100 else if (ctx->Driver.PointsFunc == antialiased_rgba_points)
1101 printf("antialiased_rgba_points\n");
1102 else if (ctx->Driver.PointsFunc == null_points)
1103 printf("null_points\n");
1104 else if (ctx->Driver.PointsFunc == dist_atten_general_ci_points)
1105 printf("dist_atten_general_ci_points\n");
1106 else if (ctx->Driver.PointsFunc == dist_atten_general_rgba_points)
1107 printf("dist_atten_general_rgba_points\n");
1108 else if (ctx->Driver.PointsFunc == dist_atten_textured_rgba_points)
1109 printf("dist_atten_textured_rgba_points\n");
1110 else if (ctx->Driver.PointsFunc == dist_atten_antialiased_rgba_points)
1111 printf("dist_atten_antialiased_rgba_points\n");
1112 else if (!ctx->Driver.PointsFunc)
1113 printf("NULL\n");
1114 else
1115 printf("Driver func %p\n", ctx->Driver.PointsFunc);
1116 }
1117 #endif
1118
1119
1120 /*
1121 * Examine the current context to determine which point drawing function
1122 * should be used.
1123 */
1124 void
1125 _swrast_set_point_function( GLcontext *ctx )
1126 {
1127 GLboolean rgbmode = ctx->Visual.RGBAflag;
1128
1129 if (ctx->RenderMode==GL_RENDER) {
1130 if (ctx->NoRaster) {
1131 ctx->Driver.PointsFunc = null_points;
1132 return;
1133 }
1134 if (ctx->Driver.PointsFunc) {
1135 /* Device driver will draw points. */
1136 ctx->IndirectTriangles &= ~DD_POINT_SW_RASTERIZE;
1137 return;
1138 }
1139
1140 if (!ctx->Point.Attenuated) {
1141 if (ctx->Point.SmoothFlag && rgbmode) {
1142 ctx->Driver.PointsFunc = antialiased_rgba_points;
1143 }
1144 else if (ctx->Texture.ReallyEnabled) {
1145 if (ctx->Texture.MultiTextureEnabled ||
1146 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR ||
1147 ctx->Fog.ColorSumEnabled) {
1148 ctx->Driver.PointsFunc = multitextured_rgba_points;
1149 }
1150 else {
1151 ctx->Driver.PointsFunc = textured_rgba_points;
1152 }
1153 }
1154 else if (ctx->Point.Size==1.0) {
1155 /* size=1, any raster ops */
1156 if (rgbmode)
1157 ctx->Driver.PointsFunc = size1_rgba_points;
1158 else
1159 ctx->Driver.PointsFunc = size1_ci_points;
1160 }
1161 else {
1162 /* every other kind of point rendering */
1163 if (rgbmode)
1164 ctx->Driver.PointsFunc = general_rgba_points;
1165 else
1166 ctx->Driver.PointsFunc = general_ci_points;
1167 }
1168 }
1169 else if(ctx->Point.SmoothFlag && rgbmode) {
1170 ctx->Driver.PointsFunc = dist_atten_antialiased_rgba_points;
1171 }
1172 else if (ctx->Texture.ReallyEnabled) {
1173 ctx->Driver.PointsFunc = dist_atten_textured_rgba_points;
1174 }
1175 else {
1176 /* every other kind of point rendering */
1177 if (rgbmode)
1178 ctx->Driver.PointsFunc = dist_atten_general_rgba_points;
1179 else
1180 ctx->Driver.PointsFunc = dist_atten_general_ci_points;
1181 }
1182 }
1183 else if (ctx->RenderMode==GL_FEEDBACK) {
1184 ctx->Driver.PointsFunc = gl_feedback_points;
1185 }
1186 else {
1187 /* GL_SELECT mode */
1188 ctx->Driver.PointsFunc = gl_select_points;
1189 }
1190
1191 /*_mesa_print_points_function(ctx);*/
1192 }
1193