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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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