xref: /reactos/dll/opengl/mesa/points.c (revision 5f2bebf7)
1 /* $Id: points.c,v 1.15 1998/02/03 23:46:00 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.5
6  * Copyright (C) 1995-1997  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: points.c,v $
26  * Revision 1.15  1998/02/03 23:46:00  brianp
27  * fixed a few problems with condition expressions for Amiga StormC compiler
28  *
29  * Revision 1.14  1997/10/29 01:29:09  brianp
30  * added GL_EXT_point_parameters extension from Daniel Barrero
31  *
32  * Revision 1.13  1997/07/24 01:23:44  brianp
33  * changed precompiled header symbol from PCH to PC_HEADER
34  *
35  * Revision 1.12  1997/06/20 02:50:39  brianp
36  * changed color components from GLfixed to GLubyte
37  *
38  * Revision 1.11  1997/05/28 03:26:02  brianp
39  * added precompiled header (PCH) support
40  *
41  * Revision 1.10  1997/05/03 00:51:02  brianp
42  * removed calls to gl_texturing_enabled()
43  *
44  * Revision 1.9  1997/04/14 02:00:39  brianp
45  * #include "texstate.h" instead of "texture.h"
46  *
47  * Revision 1.8  1997/04/12 12:24:43  brianp
48  * replaced ctx->PointsFunc with ctx->Driver.PointsFunc
49  *
50  * Revision 1.7  1997/04/02 03:11:38  brianp
51  * replaced VB->Unclipped with VB->ClipMask
52  *
53  * Revision 1.6  1997/03/08 02:04:27  brianp
54  * better implementation of feedback function
55  *
56  * Revision 1.5  1997/02/09 18:43:52  brianp
57  * added GL_EXT_texture3D support
58  *
59  * Revision 1.4  1997/01/09 19:48:00  brianp
60  * now call gl_texturing_enabled()
61  *
62  * Revision 1.3  1996/11/08 02:21:21  brianp
63  * added null drawing function for GL_NO_RASTER
64  *
65  * Revision 1.2  1996/09/15 14:18:37  brianp
66  * now use GLframebuffer and GLvisual
67  *
68  * Revision 1.1  1996/09/13 01:38:16  brianp
69  * Initial revision
70  *
71  */
72 
73 
74 #ifdef PC_HEADER
75 #include "all.h"
76 #else
77 #include "context.h"
78 #include "feedback.h"
79 #include "dlist.h"
80 #include "macros.h"
81 #include "pb.h"
82 #include "span.h"
83 #include "texstate.h"
84 #include "types.h"
85 #include "vb.h"
86 #include "mmath.h"
87 #endif
88 
89 
90 
gl_PointSize(GLcontext * ctx,GLfloat size)91 void gl_PointSize( GLcontext *ctx, GLfloat size )
92 {
93    if (size<=0.0) {
94       gl_error( ctx, GL_INVALID_VALUE, "glPointSize" );
95       return;
96    }
97    if (INSIDE_BEGIN_END(ctx)) {
98       gl_error( ctx, GL_INVALID_OPERATION, "glPointSize" );
99       return;
100    }
101    ctx->Point.Size = size;
102    ctx->NewState |= NEW_RASTER_OPS;
103 }
104 
105 
106 /**********************************************************************/
107 /*****                    Rasterization                           *****/
108 /**********************************************************************/
109 
110 
111 /*
112  * There are 3 pairs (RGBA, CI) of point rendering functions:
113  *   1. simple:  size=1 and no special rasterization functions (fastest)
114  *   2. size1:  size=1 and any rasterization functions
115  *   3. general:  any size and rasterization functions (slowest)
116  *
117  * All point rendering functions take the same two arguments: first and
118  * last which specify that the points specified by VB[first] through
119  * VB[last] are to be rendered.
120  */
121 
122 
123 
124 /*
125  * Put points in feedback buffer.
126  */
feedback_points(GLcontext * ctx,GLuint first,GLuint last)127 static void feedback_points( GLcontext *ctx, GLuint first, GLuint last )
128 {
129    struct vertex_buffer *VB = ctx->VB;
130    GLuint i;
131    GLfloat invRedScale   = ctx->Visual->InvRedScale;
132    GLfloat invGreenScale = ctx->Visual->InvGreenScale;
133    GLfloat invBlueScale  = ctx->Visual->InvBlueScale;
134    GLfloat invAlphaScale = ctx->Visual->InvAlphaScale;
135 
136    for (i=first;i<=last;i++) {
137       if (VB->ClipMask[i]==0) {
138          GLfloat x, y, z, w, invq;
139          GLfloat color[4], texcoord[4];
140 
141          x = VB->Win[i][0];
142          y = VB->Win[i][1];
143          z = VB->Win[i][2] / DEPTH_SCALE;
144          w = VB->Clip[i][3];
145 
146          /* convert color from integer back to a float in [0,1] */
147          if (ctx->Light.ShadeModel==GL_SMOOTH) {
148             /* smooth shading - colors are in fixed point */
149             color[0] = FixedToFloat(VB->Color[i][0]) * invRedScale;
150             color[1] = FixedToFloat(VB->Color[i][1]) * invGreenScale;
151             color[2] = FixedToFloat(VB->Color[i][2]) * invBlueScale;
152             color[3] = FixedToFloat(VB->Color[i][3]) * invAlphaScale;
153          }
154          else {
155             /* flat shading - colors are integers */
156             color[0] = VB->Color[i][0] * invRedScale;
157             color[1] = VB->Color[i][1] * invGreenScale;
158             color[2] = VB->Color[i][2] * invBlueScale;
159             color[3] = VB->Color[i][3] * invAlphaScale;
160          }
161          invq = 1.0F / VB->TexCoord[i][3];
162          texcoord[0] = VB->TexCoord[i][0] * invq;
163          texcoord[1] = VB->TexCoord[i][1] * invq;
164          texcoord[2] = VB->TexCoord[i][2] * invq;
165          texcoord[3] = VB->TexCoord[i][3];
166 
167          FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POINT_TOKEN );
168          gl_feedback_vertex( ctx, x, y, z, w, color,
169                              (GLfloat) VB->Index[i], texcoord );
170       }
171    }
172 }
173 
174 
175 
176 /*
177  * Put points in selection buffer.
178  */
select_points(GLcontext * ctx,GLuint first,GLuint last)179 static void select_points( GLcontext *ctx, GLuint first, GLuint last )
180 {
181    struct vertex_buffer *VB = ctx->VB;
182    GLuint i;
183 
184    for (i=first;i<=last;i++) {
185       if (VB->ClipMask[i]==0) {
186          gl_update_hitflag( ctx, VB->Win[i][2] / DEPTH_SCALE );
187       }
188    }
189 }
190 
191 
192 /*
193  * CI points with size == 1.0
194  */
size1_ci_points(GLcontext * ctx,GLuint first,GLuint last)195 void size1_ci_points( GLcontext *ctx, GLuint first, GLuint last )
196 {
197    struct vertex_buffer *VB = ctx->VB;
198    struct pixel_buffer *PB = ctx->PB;
199    GLfloat *win;
200    GLint *pbx = PB->x, *pby = PB->y;
201    GLdepth *pbz = PB->z;
202    GLuint *pbi = PB->i;
203    GLuint pbcount = PB->count;
204    GLuint i;
205 
206    win = &VB->Win[first][0];
207    for (i=first;i<=last;i++) {
208       if (VB->ClipMask[i]==0) {
209          pbx[pbcount] = (GLint)  win[0];
210          pby[pbcount] = (GLint)  win[1];
211          pbz[pbcount] = (GLint) (win[2] + ctx->PointZoffset);
212          pbi[pbcount] = VB->Index[i];
213          pbcount++;
214       }
215       win += 3;
216    }
217    PB->count = pbcount;
218    PB_CHECK_FLUSH(ctx, PB)
219 }
220 
221 
222 
223 /*
224  * RGBA points with size == 1.0
225  */
size1_rgba_points(GLcontext * ctx,GLuint first,GLuint last)226 static void size1_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
227 {
228    struct vertex_buffer *VB = ctx->VB;
229    struct pixel_buffer *PB = ctx->PB;
230    GLuint i;
231 
232    for (i=first;i<=last;i++) {
233       if (VB->ClipMask[i]==0) {
234          GLint x, y, z;
235          GLint red, green, blue, alpha;
236 
237          x = (GLint)  VB->Win[i][0];
238          y = (GLint)  VB->Win[i][1];
239          z = (GLint) (VB->Win[i][2] + ctx->PointZoffset);
240 
241          red   = VB->Color[i][0];
242          green = VB->Color[i][1];
243          blue  = VB->Color[i][2];
244          alpha = VB->Color[i][3];
245 
246          PB_WRITE_RGBA_PIXEL( PB, x, y, z, red, green, blue, alpha );
247       }
248    }
249    PB_CHECK_FLUSH(ctx,PB)
250 }
251 
252 
253 
254 /*
255  * General CI points.
256  */
general_ci_points(GLcontext * ctx,GLuint first,GLuint last)257 static void general_ci_points( GLcontext *ctx, GLuint first, GLuint last )
258 {
259    struct vertex_buffer *VB = ctx->VB;
260    struct pixel_buffer *PB = ctx->PB;
261    GLuint i;
262    GLint isize;
263 
264    isize = (GLint) (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F);
265 
266    for (i=first;i<=last;i++) {
267       if (VB->ClipMask[i]==0) {
268          GLint x, y, z;
269          GLint x0, x1, y0, y1;
270          GLint ix, iy;
271 
272          x = (GLint)  VB->Win[i][0];
273          y = (GLint)  VB->Win[i][1];
274          z = (GLint) (VB->Win[i][2] + ctx->PointZoffset);
275 
276          if (isize&1) {
277             /* odd size */
278             x0 = x - isize/2;
279             x1 = x + isize/2;
280             y0 = y - isize/2;
281             y1 = y + isize/2;
282          }
283          else {
284             /* even size */
285             x0 = (GLint) (x + 0.5F) - isize/2;
286             x1 = x0 + isize-1;
287             y0 = (GLint) (y + 0.5F) - isize/2;
288             y1 = y0 + isize-1;
289          }
290 
291          PB_SET_INDEX( ctx, PB, VB->Index[i] );
292 
293          for (iy=y0;iy<=y1;iy++) {
294             for (ix=x0;ix<=x1;ix++) {
295                PB_WRITE_PIXEL( PB, ix, iy, z );
296             }
297          }
298          PB_CHECK_FLUSH(ctx,PB)
299       }
300    }
301 }
302 
303 
304 /*
305  * General RGBA points.
306  */
general_rgba_points(GLcontext * ctx,GLuint first,GLuint last)307 static void general_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
308 {
309    struct vertex_buffer *VB = ctx->VB;
310    struct pixel_buffer *PB = ctx->PB;
311    GLuint i;
312    GLint isize;
313 
314    isize = (GLint) (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F);
315 
316    for (i=first;i<=last;i++) {
317       if (VB->ClipMask[i]==0) {
318          GLint x, y, z;
319          GLint x0, x1, y0, y1;
320          GLint ix, iy;
321 
322          x = (GLint)  VB->Win[i][0];
323          y = (GLint)  VB->Win[i][1];
324          z = (GLint) (VB->Win[i][2] + ctx->PointZoffset);
325 
326          if (isize&1) {
327             /* odd size */
328             x0 = x - isize/2;
329             x1 = x + isize/2;
330             y0 = y - isize/2;
331             y1 = y + isize/2;
332          }
333          else {
334             /* even size */
335             x0 = (GLint) (x + 0.5F) - isize/2;
336             x1 = x0 + isize-1;
337             y0 = (GLint) (y + 0.5F) - isize/2;
338             y1 = y0 + isize-1;
339          }
340 
341          PB_SET_COLOR( ctx, PB,
342                        VB->Color[i][0],
343                        VB->Color[i][1],
344                        VB->Color[i][2],
345                        VB->Color[i][3] );
346 
347          for (iy=y0;iy<=y1;iy++) {
348             for (ix=x0;ix<=x1;ix++) {
349                PB_WRITE_PIXEL( PB, ix, iy, z );
350             }
351          }
352          PB_CHECK_FLUSH(ctx,PB)
353       }
354    }
355 }
356 
357 
358 
359 
360 /*
361  * Textured RGBA points.
362  */
textured_rgba_points(GLcontext * ctx,GLuint first,GLuint last)363 static void textured_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
364 {
365    struct vertex_buffer *VB = ctx->VB;
366    struct pixel_buffer *PB = ctx->PB;
367    GLuint i;
368 
369    for (i=first;i<=last;i++) {
370       if (VB->ClipMask[i]==0) {
371          GLint x, y, z;
372          GLint x0, x1, y0, y1;
373          GLint ix, iy;
374          GLint isize;
375          GLint red, green, blue, alpha;
376          GLfloat s, t, u;
377 
378          x = (GLint)  VB->Win[i][0];
379          y = (GLint)  VB->Win[i][1];
380          z = (GLint) (VB->Win[i][2] + ctx->PointZoffset);
381 
382          isize = (GLint)
383                    (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F);
384          if (isize<1) {
385             isize = 1;
386          }
387 
388          if (isize&1) {
389             /* odd size */
390             x0 = x - isize/2;
391             x1 = x + isize/2;
392             y0 = y - isize/2;
393             y1 = y + isize/2;
394          }
395          else {
396             /* even size */
397             x0 = (GLint) (x + 0.5F) - isize/2;
398             x1 = x0 + isize-1;
399             y0 = (GLint) (y + 0.5F) - isize/2;
400             y1 = y0 + isize-1;
401          }
402 
403          red   = VB->Color[i][0];
404          green = VB->Color[i][1];
405          blue  = VB->Color[i][2];
406          alpha = VB->Color[i][3];
407          s = VB->TexCoord[i][0] / VB->TexCoord[i][3];
408          t = VB->TexCoord[i][1] / VB->TexCoord[i][3];
409          u = VB->TexCoord[i][2] / VB->TexCoord[i][3];
410 
411 /*    don't think this is needed
412          PB_SET_COLOR( red, green, blue, alpha );
413 */
414 
415          for (iy=y0;iy<=y1;iy++) {
416             for (ix=x0;ix<=x1;ix++) {
417                PB_WRITE_TEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u );
418             }
419          }
420          PB_CHECK_FLUSH(ctx,PB)
421       }
422    }
423 }
424 
425 
426 
427 /*
428  * Antialiased points with or without texture mapping.
429  */
antialiased_rgba_points(GLcontext * ctx,GLuint first,GLuint last)430 static void antialiased_rgba_points( GLcontext *ctx,
431                                      GLuint first, GLuint last )
432 {
433    struct vertex_buffer *VB = ctx->VB;
434    struct pixel_buffer *PB = ctx->PB;
435    GLuint i;
436    GLfloat radius, rmin, rmax, rmin2, rmax2, cscale;
437 
438    radius = CLAMP( ctx->Point.Size, MIN_POINT_SIZE, MAX_POINT_SIZE ) * 0.5F;
439    rmin = radius - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
440    rmax = radius + 0.7071F;
441    rmin2 = rmin*rmin;
442    rmax2 = rmax*rmax;
443    cscale = 256.0F / (rmax2-rmin2);
444 
445    if (ctx->Texture.Enabled) {
446       for (i=first;i<=last;i++) {
447          if (VB->ClipMask[i]==0) {
448             GLint xmin, ymin, xmax, ymax;
449             GLint x, y, z;
450             GLint red, green, blue, alpha;
451             GLfloat s, t, u;
452 
453             xmin = (GLint) (VB->Win[i][0] - radius);
454             xmax = (GLint) (VB->Win[i][0] + radius);
455             ymin = (GLint) (VB->Win[i][1] - radius);
456             ymax = (GLint) (VB->Win[i][1] + radius);
457             z = (GLint) (VB->Win[i][2] + ctx->PointZoffset);
458 
459             red   = VB->Color[i][0];
460             green = VB->Color[i][1];
461             blue  = VB->Color[i][2];
462             s = VB->TexCoord[i][0] / VB->TexCoord[i][3];
463             t = VB->TexCoord[i][1] / VB->TexCoord[i][3];
464             u = VB->TexCoord[i][2] / VB->TexCoord[i][3];
465 
466             for (y=ymin;y<=ymax;y++) {
467                for (x=xmin;x<=xmax;x++) {
468                   GLfloat dx = x/*+0.5F*/ - VB->Win[i][0];
469                   GLfloat dy = y/*+0.5F*/ - VB->Win[i][1];
470                   GLfloat dist2 = dx*dx + dy*dy;
471                   if (dist2<rmax2) {
472                      alpha = VB->Color[i][3];
473                      if (dist2>=rmin2) {
474                         GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale);
475                         /* coverage is in [0,256] */
476                         alpha = (alpha * coverage) >> 8;
477                      }
478                      PB_WRITE_TEX_PIXEL( PB, x,y,z, red, green, blue, alpha, s, t, u );
479                   }
480                }
481             }
482             PB_CHECK_FLUSH(ctx,PB)
483          }
484       }
485    }
486    else {
487       /* Not texture mapped */
488       for (i=first;i<=last;i++) {
489          if (VB->ClipMask[i]==0) {
490             GLint xmin, ymin, xmax, ymax;
491             GLint x, y, z;
492             GLint red, green, blue, alpha;
493 
494             xmin = (GLint) (VB->Win[i][0] - radius);
495             xmax = (GLint) (VB->Win[i][0] + radius);
496             ymin = (GLint) (VB->Win[i][1] - radius);
497             ymax = (GLint) (VB->Win[i][1] + radius);
498             z = (GLint) (VB->Win[i][2] + ctx->PointZoffset);
499 
500             red   = VB->Color[i][0];
501             green = VB->Color[i][1];
502             blue  = VB->Color[i][2];
503 
504             for (y=ymin;y<=ymax;y++) {
505                for (x=xmin;x<=xmax;x++) {
506                   GLfloat dx = x/*+0.5F*/ - VB->Win[i][0];
507                   GLfloat dy = y/*+0.5F*/ - VB->Win[i][1];
508                   GLfloat dist2 = dx*dx + dy*dy;
509                   if (dist2<rmax2) {
510                      alpha = VB->Color[i][3];
511                      if (dist2>=rmin2) {
512                         GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale);
513                         /* coverage is in [0,256] */
514                         alpha = (alpha * coverage) >> 8;
515                      }
516                      PB_WRITE_RGBA_PIXEL( PB, x, y, z, red, green, blue, alpha );
517                   }
518                }
519             }
520             PB_CHECK_FLUSH(ctx,PB)
521          }
522       }
523    }
524 }
525 
526 
527 
528 /*
529  * Null rasterizer for measuring transformation speed.
530  */
null_points(GLcontext * ctx,GLuint first,GLuint last)531 static void null_points( GLcontext *ctx, GLuint first, GLuint last )
532 {
533 }
534 
535 /* Definition of the functions for GL_EXT_point_parameters */
536 
537 /*
538  * Examine the current context to determine which point drawing function
539  * should be used.
540  */
gl_set_point_function(GLcontext * ctx)541 void gl_set_point_function( GLcontext *ctx )
542 {
543    GLboolean rgbmode = ctx->Visual->RGBAflag;
544 
545    if (ctx->RenderMode==GL_RENDER) {
546       if (ctx->NoRaster) {
547          ctx->Driver.PointsFunc = null_points;
548          return;
549       }
550       if (ctx->Driver.PointsFunc) {
551          /* Device driver will draw points. */
552          ctx->Driver.PointsFunc = ctx->Driver.PointsFunc;
553       }
554       else {
555          if (ctx->Point.SmoothFlag && rgbmode) {
556             ctx->Driver.PointsFunc = antialiased_rgba_points;
557          }
558          else if (ctx->Texture.Enabled) {
559 	    ctx->Driver.PointsFunc = textured_rgba_points;
560          }
561          else if (ctx->Point.Size==1.0) {
562             /* size=1, any raster ops */
563             if (rgbmode)
564                ctx->Driver.PointsFunc = size1_rgba_points;
565             else
566                ctx->Driver.PointsFunc = size1_ci_points;
567          }
568          else {
569 	    /* every other kind of point rendering */
570             if (rgbmode)
571                ctx->Driver.PointsFunc = general_rgba_points;
572             else
573                ctx->Driver.PointsFunc = general_ci_points;
574          }
575       }
576    }
577    else if (ctx->RenderMode==GL_FEEDBACK) {
578       ctx->Driver.PointsFunc = feedback_points;
579    }
580    else {
581       /* GL_SELECT mode */
582       ctx->Driver.PointsFunc = select_points;
583    }
584 
585 }
586 
587