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