1 /* $Id: points.c,v 1.15 1998/02/03 23:46:00 brianp Exp $ */
4 * Mesa 3-D graphics library
6 * Copyright (C) 1995-1997 Brian Paul
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.
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.
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.
26 * Revision 1.15 1998/02/03 23:46:00 brianp
27 * fixed a few problems with condition expressions for Amiga StormC compiler
29 * Revision 1.14 1997/10/29 01:29:09 brianp
30 * added GL_EXT_point_parameters extension from Daniel Barrero
32 * Revision 1.13 1997/07/24 01:23:44 brianp
33 * changed precompiled header symbol from PCH to PC_HEADER
35 * Revision 1.12 1997/06/20 02:50:39 brianp
36 * changed color components from GLfixed to GLubyte
38 * Revision 1.11 1997/05/28 03:26:02 brianp
39 * added precompiled header (PCH) support
41 * Revision 1.10 1997/05/03 00:51:02 brianp
42 * removed calls to gl_texturing_enabled()
44 * Revision 1.9 1997/04/14 02:00:39 brianp
45 * #include "texstate.h" instead of "texture.h"
47 * Revision 1.8 1997/04/12 12:24:43 brianp
48 * replaced ctx->PointsFunc with ctx->Driver.PointsFunc
50 * Revision 1.7 1997/04/02 03:11:38 brianp
51 * replaced VB->Unclipped with VB->ClipMask
53 * Revision 1.6 1997/03/08 02:04:27 brianp
54 * better implementation of feedback function
56 * Revision 1.5 1997/02/09 18:43:52 brianp
57 * added GL_EXT_texture3D support
59 * Revision 1.4 1997/01/09 19:48:00 brianp
60 * now call gl_texturing_enabled()
62 * Revision 1.3 1996/11/08 02:21:21 brianp
63 * added null drawing function for GL_NO_RASTER
65 * Revision 1.2 1996/09/15 14:18:37 brianp
66 * now use GLframebuffer and GLvisual
68 * Revision 1.1 1996/09/13 01:38:16 brianp
91 void gl_PointSize( GLcontext
*ctx
, GLfloat size
)
94 gl_error( ctx
, GL_INVALID_VALUE
, "glPointSize" );
97 if (INSIDE_BEGIN_END(ctx
)) {
98 gl_error( ctx
, GL_INVALID_OPERATION
, "glPointSize" );
101 ctx
->Point
.Size
= size
;
102 ctx
->NewState
|= NEW_RASTER_OPS
;
106 /**********************************************************************/
107 /***** Rasterization *****/
108 /**********************************************************************/
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)
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.
125 * Put points in feedback buffer.
127 static void feedback_points( GLcontext
*ctx
, GLuint first
, GLuint last
)
129 struct vertex_buffer
*VB
= ctx
->VB
;
131 GLfloat invRedScale
= ctx
->Visual
->InvRedScale
;
132 GLfloat invGreenScale
= ctx
->Visual
->InvGreenScale
;
133 GLfloat invBlueScale
= ctx
->Visual
->InvBlueScale
;
134 GLfloat invAlphaScale
= ctx
->Visual
->InvAlphaScale
;
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];
143 z
= VB
->Win
[i
][2] / DEPTH_SCALE
;
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
;
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
;
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];
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
);
177 * Put points in selection buffer.
179 static void select_points( GLcontext
*ctx
, GLuint first
, GLuint last
)
181 struct vertex_buffer
*VB
= ctx
->VB
;
184 for (i
=first
;i
<=last
;i
++) {
185 if (VB
->ClipMask
[i
]==0) {
186 gl_update_hitflag( ctx
, VB
->Win
[i
][2] / DEPTH_SCALE
);
193 * CI points with size == 1.0
195 void size1_ci_points( GLcontext
*ctx
, GLuint first
, GLuint last
)
197 struct vertex_buffer
*VB
= ctx
->VB
;
198 struct pixel_buffer
*PB
= ctx
->PB
;
200 GLint
*pbx
= PB
->x
, *pby
= PB
->y
;
201 GLdepth
*pbz
= PB
->z
;
203 GLuint pbcount
= PB
->count
;
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
];
218 PB_CHECK_FLUSH(ctx
, PB
)
224 * RGBA points with size == 1.0
226 static void size1_rgba_points( GLcontext
*ctx
, GLuint first
, GLuint last
)
228 struct vertex_buffer
*VB
= ctx
->VB
;
229 struct pixel_buffer
*PB
= ctx
->PB
;
232 for (i
=first
;i
<=last
;i
++) {
233 if (VB
->ClipMask
[i
]==0) {
235 GLint red
, green
, blue
, alpha
;
237 x
= (GLint
) VB
->Win
[i
][0];
238 y
= (GLint
) VB
->Win
[i
][1];
239 z
= (GLint
) (VB
->Win
[i
][2] + ctx
->PointZoffset
);
241 red
= VB
->Color
[i
][0];
242 green
= VB
->Color
[i
][1];
243 blue
= VB
->Color
[i
][2];
244 alpha
= VB
->Color
[i
][3];
246 PB_WRITE_RGBA_PIXEL( PB
, x
, y
, z
, red
, green
, blue
, alpha
);
249 PB_CHECK_FLUSH(ctx
,PB
)
257 static void general_ci_points( GLcontext
*ctx
, GLuint first
, GLuint last
)
259 struct vertex_buffer
*VB
= ctx
->VB
;
260 struct pixel_buffer
*PB
= ctx
->PB
;
264 isize
= (GLint
) (CLAMP(ctx
->Point
.Size
,MIN_POINT_SIZE
,MAX_POINT_SIZE
) + 0.5F
);
266 for (i
=first
;i
<=last
;i
++) {
267 if (VB
->ClipMask
[i
]==0) {
269 GLint x0
, x1
, y0
, y1
;
272 x
= (GLint
) VB
->Win
[i
][0];
273 y
= (GLint
) VB
->Win
[i
][1];
274 z
= (GLint
) (VB
->Win
[i
][2] + ctx
->PointZoffset
);
285 x0
= (GLint
) (x
+ 0.5F
) - isize
/2;
287 y0
= (GLint
) (y
+ 0.5F
) - isize
/2;
291 PB_SET_INDEX( ctx
, PB
, VB
->Index
[i
] );
293 for (iy
=y0
;iy
<=y1
;iy
++) {
294 for (ix
=x0
;ix
<=x1
;ix
++) {
295 PB_WRITE_PIXEL( PB
, ix
, iy
, z
);
298 PB_CHECK_FLUSH(ctx
,PB
)
305 * General RGBA points.
307 static void general_rgba_points( GLcontext
*ctx
, GLuint first
, GLuint last
)
309 struct vertex_buffer
*VB
= ctx
->VB
;
310 struct pixel_buffer
*PB
= ctx
->PB
;
314 isize
= (GLint
) (CLAMP(ctx
->Point
.Size
,MIN_POINT_SIZE
,MAX_POINT_SIZE
) + 0.5F
);
316 for (i
=first
;i
<=last
;i
++) {
317 if (VB
->ClipMask
[i
]==0) {
319 GLint x0
, x1
, y0
, y1
;
322 x
= (GLint
) VB
->Win
[i
][0];
323 y
= (GLint
) VB
->Win
[i
][1];
324 z
= (GLint
) (VB
->Win
[i
][2] + ctx
->PointZoffset
);
335 x0
= (GLint
) (x
+ 0.5F
) - isize
/2;
337 y0
= (GLint
) (y
+ 0.5F
) - isize
/2;
341 PB_SET_COLOR( ctx
, PB
,
347 for (iy
=y0
;iy
<=y1
;iy
++) {
348 for (ix
=x0
;ix
<=x1
;ix
++) {
349 PB_WRITE_PIXEL( PB
, ix
, iy
, z
);
352 PB_CHECK_FLUSH(ctx
,PB
)
361 * Textured RGBA points.
363 static void textured_rgba_points( GLcontext
*ctx
, GLuint first
, GLuint last
)
365 struct vertex_buffer
*VB
= ctx
->VB
;
366 struct pixel_buffer
*PB
= ctx
->PB
;
369 for (i
=first
;i
<=last
;i
++) {
370 if (VB
->ClipMask
[i
]==0) {
372 GLint x0
, x1
, y0
, y1
;
375 GLint red
, green
, blue
, alpha
;
378 x
= (GLint
) VB
->Win
[i
][0];
379 y
= (GLint
) VB
->Win
[i
][1];
380 z
= (GLint
) (VB
->Win
[i
][2] + ctx
->PointZoffset
);
383 (CLAMP(ctx
->Point
.Size
,MIN_POINT_SIZE
,MAX_POINT_SIZE
) + 0.5F
);
397 x0
= (GLint
) (x
+ 0.5F
) - isize
/2;
399 y0
= (GLint
) (y
+ 0.5F
) - isize
/2;
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];
411 /* don't think this is needed
412 PB_SET_COLOR( red, green, blue, alpha );
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
);
420 PB_CHECK_FLUSH(ctx
,PB
)
428 * Antialiased points with or without texture mapping.
430 static void antialiased_rgba_points( GLcontext
*ctx
,
431 GLuint first
, GLuint last
)
433 struct vertex_buffer
*VB
= ctx
->VB
;
434 struct pixel_buffer
*PB
= ctx
->PB
;
436 GLfloat radius
, rmin
, rmax
, rmin2
, rmax2
, cscale
;
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
;
443 cscale
= 256.0F
/ (rmax2
-rmin2
);
445 if (ctx
->Texture
.Enabled
) {
446 for (i
=first
;i
<=last
;i
++) {
447 if (VB
->ClipMask
[i
]==0) {
448 GLint xmin
, ymin
, xmax
, ymax
;
450 GLint red
, green
, blue
, alpha
;
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
);
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];
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
;
472 alpha
= VB
->Color
[i
][3];
474 GLint coverage
= (GLint
) (256.0F
-(dist2
-rmin2
)*cscale
);
475 /* coverage is in [0,256] */
476 alpha
= (alpha
* coverage
) >> 8;
478 PB_WRITE_TEX_PIXEL( PB
, x
,y
,z
, red
, green
, blue
, alpha
, s
, t
, u
);
482 PB_CHECK_FLUSH(ctx
,PB
)
487 /* Not texture mapped */
488 for (i
=first
;i
<=last
;i
++) {
489 if (VB
->ClipMask
[i
]==0) {
490 GLint xmin
, ymin
, xmax
, ymax
;
492 GLint red
, green
, blue
, alpha
;
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
);
500 red
= VB
->Color
[i
][0];
501 green
= VB
->Color
[i
][1];
502 blue
= VB
->Color
[i
][2];
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
;
510 alpha
= VB
->Color
[i
][3];
512 GLint coverage
= (GLint
) (256.0F
-(dist2
-rmin2
)*cscale
);
513 /* coverage is in [0,256] */
514 alpha
= (alpha
* coverage
) >> 8;
516 PB_WRITE_RGBA_PIXEL( PB
, x
, y
, z
, red
, green
, blue
, alpha
);
520 PB_CHECK_FLUSH(ctx
,PB
)
529 * Null rasterizer for measuring transformation speed.
531 static void null_points( GLcontext
*ctx
, GLuint first
, GLuint last
)
535 /* Definition of the functions for GL_EXT_point_parameters */
538 * Examine the current context to determine which point drawing function
541 void gl_set_point_function( GLcontext
*ctx
)
543 GLboolean rgbmode
= ctx
->Visual
->RGBAflag
;
545 if (ctx
->RenderMode
==GL_RENDER
) {
547 ctx
->Driver
.PointsFunc
= null_points
;
550 if (ctx
->Driver
.PointsFunc
) {
551 /* Device driver will draw points. */
552 ctx
->Driver
.PointsFunc
= ctx
->Driver
.PointsFunc
;
555 if (ctx
->Point
.SmoothFlag
&& rgbmode
) {
556 ctx
->Driver
.PointsFunc
= antialiased_rgba_points
;
558 else if (ctx
->Texture
.Enabled
) {
559 ctx
->Driver
.PointsFunc
= textured_rgba_points
;
561 else if (ctx
->Point
.Size
==1.0) {
562 /* size=1, any raster ops */
564 ctx
->Driver
.PointsFunc
= size1_rgba_points
;
566 ctx
->Driver
.PointsFunc
= size1_ci_points
;
569 /* every other kind of point rendering */
571 ctx
->Driver
.PointsFunc
= general_rgba_points
;
573 ctx
->Driver
.PointsFunc
= general_ci_points
;
577 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
578 ctx
->Driver
.PointsFunc
= feedback_points
;
582 ctx
->Driver
.PointsFunc
= select_points
;