1 /* $Id: misc.c,v 1.23 1997/12/06 18:07:13 brianp Exp $ */ 2 3 /* 4 * Mesa 3-D graphics library 5 * Version: 2.6 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: misc.c,v $ 26 * Revision 1.23 1997/12/06 18:07:13 brianp 27 * changed version to 2.6 28 * 29 * Revision 1.22 1997/12/05 04:38:55 brianp 30 * added ClearColorAndDepth() function pointer (David Bucciarelli) 31 * 32 * Revision 1.21 1997/10/29 01:29:09 brianp 33 * added GL_EXT_point_parameters extension from Daniel Barrero 34 * 35 * Revision 1.20 1997/10/16 02:32:19 brianp 36 * added GL_EXT_shared_texture_palette extension 37 * 38 * Revision 1.19 1997/10/14 00:17:48 brianp 39 * added 3DFX_set_global_palette to extension string for 3Dfx 40 * 41 * Revision 1.18 1997/09/27 00:13:44 brianp 42 * added GL_EXT_paletted_texture extension 43 * 44 * Revision 1.17 1997/08/13 01:26:40 brianp 45 * changed version string to 2.4 46 * 47 * Revision 1.16 1997/07/24 01:23:16 brianp 48 * changed precompiled header symbol from PCH to PC_HEADER 49 * 50 * Revision 1.15 1997/06/20 02:21:36 brianp 51 * don't clear buffers if RenderMode != GL_RENDER 52 * 53 * Revision 1.14 1997/05/28 03:25:43 brianp 54 * added precompiled header (PCH) support 55 * 56 * Revision 1.13 1997/04/12 12:31:18 brianp 57 * removed gl_Rectf() 58 * 59 * Revision 1.12 1997/03/21 01:58:54 brianp 60 * now call Driver.RendererString() in gl_GetString() 61 * 62 * Revision 1.11 1997/02/10 20:40:51 brianp 63 * added GL_MESA_resize_buffers to extensions string 64 * 65 * Revision 1.10 1997/02/09 18:44:35 brianp 66 * added GL_EXT_texture3D support 67 * 68 * Revision 1.9 1997/01/08 20:55:02 brianp 69 * added GL_EXT_texture_object 70 * 71 * Revision 1.8 1996/11/05 01:41:45 brianp 72 * fixed potential scissor/clear color buffer bug 73 * 74 * Revision 1.7 1996/10/30 03:14:02 brianp 75 * incremented version to 2.1 76 * 77 * Revision 1.6 1996/10/11 03:42:17 brianp 78 * added GL_EXT_polygon_offset to extensions string 79 * 80 * Revision 1.5 1996/10/02 02:51:44 brianp 81 * created clear_color_buffers() which handles draw mode GL_FRONT_AND_BACK 82 * 83 * Revision 1.4 1996/09/25 03:22:14 brianp 84 * glDrawBuffer(GL_NONE) works now 85 * 86 * Revision 1.3 1996/09/24 00:16:10 brianp 87 * set NewState flag in glRead/DrawBuffer() and glHint() 88 * fixed display list bug in gl_Hint() 89 * 90 * Revision 1.2 1996/09/15 14:18:37 brianp 91 * now use GLframebuffer and GLvisual 92 * 93 * Revision 1.1 1996/09/13 01:38:16 brianp 94 * Initial revision 95 * 96 */ 97 98 99 #ifdef PC_HEADER 100 #include "all.h" 101 #else 102 #include <stdlib.h> 103 #include <string.h> 104 #include "accum.h" 105 #include "alphabuf.h" 106 #include "context.h" 107 #include "depth.h" 108 #include "macros.h" 109 #include "masking.h" 110 #include "misc.h" 111 #include "stencil.h" 112 #include "types.h" 113 #endif 114 115 116 117 void gl_ClearIndex( GLcontext *ctx, GLfloat c ) 118 { 119 if (INSIDE_BEGIN_END(ctx)) { 120 gl_error( ctx, GL_INVALID_OPERATION, "glClearIndex" ); 121 return; 122 } 123 ctx->Color.ClearIndex = (GLuint) c; 124 if (!ctx->Visual->RGBAflag) { 125 /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */ 126 (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex ); 127 } 128 } 129 130 131 132 void gl_ClearColor( GLcontext *ctx, GLclampf red, GLclampf green, 133 GLclampf blue, GLclampf alpha ) 134 { 135 if (INSIDE_BEGIN_END(ctx)) { 136 gl_error( ctx, GL_INVALID_OPERATION, "glClearColor" ); 137 return; 138 } 139 140 ctx->Color.ClearColor[0] = CLAMP( red, 0.0F, 1.0F ); 141 ctx->Color.ClearColor[1] = CLAMP( green, 0.0F, 1.0F ); 142 ctx->Color.ClearColor[2] = CLAMP( blue, 0.0F, 1.0F ); 143 ctx->Color.ClearColor[3] = CLAMP( alpha, 0.0F, 1.0F ); 144 145 if (ctx->Visual->RGBAflag) { 146 GLubyte r = (GLint) (ctx->Color.ClearColor[0] * ctx->Visual->RedScale); 147 GLubyte g = (GLint) (ctx->Color.ClearColor[1] * ctx->Visual->GreenScale); 148 GLubyte b = (GLint) (ctx->Color.ClearColor[2] * ctx->Visual->BlueScale); 149 GLubyte a = (GLint) (ctx->Color.ClearColor[3] * ctx->Visual->AlphaScale); 150 (*ctx->Driver.ClearColor)( ctx, r, g, b, a ); 151 } 152 } 153 154 155 156 157 /* 158 * Clear the color buffer when glColorMask or glIndexMask is in effect. 159 */ 160 static void clear_color_buffer_with_masking( GLcontext *ctx ) 161 { 162 GLint x, y, height, width; 163 164 /* Compute region to clear */ 165 if (ctx->Scissor.Enabled) { 166 x = ctx->Buffer->Xmin; 167 y = ctx->Buffer->Ymin; 168 height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1; 169 width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1; 170 } 171 else { 172 x = 0; 173 y = 0; 174 height = ctx->Buffer->Height; 175 width = ctx->Buffer->Width; 176 } 177 178 if (ctx->Visual->RGBAflag) { 179 /* RGBA mode */ 180 GLubyte red[MAX_WIDTH], green[MAX_WIDTH]; 181 GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH]; 182 GLubyte r = ctx->Color.ClearColor[0] * ctx->Visual->RedScale; 183 GLubyte g = ctx->Color.ClearColor[1] * ctx->Visual->GreenScale; 184 GLubyte b = ctx->Color.ClearColor[2] * ctx->Visual->BlueScale; 185 GLubyte a = ctx->Color.ClearColor[3] * ctx->Visual->AlphaScale; 186 GLint i; 187 for (i=0;i<height;i++,y++) { 188 MEMSET( red, (int) r, width ); 189 MEMSET( green, (int) g, width ); 190 MEMSET( blue, (int) b, width ); 191 MEMSET( alpha, (int) a, width ); 192 gl_mask_color_span( ctx, width, x, y, red, green, blue, alpha ); 193 (*ctx->Driver.WriteColorSpan)( ctx, 194 width, x, y, red, green, blue, alpha, NULL ); 195 if (ctx->RasterMask & ALPHABUF_BIT) { 196 gl_write_alpha_span( ctx, width, x, y, alpha, NULL ); 197 } 198 } 199 } 200 else { 201 /* Color index mode */ 202 GLuint indx[MAX_WIDTH]; 203 GLubyte mask[MAX_WIDTH]; 204 GLint i, j; 205 MEMSET( mask, 1, width ); 206 for (i=0;i<height;i++,y++) { 207 for (j=0;j<width;j++) { 208 indx[j] = ctx->Color.ClearIndex; 209 } 210 gl_mask_index_span( ctx, width, x, y, indx ); 211 (*ctx->Driver.WriteIndexSpan)( ctx, width, x, y, indx, mask ); 212 } 213 } 214 } 215 216 217 218 /* 219 * Clear the front and/or back color buffers. Also clear the alpha 220 * buffer(s) if present. 221 */ 222 static void clear_color_buffers( GLcontext *ctx ) 223 { 224 if (ctx->Color.SWmasking) { 225 clear_color_buffer_with_masking( ctx ); 226 } 227 else { 228 GLint x = ctx->Buffer->Xmin; 229 GLint y = ctx->Buffer->Ymin; 230 GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1; 231 GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1; 232 (*ctx->Driver.Clear)( ctx, !ctx->Scissor.Enabled, 233 x, y, width, height ); 234 if (ctx->RasterMask & ALPHABUF_BIT) { 235 /* front and/or back alpha buffers will be cleared here */ 236 gl_clear_alpha_buffers( ctx ); 237 } 238 } 239 240 if (ctx->RasterMask & FRONT_AND_BACK_BIT) { 241 /*** Also clear the back buffer ***/ 242 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 243 if (ctx->Color.SWmasking) { 244 clear_color_buffer_with_masking( ctx ); 245 } 246 else { 247 GLint x = ctx->Buffer->Xmin; 248 GLint y = ctx->Buffer->Ymin; 249 GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1; 250 GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1; 251 (*ctx->Driver.Clear)( ctx, !ctx->Scissor.Enabled, 252 x, y, width, height ); 253 } 254 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 255 } 256 } 257 258 259 260 void gl_Clear( GLcontext *ctx, GLbitfield mask ) 261 { 262 #ifdef PROFILE 263 GLdouble t0 = gl_time(); 264 #endif 265 266 if (INSIDE_BEGIN_END(ctx)) { 267 gl_error( ctx, GL_INVALID_OPERATION, "glClear" ); 268 return; 269 } 270 271 if (ctx->RenderMode==GL_RENDER) { 272 if (ctx->NewState) { 273 gl_update_state( ctx ); 274 } 275 276 /* See if we can call device driver function to clear both the 277 * color and depth buffers. 278 */ 279 if (ctx->Driver.ClearColorAndDepth && 280 (mask & GL_COLOR_BUFFER_BIT) && (mask & GL_DEPTH_BUFFER_BIT)) { 281 GLint x = ctx->Buffer->Xmin; 282 GLint y = ctx->Buffer->Ymin; 283 GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1; 284 GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1; 285 (*ctx->Driver.ClearColorAndDepth)( ctx, !ctx->Scissor.Enabled, 286 x, y, width, height ); 287 if (ctx->RasterMask & FRONT_AND_BACK_BIT) { 288 /*** Also clear the back buffer ***/ 289 (*ctx->Driver.SetBuffer)( ctx, GL_BACK ); 290 (*ctx->Driver.ClearColorAndDepth)( ctx, !ctx->Scissor.Enabled, 291 x, y, width, height ); 292 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ); 293 } 294 } 295 else { 296 /* normal procedure for clearing buffers */ 297 if (mask & GL_COLOR_BUFFER_BIT) clear_color_buffers( ctx ); 298 if (mask & GL_DEPTH_BUFFER_BIT) (*ctx->Driver.ClearDepthBuffer)(ctx); 299 if (mask & GL_ACCUM_BUFFER_BIT) gl_clear_accum_buffer( ctx ); 300 if (mask & GL_STENCIL_BUFFER_BIT) gl_clear_stencil_buffer( ctx ); 301 } 302 303 #ifdef PROFILE 304 ctx->ClearTime += gl_time() - t0; 305 ctx->ClearCount++; 306 #endif 307 } 308 } 309 310 311 312 const GLubyte *gl_GetString( GLcontext *ctx, GLenum name ) 313 { 314 static char renderer[1000]; 315 static char *vendor = "Brian Paul & ReactOS Developers"; 316 static char *version = "1.1"; 317 static char *extensions = "GL_EXT_paletted_texture GL_EXT_bgra GL_WIN_swap_hint"; 318 319 if (INSIDE_BEGIN_END(ctx)) { 320 gl_error( ctx, GL_INVALID_OPERATION, "glGetString" ); 321 return (GLubyte *) 0; 322 } 323 324 switch (name) { 325 case GL_VENDOR: 326 return (GLubyte *) vendor; 327 case GL_RENDERER: 328 strcpy(renderer, "Mesa"); 329 if (ctx->Driver.RendererString) { 330 strcat(renderer, " "); 331 strcat(renderer, (*ctx->Driver.RendererString)()); 332 } 333 return (GLubyte *) renderer; 334 case GL_VERSION: 335 return (GLubyte *) version; 336 case GL_EXTENSIONS: 337 return (GLubyte *) extensions; 338 default: 339 gl_error( ctx, GL_INVALID_ENUM, "glGetString" ); 340 return (GLubyte *) 0; 341 } 342 } 343 344 345 346 void gl_Finish( GLcontext *ctx ) 347 { 348 /* Don't compile into display list */ 349 if (INSIDE_BEGIN_END(ctx)) { 350 gl_error( ctx, GL_INVALID_OPERATION, "glFinish" ); 351 return; 352 } 353 if (ctx->Driver.Finish) { 354 (*ctx->Driver.Finish)( ctx ); 355 } 356 } 357 358 359 360 void gl_Flush( GLcontext *ctx ) 361 { 362 /* Don't compile into display list */ 363 if (INSIDE_BEGIN_END(ctx)) { 364 gl_error( ctx, GL_INVALID_OPERATION, "glFlush" ); 365 return; 366 } 367 if (ctx->Driver.Flush) { 368 (*ctx->Driver.Flush)( ctx ); 369 } 370 } 371 372 373 374 void gl_Hint( GLcontext *ctx, GLenum target, GLenum mode ) 375 { 376 if (INSIDE_BEGIN_END(ctx)) { 377 gl_error( ctx, GL_INVALID_OPERATION, "glHint" ); 378 return; 379 } 380 if (mode!=GL_DONT_CARE && mode!=GL_FASTEST && mode!=GL_NICEST) { 381 gl_error( ctx, GL_INVALID_ENUM, "glHint(mode)" ); 382 return; 383 } 384 switch (target) { 385 case GL_FOG_HINT: 386 ctx->Hint.Fog = mode; 387 break; 388 case GL_LINE_SMOOTH_HINT: 389 ctx->Hint.LineSmooth = mode; 390 break; 391 case GL_PERSPECTIVE_CORRECTION_HINT: 392 ctx->Hint.PerspectiveCorrection = mode; 393 break; 394 case GL_POINT_SMOOTH_HINT: 395 ctx->Hint.PointSmooth = mode; 396 break; 397 case GL_POLYGON_SMOOTH_HINT: 398 ctx->Hint.PolygonSmooth = mode; 399 break; 400 default: 401 gl_error( ctx, GL_INVALID_ENUM, "glHint(target)" ); 402 } 403 ctx->NewState |= NEW_ALL; /* just to be safe */ 404 } 405 406 407 408 void gl_DrawBuffer( GLcontext *ctx, GLenum mode ) 409 { 410 if (INSIDE_BEGIN_END(ctx)) { 411 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 412 return; 413 } 414 switch (mode) { 415 case GL_FRONT: 416 case GL_FRONT_LEFT: 417 case GL_FRONT_AND_BACK: 418 if ( (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ) == GL_FALSE ) { 419 gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" ); 420 return; 421 } 422 ctx->Color.DrawBuffer = mode; 423 ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha; 424 ctx->NewState |= NEW_RASTER_OPS; 425 break; 426 case GL_BACK: 427 case GL_BACK_LEFT: 428 if ( (*ctx->Driver.SetBuffer)( ctx, GL_BACK ) == GL_FALSE) { 429 gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" ); 430 return; 431 } 432 ctx->Color.DrawBuffer = mode; 433 ctx->Buffer->Alpha = ctx->Buffer->BackAlpha; 434 ctx->NewState |= NEW_RASTER_OPS; 435 break; 436 case GL_NONE: 437 ctx->Color.DrawBuffer = mode; 438 ctx->Buffer->Alpha = NULL; 439 ctx->NewState |= NEW_RASTER_OPS; 440 break; 441 case GL_FRONT_RIGHT: 442 case GL_BACK_RIGHT: 443 case GL_LEFT: 444 case GL_RIGHT: 445 case GL_AUX0: 446 gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" ); 447 break; 448 default: 449 gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" ); 450 } 451 } 452 453 454 455 void gl_ReadBuffer( GLcontext *ctx, GLenum mode ) 456 { 457 if (INSIDE_BEGIN_END(ctx)) { 458 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" ); 459 return; 460 } 461 switch (mode) { 462 case GL_FRONT: 463 case GL_FRONT_LEFT: 464 if ( (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ) == GL_FALSE) { 465 gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" ); 466 return; 467 } 468 ctx->Pixel.ReadBuffer = mode; 469 ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha; 470 ctx->NewState |= NEW_RASTER_OPS; 471 break; 472 case GL_BACK: 473 case GL_BACK_LEFT: 474 if ( (*ctx->Driver.SetBuffer)( ctx, GL_BACK ) == GL_FALSE) { 475 gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" ); 476 return; 477 } 478 ctx->Pixel.ReadBuffer = mode; 479 ctx->Buffer->Alpha = ctx->Buffer->BackAlpha; 480 ctx->NewState |= NEW_RASTER_OPS; 481 break; 482 case GL_FRONT_RIGHT: 483 case GL_BACK_RIGHT: 484 case GL_LEFT: 485 case GL_RIGHT: 486 case GL_AUX0: 487 gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" ); 488 break; 489 default: 490 gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" ); 491 } 492 493 /* Remember, the draw buffer is the default state */ 494 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer ); 495 } 496