xm_api.c revision 367d308b8267ad86cd7623590b7bfd4737b5fbf5
1/* $Id: xm_api.c,v 1.47 2002/10/25 21:06:34 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 4.0.2 6 * 7 * Copyright (C) 1999-2002 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/* $XFree86: xc/extras/Mesa/src/X/xm_api.c,v 1.2 2002/02/26 23:37:31 tsi Exp $ */ 27 28/* 29 * This file contains the implementations of all the XMesa* functions. 30 * 31 * 32 * NOTES: 33 * 34 * The window coordinate system origin (0,0) is in the lower-left corner 35 * of the window. X11's window coordinate origin is in the upper-left 36 * corner of the window. Therefore, most drawing functions in this 37 * file have to flip Y coordinates. 38 * 39 * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile 40 * in support for the MIT Shared Memory extension. If enabled, when you 41 * use an Ximage for the back buffer in double buffered mode, the "swap" 42 * operation will be faster. You must also link with -lXext. 43 * 44 * Byte swapping: If the Mesa host and the X display use a different 45 * byte order then there's some trickiness to be aware of when using 46 * XImages. The byte ordering used for the XImage is that of the X 47 * display, not the Mesa host. 48 * The color-to-pixel encoding for True/DirectColor must be done 49 * according to the display's visual red_mask, green_mask, and blue_mask. 50 * If XPutPixel is used to put a pixel into an XImage then XPutPixel will 51 * do byte swapping if needed. If one wants to directly "poke" the pixel 52 * into the XImage's buffer then the pixel must be byte swapped first. In 53 * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format 54 * and use XPutPixel everywhere except in the implementation of 55 * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so 56 * instead of using XPutPixel we "poke" our values after byte-swapping 57 * the clear pixel value if needed. 58 * 59 */ 60 61#ifdef __CYGWIN__ 62#undef WIN32 63#undef __WIN32__ 64#endif 65 66#include "glxheader.h" 67#include "GL/xmesa.h" 68#include "xmesaP.h" 69#include "context.h" 70#include "extensions.h" 71#include "glthread.h" 72#include "imports.h" 73#include "matrix.h" 74#include "mmath.h" 75#include "mtypes.h" 76#include "macros.h" 77#include "texformat.h" 78#include "texstore.h" 79#include "swrast/swrast.h" 80#include "swrast_setup/swrast_setup.h" 81#include "array_cache/acache.h" 82#include "tnl/tnl.h" 83 84#ifndef GLX_NONE_EXT 85#define GLX_NONE_EXT 0x8000 86#endif 87 88 89/* 90 * Global X driver lock 91 */ 92_glthread_Mutex _xmesa_lock; 93 94 95 96/* 97 * Lookup tables for HPCR pixel format: 98 */ 99static short hpcr_rgbTbl[3][256] = { 100{ 101 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 102 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 103 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 104 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 105 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 106 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 107 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 108 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 109112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 110128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 111144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 112160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 113176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 114192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 115208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 116224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239 117}, 118{ 119 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 120 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 121 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 122 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 123 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 124 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 125 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 126 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 127112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 129144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 130160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 131176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 132192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 133208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 134224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239 135}, 136{ 137 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 138 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 139 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 140 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 141 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 142 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 143 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, 144 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 145 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 146112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 147128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 148144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 149160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 150176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 151192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 152208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223 153} 154}; 155 156 157 158/**********************************************************************/ 159/***** X Utility Functions *****/ 160/**********************************************************************/ 161 162 163/* 164 * X/Mesa error reporting function: 165 */ 166static void error( const char *msg ) 167{ 168 (void)DitherValues; /* Muffle compiler */ 169 170 if (_mesa_getenv("MESA_DEBUG")) 171 fprintf( stderr, "X/Mesa error: %s\n", msg ); 172} 173 174 175/* 176 * Return the host's byte order as LSBFirst or MSBFirst ala X. 177 */ 178#ifndef XFree86Server 179static int host_byte_order( void ) 180{ 181 int i = 1; 182 char *cptr = (char *) &i; 183 return (*cptr==1) ? LSBFirst : MSBFirst; 184} 185#endif 186 187 188/* 189 * Error handling. 190 */ 191#ifndef XFree86Server 192static int mesaXErrorFlag = 0; 193 194static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event ) 195{ 196 (void) dpy; 197 (void) event; 198 mesaXErrorFlag = 1; 199 return 0; 200} 201#endif 202 203 204/* 205 * Check if the X Shared Memory extension is available. 206 * Return: 0 = not available 207 * 1 = shared XImage support available 208 * 2 = shared Pixmap support available also 209 */ 210#ifndef XFree86Server 211static int check_for_xshm( XMesaDisplay *display ) 212{ 213#ifdef USE_XSHM 214 int major, minor, ignore; 215 Bool pixmaps; 216 217 if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { 218 if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { 219 return (pixmaps==True) ? 2 : 1; 220 } 221 else { 222 return 0; 223 } 224 } 225 else { 226 return 0; 227 } 228#else 229 /* Can't compile XSHM support */ 230 return 0; 231#endif 232} 233#endif 234 235 236/* 237 * Return the width and height of the given drawable. 238 */ 239static void get_drawable_size( XMesaDisplay *dpy, XMesaDrawable d, 240 unsigned int *width, unsigned int *height) 241{ 242#ifdef XFree86Server 243 (void) dpy; 244 *width = d->width; 245 *height = d->height; 246#else 247 Window root; 248 int x, y; 249 unsigned int bw, depth; 250 251 _glthread_LOCK_MUTEX(_xmesa_lock); 252 XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth ); 253 _glthread_UNLOCK_MUTEX(_xmesa_lock); 254#endif 255} 256 257 258/* 259 * Apply gamma correction to an intensity value in [0..max]. Return the 260 * new intensity value. 261 */ 262static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max ) 263{ 264 if (gamma == 1.0) { 265 return value; 266 } 267 else { 268 double x = (double) value / (double) max; 269 return IROUND_POS((GLfloat) max * _mesa_pow(x, 1.0F/gamma)); 270 } 271} 272 273 274 275/* 276 * Return the true number of bits per pixel for XImages. 277 * For example, if we request a 24-bit deep visual we may actually need/get 278 * 32bpp XImages. This function returns the appropriate bpp. 279 * Input: dpy - the X display 280 * visinfo - desribes the visual to be used for XImages 281 * Return: true number of bits per pixel for XImages 282 */ 283#ifdef XFree86Server 284 285static int bits_per_pixel( XMesaVisual xmv ) 286{ 287 XMesaVisualInfo visinfo = xmv->visinfo; 288 const int depth = visinfo->nplanes; 289 int i; 290 for (i = 0; i < screenInfo.numPixmapFormats; i++) { 291 if (screenInfo.formats[i].depth == depth) 292 return screenInfo.formats[i].bitsPerPixel; 293 } 294 return depth; /* should never get here, but this should be safe */ 295} 296 297#else 298 299static int bits_per_pixel( XMesaVisual xmv ) 300{ 301 XMesaDisplay *dpy = xmv->display; 302 XMesaVisualInfo visinfo = xmv->visinfo; 303 XMesaImage *img; 304 int bitsPerPixel; 305 /* Create a temporary XImage */ 306 img = XCreateImage( dpy, visinfo->visual, visinfo->depth, 307 ZPixmap, 0, /*format, offset*/ 308 (char*) MALLOC(8), /*data*/ 309 1, 1, /*width, height*/ 310 32, /*bitmap_pad*/ 311 0 /*bytes_per_line*/ 312 ); 313 assert(img); 314 /* grab the bits/pixel value */ 315 bitsPerPixel = img->bits_per_pixel; 316 /* free the XImage */ 317 FREE( img->data ); 318 img->data = NULL; 319 XMesaDestroyImage( img ); 320 return bitsPerPixel; 321} 322#endif 323 324 325 326/* 327 * Determine if a given X window ID is valid (window exists). 328 * Do this by calling XGetWindowAttributes() for the window and 329 * checking if we catch an X error. 330 * Input: dpy - the display 331 * win - the window to check for existance 332 * Return: GL_TRUE - window exists 333 * GL_FALSE - window doesn't exist 334 */ 335#ifndef XFree86Server 336static GLboolean WindowExistsFlag; 337 338static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr ) 339{ 340 (void) dpy; 341 if (xerr->error_code == BadWindow) { 342 WindowExistsFlag = GL_FALSE; 343 } 344 return 0; 345} 346 347static GLboolean window_exists( XMesaDisplay *dpy, Window win ) 348{ 349 XWindowAttributes wa; 350 int (*old_handler)( XMesaDisplay*, XErrorEvent* ); 351 WindowExistsFlag = GL_TRUE; 352 old_handler = XSetErrorHandler(window_exists_err_handler); 353 XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ 354 XSetErrorHandler(old_handler); 355 return WindowExistsFlag; 356} 357#endif 358 359 360 361/**********************************************************************/ 362/***** Linked list of XMesaBuffers *****/ 363/**********************************************************************/ 364 365static XMesaBuffer XMesaBufferList = NULL; 366 367 368/* Allocate a new XMesaBuffer, add to linked list */ 369static XMesaBuffer alloc_xmesa_buffer(void) 370{ 371 XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); 372 if (b) { 373 b->Next = XMesaBufferList; 374 XMesaBufferList = b; 375 } 376 return b; 377} 378 379 380/* 381 * Find an XMesaBuffer by matching X display and colormap but NOT matching 382 * the notThis buffer. 383 */ 384static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy, 385 XMesaColormap cmap, 386 XMesaBuffer notThis) 387{ 388 XMesaBuffer b; 389 for (b=XMesaBufferList; b; b=b->Next) { 390 if (b->display==dpy && b->cmap==cmap && b!=notThis) { 391 return b; 392 } 393 } 394 return NULL; 395} 396 397 398/* 399 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap 400 * entries. 401 */ 402static void free_xmesa_buffer(int client, XMesaBuffer buffer) 403{ 404 XMesaBuffer prev = NULL, b; 405 (void) client; 406 for (b=XMesaBufferList; b; b=b->Next) { 407 if (b==buffer) { 408 /* unlink bufer from list */ 409 if (prev) 410 prev->Next = buffer->Next; 411 else 412 XMesaBufferList = buffer->Next; 413 /* Check to free X colors */ 414 if (buffer->num_alloced>0) { 415 /* If no other buffer uses this X colormap then free the colors. */ 416 if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) { 417#ifdef XFree86Server 418 (void)FreeColors(buffer->cmap, client, 419 buffer->num_alloced, buffer->alloced_colors, 420 0); 421#else 422 XFreeColors(buffer->display, buffer->cmap, 423 buffer->alloced_colors, buffer->num_alloced, 0); 424#endif 425 } 426 } 427 428 _mesa_free_framebuffer_data(&buffer->mesa_buffer); 429 FREE(buffer); 430 431 return; 432 } 433 /* continue search */ 434 prev = b; 435 } 436 /* buffer not found in XMesaBufferList */ 437 _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n"); 438} 439 440 441/* Copy X color table stuff from one XMesaBuffer to another. */ 442static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src) 443{ 444 MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table)); 445 MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r)); 446 MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g)); 447 MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b)); 448 dst->num_alloced = src->num_alloced; 449 MEMCPY(dst->alloced_colors, src->alloced_colors, 450 sizeof(src->alloced_colors)); 451} 452 453 454 455/**********************************************************************/ 456/***** Misc Private Functions *****/ 457/**********************************************************************/ 458 459 460/* 461 * Return number of bits set in n. 462 */ 463static int bitcount( unsigned long n ) 464{ 465 int bits; 466 for (bits=0; n>0; n=n>>1) { 467 if (n&1) { 468 bits++; 469 } 470 } 471 return bits; 472} 473 474 475 476/* 477 * Allocate a shared memory XImage back buffer for the given XMesaBuffer. 478 * Return: GL_TRUE if success, GL_FALSE if error 479 */ 480#ifndef XFree86Server 481static GLboolean alloc_shm_back_buffer( XMesaBuffer b ) 482{ 483#ifdef USE_XSHM 484 /* 485 * We have to do a _lot_ of error checking here to be sure we can 486 * really use the XSHM extension. It seems different servers trigger 487 * errors at different points if the extension won't work. Therefore 488 * we have to be very careful... 489 */ 490 GC gc; 491 int (*old_handler)( XMesaDisplay *, XErrorEvent * ); 492 493 b->backimage = XShmCreateImage( b->xm_visual->display, 494 b->xm_visual->visinfo->visual, 495 b->xm_visual->visinfo->depth, 496 ZPixmap, NULL, &b->shminfo, 497 b->width, b->height ); 498 if (b->backimage == NULL) { 499 error("alloc_back_buffer: Shared memory error (XShmCreateImage), disabling."); 500 b->shm = 0; 501 return GL_FALSE; 502 } 503 504 b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line 505 * b->backimage->height, IPC_CREAT|0777 ); 506 if (b->shminfo.shmid < 0) { 507 if (_mesa_getenv("MESA_DEBUG")) 508 perror("alloc_back_buffer"); 509 XDestroyImage( b->backimage ); 510 b->backimage = NULL; 511 error("alloc_back_buffer: Shared memory error (shmget), disabling."); 512 b->shm = 0; 513 return GL_FALSE; 514 } 515 516 b->shminfo.shmaddr = b->backimage->data 517 = (char*)shmat( b->shminfo.shmid, 0, 0 ); 518 if (b->shminfo.shmaddr == (char *) -1) { 519 if (_mesa_getenv("MESA_DEBUG")) 520 perror("alloc_back_buffer"); 521 XDestroyImage( b->backimage ); 522 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); 523 b->backimage = NULL; 524 error("alloc_back_buffer: Shared memory error (shmat), disabling."); 525 b->shm = 0; 526 return GL_FALSE; 527 } 528 529 b->shminfo.readOnly = False; 530 mesaXErrorFlag = 0; 531 old_handler = XSetErrorHandler( mesaHandleXError ); 532 /* This may trigger the X protocol error we're ready to catch: */ 533 XShmAttach( b->xm_visual->display, &b->shminfo ); 534 XSync( b->xm_visual->display, False ); 535 536 if (mesaXErrorFlag) { 537 /* we are on a remote display, this error is normal, don't print it */ 538 XFlush( b->xm_visual->display ); 539 mesaXErrorFlag = 0; 540 XDestroyImage( b->backimage ); 541 shmdt( b->shminfo.shmaddr ); 542 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); 543 b->backimage = NULL; 544 b->shm = 0; 545 (void) XSetErrorHandler( old_handler ); 546 return GL_FALSE; 547 } 548 549 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */ 550 551 /* Finally, try an XShmPutImage to be really sure the extension works */ 552 gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL ); 553 XShmPutImage( b->xm_visual->display, b->frontbuffer, gc, 554 b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False ); 555 XSync( b->xm_visual->display, False ); 556 XFreeGC( b->xm_visual->display, gc ); 557 (void) XSetErrorHandler( old_handler ); 558 if (mesaXErrorFlag) { 559 XFlush( b->xm_visual->display ); 560 mesaXErrorFlag = 0; 561 XDestroyImage( b->backimage ); 562 shmdt( b->shminfo.shmaddr ); 563 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); 564 b->backimage = NULL; 565 b->shm = 0; 566 return GL_FALSE; 567 } 568 569 if (b->backimage) { 570 int height = b->backimage->height; 571 /* Needed by PIXELADDR1 macro */ 572 b->ximage_width1 = b->backimage->bytes_per_line; 573 b->ximage_origin1 = (GLubyte *) b->backimage->data 574 + b->ximage_width1 * (height-1); 575 /* Needed by PIXELADDR2 macro */ 576 b->ximage_width2 = b->backimage->bytes_per_line / 2; 577 b->ximage_origin2 = (GLushort *) b->backimage->data 578 + b->ximage_width2 * (height-1); 579 /* Needed by PIXELADDR3 macro */ 580 b->ximage_width3 = b->backimage->bytes_per_line; 581 b->ximage_origin3 = (GLubyte *) b->backimage->data 582 + b->ximage_width3 * (height-1); 583 /* Needed by PIXELADDR4 macro */ 584 b->ximage_width4 = b->backimage->width; 585 b->ximage_origin4 = (GLuint *) b->backimage->data 586 + b->ximage_width4 * (height-1); 587 } 588 589 return GL_TRUE; 590#else 591 /* Can't compile XSHM support */ 592 return GL_FALSE; 593#endif 594} 595#endif 596 597 598 599/* 600 * Setup an off-screen pixmap or Ximage to use as the back buffer. 601 * Input: b - the X/Mesa buffer 602 */ 603void xmesa_alloc_back_buffer( XMesaBuffer b ) 604{ 605 if (b->db_state==BACK_XIMAGE) { 606 /* Deallocate the old backimage, if any */ 607 if (b->backimage) { 608#if defined(USE_XSHM) && !defined(XFree86Server) 609 if (b->shm) { 610 XShmDetach( b->xm_visual->display, &b->shminfo ); 611 XDestroyImage( b->backimage ); 612 shmdt( b->shminfo.shmaddr ); 613 } 614 else 615#endif 616 XMesaDestroyImage( b->backimage ); 617 b->backimage = NULL; 618 } 619 620 /* Allocate new back buffer */ 621#ifdef XFree86Server 622 { 623 /* Allocate a regular XImage for the back buffer. */ 624 b->backimage = XMesaCreateImage(b->xm_visual->BitsPerPixel, 625 b->width, b->height, NULL); 626#else 627 if (b->shm==0 || alloc_shm_back_buffer(b)==GL_FALSE) { 628 /* Allocate a regular XImage for the back buffer. */ 629 b->backimage = XCreateImage( b->xm_visual->display, 630 b->xm_visual->visinfo->visual, 631 GET_VISUAL_DEPTH(b->xm_visual), 632 ZPixmap, 0, /* format, offset */ 633 NULL, b->width, b->height, 634 8, 0 ); /* pad, bytes_per_line */ 635#endif 636 if (!b->backimage) { 637 error("alloc_back_buffer: XCreateImage failed."); 638 } 639 b->backimage->data = (char *) MALLOC( b->backimage->height 640 * b->backimage->bytes_per_line ); 641 if (!b->backimage->data) { 642 error("alloc_back_buffer: MALLOC failed."); 643 XMesaDestroyImage( b->backimage ); 644 b->backimage = NULL; 645 } 646 } 647 b->backpixmap = None; 648 } 649 else if (b->db_state==BACK_PIXMAP) { 650 XMesaPixmap old_pixmap = b->backpixmap; 651 /* Free the old back pixmap */ 652 if (b->backpixmap) { 653 XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); 654 } 655 /* Allocate new back pixmap */ 656 b->backpixmap = XMesaCreatePixmap( b->xm_visual->display, b->frontbuffer, 657 b->width, b->height, 658 GET_VISUAL_DEPTH(b->xm_visual) ); 659 b->backimage = NULL; 660 /* update other references to backpixmap */ 661 if (b->buffer==(XMesaDrawable)old_pixmap) { 662 b->buffer = (XMesaDrawable)b->backpixmap; 663 } 664 } 665} 666 667 668 669/* 670 * A replacement for XAllocColor. This function should never 671 * fail to allocate a color. When XAllocColor fails, we return 672 * the nearest matching color. If we have to allocate many colors 673 * this function isn't too efficient; the XQueryColors() could be 674 * done just once. 675 * Written by Michael Pichler, Brian Paul, Mark Kilgard 676 * Input: dpy - X display 677 * cmap - X colormap 678 * cmapSize - size of colormap 679 * In/Out: color - the XColor struct 680 * Output: exact - 1=exact color match, 0=closest match 681 * alloced - 1=XAlloc worked, 0=XAlloc failed 682 */ 683static void 684noFaultXAllocColor( int client, 685 XMesaDisplay *dpy, 686 XMesaColormap cmap, 687 int cmapSize, 688 XMesaColor *color, 689 int *exact, int *alloced ) 690{ 691#ifdef XFree86Server 692 Pixel *ppixIn; 693 xrgb *ctable; 694#else 695 /* we'll try to cache ctable for better remote display performance */ 696 static Display *prevDisplay = NULL; 697 static XMesaColormap prevCmap = 0; 698 static int prevCmapSize = 0; 699 static XMesaColor *ctable = NULL; 700#endif 701 XMesaColor subColor; 702 int i, bestmatch; 703 double mindist; /* 3*2^16^2 exceeds long int precision. */ 704 705 (void) client; 706 707 /* First try just using XAllocColor. */ 708#ifdef XFree86Server 709 if (AllocColor(cmap, 710 &color->red, &color->green, &color->blue, 711 &color->pixel, 712 client) == Success) { 713#else 714 if (XAllocColor(dpy, cmap, color)) { 715#endif 716 *exact = 1; 717 *alloced = 1; 718 return; 719 } 720 721 /* Alloc failed, search for closest match */ 722 723 /* Retrieve color table entries. */ 724 /* XXX alloca candidate. */ 725#ifdef XFree86Server 726 ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel)); 727 ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb)); 728 for (i = 0; i < cmapSize; i++) { 729 ppixIn[i] = i; 730 } 731 QueryColors(cmap, cmapSize, ppixIn, ctable); 732#else 733 if (prevDisplay != dpy || prevCmap != cmap 734 || prevCmapSize != cmapSize || !ctable) { 735 /* free previously cached color table */ 736 if (ctable) 737 FREE(ctable); 738 /* Get the color table from X */ 739 ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor)); 740 assert(ctable); 741 for (i = 0; i < cmapSize; i++) { 742 ctable[i].pixel = i; 743 } 744 XQueryColors(dpy, cmap, ctable, cmapSize); 745 prevDisplay = dpy; 746 prevCmap = cmap; 747 prevCmapSize = cmapSize; 748 } 749#endif 750 751 /* Find best match. */ 752 bestmatch = -1; 753 mindist = 0.0; 754 for (i = 0; i < cmapSize; i++) { 755 double dr = 0.30 * ((double) color->red - (double) ctable[i].red); 756 double dg = 0.59 * ((double) color->green - (double) ctable[i].green); 757 double db = 0.11 * ((double) color->blue - (double) ctable[i].blue); 758 double dist = dr * dr + dg * dg + db * db; 759 if (bestmatch < 0 || dist < mindist) { 760 bestmatch = i; 761 mindist = dist; 762 } 763 } 764 765 /* Return result. */ 766 subColor.red = ctable[bestmatch].red; 767 subColor.green = ctable[bestmatch].green; 768 subColor.blue = ctable[bestmatch].blue; 769 /* Try to allocate the closest match color. This should only 770 * fail if the cell is read/write. Otherwise, we're incrementing 771 * the cell's reference count. 772 */ 773#ifdef XFree86Server 774 if (AllocColor(cmap, 775 &subColor.red, &subColor.green, &subColor.blue, 776 &subColor.pixel, 777 client) == Success) { 778#else 779 if (XAllocColor(dpy, cmap, &subColor)) { 780#endif 781 *alloced = 1; 782 } 783 else { 784 /* do this to work around a problem reported by Frank Ortega */ 785 subColor.pixel = (unsigned long) bestmatch; 786 subColor.red = ctable[bestmatch].red; 787 subColor.green = ctable[bestmatch].green; 788 subColor.blue = ctable[bestmatch].blue; 789 subColor.flags = DoRed | DoGreen | DoBlue; 790 *alloced = 0; 791 } 792#ifdef XFree86Server 793 FREE(ppixIn); 794 FREE(ctable); 795#else 796 /* don't free table, save it for next time */ 797#endif 798 799 *color = subColor; 800 *exact = 0; 801} 802 803 804 805 806/* 807 * Do setup for PF_GRAYSCALE pixel format. 808 * Note that buffer may be NULL. 809 */ 810static GLboolean setup_grayscale( int client, XMesaVisual v, 811 XMesaBuffer buffer, XMesaColormap cmap ) 812{ 813 if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { 814 return GL_FALSE; 815 } 816 817 if (buffer) { 818 XMesaBuffer prevBuffer; 819 820 if (!cmap) { 821 return GL_FALSE; 822 } 823 824 prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); 825 if (prevBuffer && 826 (buffer->xm_visual->mesa_visual.rgbMode == 827 prevBuffer->xm_visual->mesa_visual.rgbMode)) { 828 /* Copy colormap stuff from previous XMesaBuffer which uses same 829 * X colormap. Do this to avoid time spent in noFaultXAllocColor. 830 */ 831 copy_colortable_info(buffer, prevBuffer); 832 } 833 else { 834 /* Allocate 256 shades of gray */ 835 int gray; 836 int colorsfailed = 0; 837 for (gray=0;gray<256;gray++) { 838 GLint r = gamma_adjust( v->RedGamma, gray, 255 ); 839 GLint g = gamma_adjust( v->GreenGamma, gray, 255 ); 840 GLint b = gamma_adjust( v->BlueGamma, gray, 255 ); 841 int exact, alloced; 842 XMesaColor xcol; 843 xcol.red = (r << 8) | r; 844 xcol.green = (g << 8) | g; 845 xcol.blue = (b << 8) | b; 846 noFaultXAllocColor( client, v->display, 847 cmap, GET_COLORMAP_SIZE(v), 848 &xcol, &exact, &alloced ); 849 if (!exact) { 850 colorsfailed++; 851 } 852 if (alloced) { 853 assert(buffer->num_alloced<256); 854 buffer->alloced_colors[buffer->num_alloced] = xcol.pixel; 855 buffer->num_alloced++; 856 } 857 858 /*OLD 859 assert(gray < 576); 860 buffer->color_table[gray*3+0] = xcol.pixel; 861 buffer->color_table[gray*3+1] = xcol.pixel; 862 buffer->color_table[gray*3+2] = xcol.pixel; 863 assert(xcol.pixel < 65536); 864 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100; 865 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100; 866 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100; 867 */ 868 buffer->color_table[gray] = xcol.pixel; 869 assert(xcol.pixel < 65536); 870 buffer->pixel_to_r[xcol.pixel] = gray; 871 buffer->pixel_to_g[xcol.pixel] = gray; 872 buffer->pixel_to_b[xcol.pixel] = gray; 873 } 874 875 if (colorsfailed && _mesa_getenv("MESA_DEBUG")) { 876 fprintf( stderr, 877 "Note: %d out of 256 needed colors do not match exactly.\n", 878 colorsfailed ); 879 } 880 } 881 } 882 883 v->dithered_pf = PF_GRAYSCALE; 884 v->undithered_pf = PF_GRAYSCALE; 885 return GL_TRUE; 886} 887 888 889 890/* 891 * Setup RGB rendering for a window with a PseudoColor, StaticColor, 892 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225 893 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB 894 * color. While this function was originally designed just for 8-bit 895 * visuals, it has also proven to work from 4-bit up to 16-bit visuals. 896 * Dithering code contributed by Bob Mercier. 897 */ 898static GLboolean setup_dithered_color( int client, XMesaVisual v, 899 XMesaBuffer buffer, XMesaColormap cmap ) 900{ 901 if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { 902 return GL_FALSE; 903 } 904 905 if (buffer) { 906 XMesaBuffer prevBuffer; 907 908 if (!cmap) { 909 return GL_FALSE; 910 } 911 912 prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); 913 if (prevBuffer && 914 (buffer->xm_visual->mesa_visual.rgbMode == 915 prevBuffer->xm_visual->mesa_visual.rgbMode)) { 916 /* Copy colormap stuff from previous, matching XMesaBuffer. 917 * Do this to avoid time spent in noFaultXAllocColor. 918 */ 919 copy_colortable_info(buffer, prevBuffer); 920 } 921 else { 922 /* Allocate X colors and initialize color_table[], red_table[], etc */ 923 int r, g, b, i; 924 int colorsfailed = 0; 925 for (r = 0; r < _R; r++) { 926 for (g = 0; g < _G; g++) { 927 for (b = 0; b < _B; b++) { 928 XMesaColor xcol; 929 int exact, alloced; 930 xcol.red =gamma_adjust(v->RedGamma, r*65535/(_R-1),65535); 931 xcol.green=gamma_adjust(v->GreenGamma, g*65535/(_G-1),65535); 932 xcol.blue =gamma_adjust(v->BlueGamma, b*65535/(_B-1),65535); 933 noFaultXAllocColor( client, v->display, 934 cmap, GET_COLORMAP_SIZE(v), 935 &xcol, &exact, &alloced ); 936 if (!exact) { 937 colorsfailed++; 938 } 939 if (alloced) { 940 assert(buffer->num_alloced<256); 941 buffer->alloced_colors[buffer->num_alloced] = xcol.pixel; 942 buffer->num_alloced++; 943 } 944 i = _MIX( r, g, b ); 945 assert(i < 576); 946 buffer->color_table[i] = xcol.pixel; 947 assert(xcol.pixel < 65536); 948 buffer->pixel_to_r[xcol.pixel] = r * 255 / (_R-1); 949 buffer->pixel_to_g[xcol.pixel] = g * 255 / (_G-1); 950 buffer->pixel_to_b[xcol.pixel] = b * 255 / (_B-1); 951 } 952 } 953 } 954 955 if (colorsfailed && _mesa_getenv("MESA_DEBUG")) { 956 fprintf( stderr, 957 "Note: %d out of %d needed colors do not match exactly.\n", 958 colorsfailed, _R*_G*_B ); 959 } 960 } 961 } 962 963 v->dithered_pf = PF_DITHER; 964 v->undithered_pf = PF_LOOKUP; 965 return GL_TRUE; 966} 967 968 969/* 970 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode. 971 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer. 972 * Special dithering tables have to be initialized. 973 */ 974static void setup_8bit_hpcr( XMesaVisual v ) 975{ 976 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be) 977 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined 978 * on the root window AND the colormap obtainable by XGetRGBColormaps 979 * for that atom must be set on the window. (see also tkInitWindow) 980 * If that colormap is not set, the output will look stripy. 981 */ 982 983 /* Setup color tables with gamma correction */ 984 int i; 985 double g; 986 987 g = 1.0 / v->RedGamma; 988 for (i=0; i<256; i++) { 989 GLint red = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[0][i]/255.0, g )); 990 v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 ); 991 } 992 993 g = 1.0 / v->GreenGamma; 994 for (i=0; i<256; i++) { 995 GLint green = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[1][i]/255.0, g )); 996 v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 ); 997 } 998 999 g = 1.0 / v->BlueGamma; 1000 for (i=0; i<256; i++) { 1001 GLint blue = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[2][i]/255.0, g )); 1002 v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 ); 1003 } 1004 v->undithered_pf = PF_HPCR; /* can't really disable dithering for now */ 1005 v->dithered_pf = PF_HPCR; 1006 1007 /* which method should I use to clear */ 1008 /* GL_FALSE: keep the ordinary method */ 1009 /* GL_TRUE : clear with dither pattern */ 1010 v->hpcr_clear_flag = _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE; 1011 1012 if (v->hpcr_clear_flag) { 1013 v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display, 1014 DefaultRootWindow(v->display), 1015 16, 2, 8); 1016#ifndef XFree86Server 1017 v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap, 1018 0, 0, 16, 2, AllPlanes, ZPixmap); 1019#endif 1020 } 1021} 1022 1023 1024/* 1025 * Setup RGB rendering for a window with a True/DirectColor visual. 1026 */ 1027static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer, 1028 XMesaColormap cmap ) 1029{ 1030 unsigned long rmask, gmask, bmask; 1031 (void) buffer; 1032 (void) cmap; 1033 1034 /* Compute red multiplier (mask) and bit shift */ 1035 v->rshift = 0; 1036 rmask = GET_REDMASK(v); 1037 while ((rmask & 1)==0) { 1038 v->rshift++; 1039 rmask = rmask >> 1; 1040 } 1041 1042 /* Compute green multiplier (mask) and bit shift */ 1043 v->gshift = 0; 1044 gmask = GET_GREENMASK(v); 1045 while ((gmask & 1)==0) { 1046 v->gshift++; 1047 gmask = gmask >> 1; 1048 } 1049 1050 /* Compute blue multiplier (mask) and bit shift */ 1051 v->bshift = 0; 1052 bmask = GET_BLUEMASK(v); 1053 while ((bmask & 1)==0) { 1054 v->bshift++; 1055 bmask = bmask >> 1; 1056 } 1057 1058 /* 1059 * Compute component-to-pixel lookup tables and dithering kernel 1060 */ 1061 { 1062 static GLubyte kernel[16] = { 1063 0*16, 8*16, 2*16, 10*16, 1064 12*16, 4*16, 14*16, 6*16, 1065 3*16, 11*16, 1*16, 9*16, 1066 15*16, 7*16, 13*16, 5*16, 1067 }; 1068 GLint rBits = bitcount(rmask); 1069 GLint gBits = bitcount(gmask); 1070 GLint bBits = bitcount(bmask); 1071 GLint maxBits; 1072 GLuint i; 1073 1074 /* convert pixel components in [0,_mask] to RGB values in [0,255] */ 1075 for (i=0; i<=rmask; i++) 1076 v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); 1077 for (i=0; i<=gmask; i++) 1078 v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); 1079 for (i=0; i<=bmask; i++) 1080 v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); 1081 1082 /* convert RGB values from [0,255] to pixel components */ 1083 1084 for (i=0;i<256;i++) { 1085 GLint r = gamma_adjust(v->RedGamma, i, 255); 1086 GLint g = gamma_adjust(v->GreenGamma, i, 255); 1087 GLint b = gamma_adjust(v->BlueGamma, i, 255); 1088 v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; 1089 v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; 1090 v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; 1091 } 1092 /* overflow protection */ 1093 for (i=256;i<512;i++) { 1094 v->RtoPixel[i] = v->RtoPixel[255]; 1095 v->GtoPixel[i] = v->GtoPixel[255]; 1096 v->BtoPixel[i] = v->BtoPixel[255]; 1097 } 1098 1099 /* setup dithering kernel */ 1100 maxBits = rBits; 1101 if (gBits > maxBits) maxBits = gBits; 1102 if (bBits > maxBits) maxBits = bBits; 1103 for (i=0;i<16;i++) { 1104 v->Kernel[i] = kernel[i] >> maxBits; 1105 } 1106 1107 v->undithered_pf = PF_TRUECOLOR; 1108 v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_TRUEDITHER : PF_TRUECOLOR; 1109 } 1110 1111 /* 1112 * Now check for TrueColor visuals which we can optimize. 1113 */ 1114 if ( GET_REDMASK(v) ==0x0000ff 1115 && GET_GREENMASK(v)==0x00ff00 1116 && GET_BLUEMASK(v) ==0xff0000 1117 && CHECK_BYTE_ORDER(v) 1118 && v->BitsPerPixel==32 1119 && sizeof(GLuint)==4 1120 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 1121 /* common 32 bpp config used on SGI, Sun */ 1122 v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; 1123 } 1124 else if (GET_REDMASK(v) ==0xff0000 1125 && GET_GREENMASK(v)==0x00ff00 1126 && GET_BLUEMASK(v) ==0x0000ff 1127 && CHECK_BYTE_ORDER(v) 1128 && v->BitsPerPixel==32 1129 && sizeof(GLuint)==4 1130 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 1131 /* common 32 bpp config used on Linux, HP, IBM */ 1132 v->undithered_pf = v->dithered_pf = PF_8R8G8B; 1133 } 1134 else if (GET_REDMASK(v) ==0xff0000 1135 && GET_GREENMASK(v)==0x00ff00 1136 && GET_BLUEMASK(v) ==0x0000ff 1137 && CHECK_BYTE_ORDER(v) 1138 && v->BitsPerPixel==24 1139 && sizeof(GLuint)==4 1140 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 1141 /* common packed 24 bpp config used on Linux */ 1142 v->undithered_pf = v->dithered_pf = PF_8R8G8B24; 1143 } 1144 else if (GET_REDMASK(v) ==0xf800 1145 && GET_GREENMASK(v)==0x07e0 1146 && GET_BLUEMASK(v) ==0x001f 1147 && CHECK_BYTE_ORDER(v) 1148 && v->BitsPerPixel==16 1149 && sizeof(GLushort)==2 1150 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 1151 /* 5-6-5 color weight on common PC VGA boards */ 1152 v->undithered_pf = PF_5R6G5B; 1153 v->dithered_pf = PF_DITHER_5R6G5B; 1154 } 1155 else if (GET_REDMASK(v) ==0xe0 1156 && GET_GREENMASK(v)==0x1c 1157 && GET_BLUEMASK(v) ==0x03 1158 && CHECK_FOR_HPCR(v)) { 1159 setup_8bit_hpcr( v ); 1160 } 1161} 1162 1163 1164 1165/* 1166 * Setup RGB rendering for a window with a monochrome visual. 1167 */ 1168static void setup_monochrome( XMesaVisual v, XMesaBuffer b ) 1169{ 1170 (void) b; 1171 v->dithered_pf = v->undithered_pf = PF_1BIT; 1172 /* if black=1 then we must flip pixel values */ 1173 v->bitFlip = (GET_BLACK_PIXEL(v) != 0); 1174} 1175 1176 1177 1178/* 1179 * When a context is "made current" for the first time, we can finally 1180 * finish initializing the context's visual and buffer information. 1181 * Input: v - the XMesaVisual to initialize 1182 * b - the XMesaBuffer to initialize (may be NULL) 1183 * rgb_flag - TRUE = RGBA mode, FALSE = color index mode 1184 * window - the window/pixmap we're rendering into 1185 * cmap - the colormap associated with the window/pixmap 1186 * Return: GL_TRUE=success, GL_FALSE=failure 1187 */ 1188static GLboolean initialize_visual_and_buffer( int client, 1189 XMesaVisual v, 1190 XMesaBuffer b, 1191 GLboolean rgb_flag, 1192 XMesaDrawable window, 1193 XMesaColormap cmap ) 1194{ 1195#ifndef XFree86Server 1196 XGCValues gcvalues; 1197#endif 1198 1199 if (b) { 1200 assert(b->xm_visual == v); 1201 } 1202 1203 /* Save true bits/pixel */ 1204 v->BitsPerPixel = bits_per_pixel(v); 1205 assert(v->BitsPerPixel > 0); 1206 1207 1208 if (rgb_flag==GL_FALSE) { 1209 /* COLOR-INDEXED WINDOW: 1210 * Even if the visual is TrueColor or DirectColor we treat it as 1211 * being color indexed. This is weird but might be useful to someone. 1212 */ 1213 v->dithered_pf = v->undithered_pf = PF_INDEX; 1214 v->index_bits = GET_VISUAL_DEPTH(v); 1215 } 1216 else { 1217 /* RGB WINDOW: 1218 * We support RGB rendering into almost any kind of visual. 1219 */ 1220 int xclass; 1221 xclass = GET_VISUAL_CLASS(v); 1222 if (xclass==TrueColor || xclass==DirectColor) { 1223 setup_truecolor( v, b, cmap ); 1224 } 1225 else if (xclass==StaticGray && GET_VISUAL_DEPTH(v)==1) { 1226 setup_monochrome( v, b ); 1227 } 1228 else if (xclass==GrayScale || xclass==StaticGray) { 1229 if (!setup_grayscale( client, v, b, cmap )) { 1230 return GL_FALSE; 1231 } 1232 } 1233 else if ((xclass==PseudoColor || xclass==StaticColor) 1234 && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) { 1235 if (!setup_dithered_color( client, v, b, cmap )) { 1236 return GL_FALSE; 1237 } 1238 } 1239 else { 1240 error("XMesa: RGB mode rendering not supported in given visual."); 1241 return GL_FALSE; 1242 } 1243 v->index_bits = 0; 1244 1245 if (_mesa_getenv("MESA_NO_DITHER")) { 1246 v->dithered_pf = v->undithered_pf; 1247 } 1248 } 1249 1250 1251 /* 1252 * If MESA_INFO env var is set print out some debugging info 1253 * which can help Brian figure out what's going on when a user 1254 * reports bugs. 1255 */ 1256 if (_mesa_getenv("MESA_INFO")) { 1257 fprintf(stderr, "X/Mesa visual = %p\n", (void *) v); 1258 fprintf(stderr, "X/Mesa dithered pf = %u\n", v->dithered_pf); 1259 fprintf(stderr, "X/Mesa undithered pf = %u\n", v->undithered_pf); 1260 fprintf(stderr, "X/Mesa level = %d\n", v->level); 1261 fprintf(stderr, "X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); 1262 fprintf(stderr, "X/Mesa bits per pixel = %d\n", v->BitsPerPixel); 1263 } 1264 1265 if (b && window) { 1266 /* Do window-specific initializations */ 1267 1268 /* Window dimensions */ 1269 unsigned int w, h; 1270 get_drawable_size( v->display, window, &w, &h ); 1271 b->width = w; 1272 b->height = h; 1273 1274 b->frontbuffer = window; 1275 1276 /* Setup for single/double buffering */ 1277 if (v->mesa_visual.doubleBufferMode) { 1278 /* Double buffered */ 1279#ifndef XFree86Server 1280 b->shm = check_for_xshm( v->display ); 1281#endif 1282 xmesa_alloc_back_buffer( b ); 1283 if (b->db_state==BACK_PIXMAP) { 1284 b->buffer = (XMesaDrawable)b->backpixmap; 1285 } 1286 else { 1287 b->buffer = XIMAGE; 1288 } 1289 } 1290 else { 1291 /* Single Buffered */ 1292 b->buffer = b->frontbuffer; 1293 } 1294 1295 /* X11 graphics contexts */ 1296#ifdef XFree86Server 1297 b->gc = CreateScratchGC(v->display, window->depth); 1298#else 1299 b->gc = XCreateGC( v->display, window, 0, NULL ); 1300#endif 1301 XMesaSetFunction( v->display, b->gc, GXcopy ); 1302 1303 /* cleargc - for glClear() */ 1304#ifdef XFree86Server 1305 b->cleargc = CreateScratchGC(v->display, window->depth); 1306#else 1307 b->cleargc = XCreateGC( v->display, window, 0, NULL ); 1308#endif 1309 XMesaSetFunction( v->display, b->cleargc, GXcopy ); 1310 1311 /* 1312 * Don't generate Graphics Expose/NoExpose events in swapbuffers(). 1313 * Patch contributed by Michael Pichler May 15, 1995. 1314 */ 1315#ifdef XFree86Server 1316 b->swapgc = CreateScratchGC(v->display, window->depth); 1317 { 1318 CARD32 v[1]; 1319 v[0] = FALSE; 1320 dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL); 1321 } 1322#else 1323 gcvalues.graphics_exposures = False; 1324 b->swapgc = XCreateGC( v->display, window, 1325 GCGraphicsExposures, &gcvalues); 1326#endif 1327 XMesaSetFunction( v->display, b->swapgc, GXcopy ); 1328 /* 1329 * Set fill style and tile pixmap once for all for HPCR stuff 1330 * (instead of doing it each time in clear_color_HPCR_pixmap()) 1331 * Initialize whole stuff 1332 * Patch contributed by Jacques Leroy March 8, 1998. 1333 */ 1334 if (v->hpcr_clear_flag && b->buffer!=XIMAGE) { 1335 int i; 1336 for (i=0; i<16; i++) 1337 { 1338 XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0); 1339 XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0); 1340 } 1341 XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap, 1342 b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); 1343 XMesaSetFillStyle( v->display, b->cleargc, FillTiled); 1344 XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap ); 1345 } 1346 1347 /* Initialize the row buffer XImage for use in write_color_span() */ 1348#ifdef XFree86Server 1349 b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, 1350 (char *)MALLOC(MAX_WIDTH*4)); 1351#else 1352 b->rowimage = XCreateImage( v->display, 1353 v->visinfo->visual, 1354 v->visinfo->depth, 1355 ZPixmap, 0, /*format, offset*/ 1356 (char*) MALLOC(MAX_WIDTH*4), /*data*/ 1357 MAX_WIDTH, 1, /*width, height*/ 1358 32, /*bitmap_pad*/ 1359 0 /*bytes_per_line*/ ); 1360#endif 1361 } 1362 1363 return GL_TRUE; 1364} 1365 1366 1367 1368/* 1369 * Convert an RGBA color to a pixel value. 1370 */ 1371unsigned long 1372xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a, 1373 GLuint pixelFormat) 1374{ 1375 switch (pixelFormat) { 1376 case PF_INDEX: 1377 return 0; 1378 case PF_TRUECOLOR: 1379 { 1380 unsigned long p; 1381 PACK_TRUECOLOR( p, r, g, b ); 1382 return p; 1383 } 1384 case PF_8A8B8G8R: 1385 return PACK_8A8B8G8R( r, g, b, a ); 1386 case PF_8R8G8B: 1387 /* fall through */ 1388 case PF_8R8G8B24: 1389 return PACK_8R8G8B( r, g, b ); 1390 case PF_5R6G5B: 1391 return PACK_5R6G5B( r, g, b ); 1392 case PF_DITHER: 1393 { 1394 DITHER_SETUP; 1395 return DITHER( 1, 0, r, g, b ); 1396 } 1397 case PF_1BIT: 1398 /* 382 = (3*255)/2 */ 1399 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 1400 case PF_HPCR: 1401 return DITHER_HPCR(1, 1, r, g, b); 1402 case PF_LOOKUP: 1403 { 1404 LOOKUP_SETUP; 1405 return LOOKUP( r, g, b ); 1406 } 1407 case PF_GRAYSCALE: 1408 return GRAY_RGB( r, g, b ); 1409 case PF_TRUEDITHER: 1410 /* fall through */ 1411 case PF_DITHER_5R6G5B: 1412 { 1413 unsigned long p; 1414 PACK_TRUEDITHER(p, 1, 0, r, g, b); 1415 return p; 1416 } 1417 default: 1418 _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel"); 1419 } 1420 return 0; 1421} 1422 1423 1424/**********************************************************************/ 1425/***** Public Functions *****/ 1426/**********************************************************************/ 1427 1428 1429/* 1430 * Create a new X/Mesa visual. 1431 * Input: display - X11 display 1432 * visinfo - an XVisualInfo pointer 1433 * rgb_flag - GL_TRUE = RGB mode, 1434 * GL_FALSE = color index mode 1435 * alpha_flag - alpha buffer requested? 1436 * db_flag - GL_TRUE = double-buffered, 1437 * GL_FALSE = single buffered 1438 * stereo_flag - stereo visual? 1439 * ximage_flag - GL_TRUE = use an XImage for back buffer, 1440 * GL_FALSE = use an off-screen pixmap for back buffer 1441 * depth_size - requested bits/depth values, or zero 1442 * stencil_size - requested bits/stencil values, or zero 1443 * accum_red_size - requested bits/red accum values, or zero 1444 * accum_green_size - requested bits/green accum values, or zero 1445 * accum_blue_size - requested bits/blue accum values, or zero 1446 * accum_alpha_size - requested bits/alpha accum values, or zero 1447 * num_samples - number of samples/pixel if multisampling, or zero 1448 * level - visual level, usually 0 1449 * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT 1450 * Return; a new XMesaVisual or 0 if error. 1451 */ 1452XMesaVisual XMesaCreateVisual( XMesaDisplay *display, 1453 XMesaVisualInfo visinfo, 1454 GLboolean rgb_flag, 1455 GLboolean alpha_flag, 1456 GLboolean db_flag, 1457 GLboolean stereo_flag, 1458 GLboolean ximage_flag, 1459 GLint depth_size, 1460 GLint stencil_size, 1461 GLint accum_red_size, 1462 GLint accum_green_size, 1463 GLint accum_blue_size, 1464 GLint accum_alpha_size, 1465 GLint num_samples, 1466 GLint level, 1467 GLint visualCaveat ) 1468{ 1469 char *gamma; 1470 XMesaVisual v; 1471 GLint red_bits, green_bits, blue_bits, alpha_bits; 1472 1473 /* For debugging only */ 1474 if (_mesa_getenv("MESA_XSYNC")) { 1475 /* This makes debugging X easier. 1476 * In your debugger, set a breakpoint on _XError to stop when an 1477 * X protocol error is generated. 1478 */ 1479#ifdef XFree86Server 1480 /* NOT_NEEDED */ 1481#else 1482 XSynchronize( display, 1 ); 1483#endif 1484 } 1485 1486 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); 1487 if (!v) { 1488 return NULL; 1489 } 1490 1491 /* 1492 * In the X server, NULL is passed in for the display. It will have 1493 * to be set before using this visual. See XMesaSetVisualDisplay() 1494 * below. 1495 */ 1496 v->display = display; 1497 1498 /* Save a copy of the XVisualInfo struct because the user may XFREE() 1499 * the struct but we may need some of the information contained in it 1500 * at a later time. 1501 */ 1502#ifdef XFree86Server 1503 v->visinfo = visinfo; 1504#else 1505 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); 1506 if(!v->visinfo) { 1507 FREE(v); 1508 return NULL; 1509 } 1510 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); 1511 1512 /* Save a copy of the pointer now so we can find this visual again 1513 * if we need to search for it in find_glx_visual(). 1514 */ 1515 v->vishandle = visinfo; 1516#endif 1517 1518#ifdef XFree86Server 1519 /* Initialize the depth of the screen */ 1520 { 1521 PixmapFormatRec *format; 1522 1523 for (format = screenInfo.formats; 1524 format->depth != display->rootDepth; 1525 format++) 1526 ; 1527 v->screen_depth = format->bitsPerPixel; 1528 } 1529#endif 1530 1531 /* check for MESA_GAMMA environment variable */ 1532 gamma = _mesa_getenv("MESA_GAMMA"); 1533 if (gamma) { 1534 v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; 1535 sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); 1536 if (v->RedGamma<=0.0) v->RedGamma = 1.0; 1537 if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; 1538 if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; 1539 } 1540 else { 1541 v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; 1542 } 1543 1544 v->ximage_flag = ximage_flag; 1545 v->level = level; 1546 v->VisualCaveat = visualCaveat; 1547 1548 (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 ); 1549 1550 { 1551 int xclass; 1552 xclass = GET_VISUAL_CLASS(v); 1553 if (xclass==TrueColor || xclass==DirectColor) { 1554 red_bits = bitcount(GET_REDMASK(v)); 1555 green_bits = bitcount(GET_GREENMASK(v)); 1556 blue_bits = bitcount(GET_BLUEMASK(v)); 1557 alpha_bits = 0; 1558 } 1559 else { 1560 /* this is an approximation */ 1561 int depth; 1562 depth = GET_VISUAL_DEPTH(v); 1563 red_bits = depth / 3; 1564 depth -= red_bits; 1565 green_bits = depth / 2; 1566 depth -= green_bits; 1567 blue_bits = depth; 1568 alpha_bits = 0; 1569 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); 1570 } 1571 } 1572 1573 if (alpha_flag && alpha_bits == 0) 1574 alpha_bits = 8; 1575 1576 _mesa_initialize_visual( &v->mesa_visual, 1577 rgb_flag, db_flag, stereo_flag, 1578 red_bits, green_bits, 1579 blue_bits, alpha_bits, 1580 v->index_bits, 1581 depth_size, 1582 stencil_size, 1583 accum_red_size, accum_green_size, 1584 accum_blue_size, accum_alpha_size, 1585 0 ); 1586 return v; 1587} 1588 1589 1590void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ) 1591{ 1592 v->display = dpy; 1593} 1594 1595 1596void XMesaDestroyVisual( XMesaVisual v ) 1597{ 1598#ifndef XFree86Server 1599 FREE(v->visinfo); 1600#endif 1601 FREE(v); 1602} 1603 1604 1605 1606/* 1607 * Create a new XMesaContext. 1608 * Input: v - XMesaVisual 1609 * share_list - another XMesaContext with which to share display 1610 * lists or NULL if no sharing is wanted. 1611 * Return: an XMesaContext or NULL if error. 1612 */ 1613XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 1614{ 1615 static GLboolean firstTime = GL_TRUE; 1616 XMesaContext c; 1617 GLcontext *ctx; 1618 GLboolean direct = GL_TRUE; /* not really */ 1619 1620 if (firstTime) { 1621 _glthread_INIT_MUTEX(_xmesa_lock); 1622 firstTime = GL_FALSE; 1623 } 1624 1625 c = (XMesaContext) CALLOC_STRUCT(xmesa_context); 1626 if (!c) { 1627 return NULL; 1628 } 1629 1630 ctx = c->gl_ctx = _mesa_create_context( &v->mesa_visual, 1631 share_list ? share_list->gl_ctx : (GLcontext *) NULL, 1632 (void *) c, direct); 1633 if (!c->gl_ctx) { 1634 FREE(c); 1635 return NULL; 1636 } 1637 1638 _mesa_enable_sw_extensions(ctx); 1639 _mesa_enable_1_3_extensions(ctx); 1640 /*_mesa_enable_1_4_extensions(ctx);*/ 1641 1642 if (CHECK_BYTE_ORDER(v)) { 1643 c->swapbytes = GL_FALSE; 1644 } 1645 else { 1646 c->swapbytes = GL_TRUE; 1647 } 1648 1649 c->xm_visual = v; 1650 c->xm_draw_buffer = NULL; /* set later by XMesaMakeCurrent */ 1651 c->xm_read_buffer = NULL; /* set later by XMesaMakeCurrent */ 1652 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ 1653 c->display = v->display; 1654 c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ 1655 1656 ctx->Driver.UpdateState = xmesa_update_state; 1657 1658 /* Initialize the software rasterizer and helper modules. 1659 */ 1660 _swrast_CreateContext( ctx ); 1661 _ac_CreateContext( ctx ); 1662 _tnl_CreateContext( ctx ); 1663 _swsetup_CreateContext( ctx ); 1664 1665 xmesa_register_swrast_functions( ctx ); 1666 1667 /* Set up some constant pointers: 1668 */ 1669 xmesa_init_pointers( ctx ); 1670 1671 return c; 1672} 1673 1674 1675 1676 1677void XMesaDestroyContext( XMesaContext c ) 1678{ 1679#ifdef FX 1680 if (c->xm_draw_buffer && c->xm_buffer->FXctx) 1681 fxMesaDestroyContext(c->xm_draw_buffer->FXctx); 1682#endif 1683 if (c->gl_ctx) { 1684 _swsetup_DestroyContext( c->gl_ctx ); 1685 _swrast_DestroyContext( c->gl_ctx ); 1686 _tnl_DestroyContext( c->gl_ctx ); 1687 _ac_DestroyContext( c->gl_ctx ); 1688 _mesa_destroy_context( c->gl_ctx ); 1689 } 1690 1691 FREE( c ); 1692} 1693 1694 1695 1696/* 1697 * XXX this isn't a public function! It's a hack for the 3Dfx driver. 1698 * Create a new XMesaBuffer from an X window. 1699 * Input: v - the XMesaVisual 1700 * w - the window 1701 * c - the context 1702 * Return: new XMesaBuffer or NULL if error 1703 */ 1704XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w, 1705 XMesaContext c ) 1706{ 1707#ifndef XFree86Server 1708 XWindowAttributes attr; 1709#endif 1710#ifdef FX 1711 char *fxEnvVar; 1712#endif 1713 int client = 0; 1714 1715 XMesaBuffer b = alloc_xmesa_buffer(); 1716 if (!b) { 1717 return NULL; 1718 } 1719 1720 (void) c; 1721 1722#ifdef XFree86Server 1723 client = CLIENT_ID(((XMesaDrawable)w)->id); 1724#endif 1725 1726 assert(v); 1727 1728#ifdef XFree86Server 1729 if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) { 1730#else 1731 XGetWindowAttributes( v->display, w, &attr ); 1732 1733 if (GET_VISUAL_DEPTH(v) != attr.depth) { 1734#endif 1735 if (_mesa_getenv("MESA_DEBUG")) { 1736 fprintf(stderr, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n"); 1737 } 1738 return NULL; 1739 } 1740 1741 b->xm_visual = v; 1742 b->type = WINDOW; 1743 b->display = v->display; 1744#ifdef XFree86Server 1745 b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); 1746#else 1747 if (attr.colormap) { 1748 b->cmap = attr.colormap; 1749 } 1750 else { 1751 if (_mesa_getenv("MESA_DEBUG")) { 1752 fprintf(stderr, "Window %u has no colormap!\n", (unsigned int) w); 1753 } 1754 /* this is weird, a window w/out a colormap!? */ 1755 /* OK, let's just allocate a new one and hope for the best */ 1756 b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); 1757 } 1758#endif 1759 1760 /* determine back buffer implementation */ 1761 if (v->mesa_visual.doubleBufferMode) { 1762 if (v->ximage_flag) { 1763 b->db_state = BACK_XIMAGE; 1764 } 1765 else { 1766 b->db_state = BACK_PIXMAP; 1767 } 1768 } 1769 else { 1770 b->db_state = 0; 1771 } 1772 1773 _mesa_initialize_framebuffer(&b->mesa_buffer, 1774 &v->mesa_visual, 1775 v->mesa_visual.depthBits > 0, 1776 v->mesa_visual.stencilBits > 0, 1777 v->mesa_visual.accumRedBits > 0, 1778 v->mesa_visual.alphaBits > 0 ); 1779 1780 if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode, 1781 (XMesaDrawable)w, b->cmap )) { 1782 free_xmesa_buffer(client, b); 1783 return NULL; 1784 } 1785 1786#ifdef FX 1787 fxEnvVar = _mesa_getenv("MESA_GLX_FX"); 1788 if (fxEnvVar) { 1789 if (fxEnvVar[0]!='d') { 1790 int attribs[100]; 1791 int numAttribs = 0; 1792 int hw; 1793 if (v->mesa_visual.depthBits > 0) { 1794 attribs[numAttribs++] = FXMESA_DEPTH_SIZE; 1795 attribs[numAttribs++] = 1; 1796 } 1797 if (v->mesa_visual.doubleBufferMode) { 1798 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; 1799 } 1800 if (v->mesa_visual.accumRedBits > 0) { 1801 attribs[numAttribs++] = FXMESA_ACCUM_SIZE; 1802 attribs[numAttribs++] = v->mesa_visual.accumRedBits; 1803 } 1804 if (v->mesa_visual.stencilBits > 0) { 1805 attribs[numAttribs++] = FXMESA_STENCIL_SIZE; 1806 attribs[numAttribs++] = v->mesa_visual.stencilBits; 1807 } 1808 if (v->mesa_visual.alphaBits > 0) { 1809 attribs[numAttribs++] = FXMESA_ALPHA_SIZE; 1810 attribs[numAttribs++] = 1; 1811 } 1812 if (c->gl_ctx) { 1813#define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with fxapi.c! */ 1814 attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; 1815 attribs[numAttribs++] = (int) c->gl_ctx; 1816 } 1817 attribs[numAttribs++] = FXMESA_NONE; 1818 1819 if ((hw = fxQueryHardware())==GR_SSTTYPE_VOODOO) { 1820 b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); 1821 if ((v->undithered_pf!=PF_INDEX) && (b->backimage)) { 1822 b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; 1823 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') 1824 b->FXwindowHack = b->FXctx ? GL_TRUE : GL_FALSE; 1825 else 1826 b->FXwindowHack = GL_FALSE; 1827 } 1828 } 1829 else { 1830 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') 1831 b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, 1832 GR_REFRESH_75Hz, attribs); 1833 else 1834 b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); 1835 b->FXisHackUsable = GL_FALSE; 1836 b->FXwindowHack = GL_FALSE; 1837 } 1838 /* 1839 fprintf(stderr, 1840 "voodoo %d, wid %d height %d hack: usable %d active %d\n", 1841 hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack); 1842 */ 1843 } 1844 } 1845 else { 1846 fprintf(stderr,"WARNING: This Mesa Library includes the Glide driver but\n"); 1847 fprintf(stderr," you have not defined the MESA_GLX_FX env. var.\n"); 1848 fprintf(stderr," (check the README.3DFX file for more information).\n\n"); 1849 fprintf(stderr," you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); 1850 } 1851#endif 1852 1853 return b; 1854} 1855 1856 1857XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w ) 1858{ 1859 return XMesaCreateWindowBuffer2( v, w, NULL ); 1860} 1861 1862 1863/* 1864 * Create a new XMesaBuffer from an X pixmap. 1865 * Input: v - the XMesaVisual 1866 * p - the pixmap 1867 * cmap - the colormap, may be 0 if using a TrueColor or DirectColor 1868 * visual for the pixmap 1869 * Return: new XMesaBuffer or NULL if error 1870 */ 1871XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, 1872 XMesaPixmap p, XMesaColormap cmap ) 1873{ 1874 int client = 0; 1875 XMesaBuffer b = alloc_xmesa_buffer(); 1876 if (!b) { 1877 return NULL; 1878 } 1879 1880 1881#ifdef XFree86Server 1882 client = CLIENT_ID(((XMesaDrawable)p)->id); 1883#endif 1884 1885 assert(v); 1886 1887 b->xm_visual = v; 1888 b->type = PIXMAP; 1889 b->display = v->display; 1890 b->cmap = cmap; 1891 1892 /* determine back buffer implementation */ 1893 if (v->mesa_visual.doubleBufferMode) { 1894 if (v->ximage_flag) { 1895 b->db_state = BACK_XIMAGE; 1896 } 1897 else { 1898 b->db_state = BACK_PIXMAP; 1899 } 1900 } 1901 else { 1902 b->db_state = 0; 1903 } 1904 1905 _mesa_initialize_framebuffer(&b->mesa_buffer, 1906 &v->mesa_visual, 1907 v->mesa_visual.depthBits > 0, 1908 v->mesa_visual.stencilBits > 0, 1909 v->mesa_visual.accumRedBits + 1910 v->mesa_visual.accumGreenBits + 1911 v->mesa_visual.accumBlueBits > 0, 1912 v->mesa_visual.alphaBits > 0 ); 1913 1914 if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, 1915 (XMesaDrawable)p, cmap)) { 1916 free_xmesa_buffer(client, b); 1917 return NULL; 1918 } 1919 1920 return b; 1921} 1922 1923 1924 1925XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap, 1926 unsigned int width, unsigned int height ) 1927{ 1928#ifdef XFree86Server 1929 return 0; 1930#else 1931 int client = 0; 1932 XMesaWindow root; 1933 XMesaDrawable drawable; /* X Pixmap Drawable */ 1934 XMesaBuffer b = alloc_xmesa_buffer(); 1935 if (!b) { 1936 return NULL; 1937 } 1938 1939 b->xm_visual = v; 1940 b->type = PBUFFER; 1941 b->display = v->display; 1942 b->cmap = cmap; 1943 1944 /* allocate pixmap for front buffer */ 1945 root = RootWindow( v->display, v->visinfo->screen ); 1946 drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth ); 1947 1948 /* determine back buffer implementation */ 1949 if (v->mesa_visual.doubleBufferMode) { 1950 if (v->ximage_flag) { 1951 b->db_state = BACK_XIMAGE; 1952 } 1953 else { 1954 b->db_state = BACK_PIXMAP; 1955 } 1956 } 1957 else { 1958 b->db_state = 0; 1959 } 1960 1961 _mesa_initialize_framebuffer(&b->mesa_buffer, 1962 &v->mesa_visual, 1963 v->mesa_visual.depthBits > 0, 1964 v->mesa_visual.stencilBits > 0, 1965 v->mesa_visual.accumRedBits + 1966 v->mesa_visual.accumGreenBits + 1967 v->mesa_visual.accumBlueBits > 0, 1968 v->mesa_visual.alphaBits > 0 ); 1969 1970 if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, 1971 drawable, cmap)) { 1972 free_xmesa_buffer(client, b); 1973 return NULL; 1974 } 1975 1976 return b; 1977#endif 1978} 1979 1980 1981 1982/* 1983 * Deallocate an XMesaBuffer structure and all related info. 1984 */ 1985void XMesaDestroyBuffer( XMesaBuffer b ) 1986{ 1987 int client = 0; 1988 1989#ifdef XFree86Server 1990 if (b->frontbuffer) 1991 client = CLIENT_ID(b->frontbuffer->id); 1992#endif 1993 1994 if (b->gc) XMesaFreeGC( b->xm_visual->display, b->gc ); 1995 if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc ); 1996 if (b->swapgc) XMesaFreeGC( b->xm_visual->display, b->swapgc ); 1997 1998 if (b->backimage) { 1999#if defined(USE_XSHM) && !defined(XFree86Server) 2000 if (b->shm) { 2001 XShmDetach( b->xm_visual->display, &b->shminfo ); 2002 XDestroyImage( b->backimage ); 2003 shmdt( b->shminfo.shmaddr ); 2004 } 2005 else 2006#endif 2007 XMesaDestroyImage( b->backimage ); 2008 } 2009 if (b->backpixmap) { 2010 XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); 2011 if (b->xm_visual->hpcr_clear_flag) { 2012 XMesaFreePixmap( b->xm_visual->display, 2013 b->xm_visual->hpcr_clear_pixmap ); 2014 XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); 2015 } 2016 } 2017 if (b->rowimage) { 2018 FREE( b->rowimage->data ); 2019 b->rowimage->data = NULL; 2020 XMesaDestroyImage( b->rowimage ); 2021 } 2022 2023 free_xmesa_buffer(client, b); 2024} 2025 2026 2027 2028/* 2029 * Bind buffer b to context c and make c the current rendering context. 2030 */ 2031GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) 2032{ 2033 return XMesaMakeCurrent2( c, b, b ); 2034} 2035 2036 2037/* 2038 * Bind buffer b to context c and make c the current rendering context. 2039 */ 2040GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, 2041 XMesaBuffer readBuffer ) 2042{ 2043 if (c) { 2044 if (!drawBuffer || !readBuffer) 2045 return GL_FALSE; /* must specify buffers! */ 2046 2047#ifdef FX 2048 if (drawBuffer->FXctx) { 2049 fxMesaMakeCurrent(drawBuffer->FXctx); 2050 2051 c->xm_draw_buffer = drawBuffer; 2052 c->xm_read_buffer = readBuffer; 2053 c->xm_buffer = drawBuffer; 2054 2055 return GL_TRUE; 2056 } 2057#endif 2058 if (c->gl_ctx == _mesa_get_current_context() 2059 && c->xm_draw_buffer == drawBuffer 2060 && c->xm_read_buffer == readBuffer 2061 && c->xm_draw_buffer->wasCurrent) { 2062 /* same context and buffer, do nothing */ 2063 return GL_TRUE; 2064 } 2065 2066 c->xm_draw_buffer = drawBuffer; 2067 c->xm_read_buffer = readBuffer; 2068 c->xm_buffer = drawBuffer; 2069 2070 _mesa_make_current2(c->gl_ctx, 2071 &drawBuffer->mesa_buffer, 2072 &readBuffer->mesa_buffer); 2073 2074 if (c->gl_ctx->Viewport.Width == 0) { 2075 /* initialize viewport to window size */ 2076 _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height ); 2077 c->gl_ctx->Scissor.Width = drawBuffer->width; 2078 c->gl_ctx->Scissor.Height = drawBuffer->height; 2079 } 2080 2081 if (c->xm_visual->mesa_visual.rgbMode) { 2082 /* 2083 * Must recompute and set these pixel values because colormap 2084 * can be different for different windows. 2085 */ 2086 c->clearpixel = xmesa_color_to_pixel( c, 2087 c->clearcolor[0], 2088 c->clearcolor[1], 2089 c->clearcolor[2], 2090 c->clearcolor[3], 2091 c->xm_visual->undithered_pf); 2092 XMesaSetForeground(c->display, c->xm_draw_buffer->cleargc, c->clearpixel); 2093 } 2094 2095 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 2096 c->xm_draw_buffer->wasCurrent = GL_TRUE; 2097 } 2098 else { 2099 /* Detach */ 2100 _mesa_make_current2( NULL, NULL, NULL ); 2101 } 2102 return GL_TRUE; 2103} 2104 2105 2106/* 2107 * Unbind the context c from its buffer. 2108 */ 2109GLboolean XMesaUnbindContext( XMesaContext c ) 2110{ 2111 /* A no-op for XFree86 integration purposes */ 2112 return GL_TRUE; 2113} 2114 2115 2116XMesaContext XMesaGetCurrentContext( void ) 2117{ 2118 GET_CURRENT_CONTEXT(ctx); 2119 if (ctx) { 2120 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2121 return xmesa; 2122 } 2123 else { 2124 return 0; 2125 } 2126} 2127 2128 2129XMesaBuffer XMesaGetCurrentBuffer( void ) 2130{ 2131 GET_CURRENT_CONTEXT(ctx); 2132 if (ctx) { 2133 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2134 return xmesa->xm_draw_buffer; 2135 } 2136 else { 2137 return 0; 2138 } 2139} 2140 2141 2142/* New in Mesa 3.1 */ 2143XMesaBuffer XMesaGetCurrentReadBuffer( void ) 2144{ 2145 GET_CURRENT_CONTEXT(ctx); 2146 if (ctx) { 2147 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2148 return xmesa->xm_read_buffer; 2149 } 2150 else { 2151 return 0; 2152 } 2153} 2154 2155 2156GLboolean XMesaForceCurrent(XMesaContext c) 2157{ 2158 if (c) { 2159 if (c->gl_ctx != _mesa_get_current_context()) { 2160 _mesa_make_current(c->gl_ctx, &c->xm_draw_buffer->mesa_buffer); 2161 } 2162 } 2163 else { 2164 _mesa_make_current(NULL, NULL); 2165 } 2166 return GL_TRUE; 2167} 2168 2169 2170GLboolean XMesaLoseCurrent(XMesaContext c) 2171{ 2172 (void) c; 2173 _mesa_make_current(NULL, NULL); 2174 return GL_TRUE; 2175} 2176 2177 2178/* 2179 * Switch 3Dfx support hack between window and full-screen mode. 2180 */ 2181GLboolean XMesaSetFXmode( GLint mode ) 2182{ 2183#ifdef FX 2184 const char *fx = _mesa_getenv("MESA_GLX_FX"); 2185 if (fx && fx[0] != 'd') { 2186 GET_CURRENT_CONTEXT(ctx); 2187 GrHwConfiguration hw; 2188 if (!FX_grSstQueryHardware(&hw)) { 2189 /*fprintf(stderr, "!grSstQueryHardware\n");*/ 2190 return GL_FALSE; 2191 } 2192 if (hw.num_sst < 1) { 2193 /*fprintf(stderr, "hw.num_sst < 1\n");*/ 2194 return GL_FALSE; 2195 } 2196 if (ctx) { 2197 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2198 if (mode == XMESA_FX_WINDOW) { 2199 if (xmesa->xm_draw_buffer->FXisHackUsable) { 2200 FX_grSstControl(GR_CONTROL_DEACTIVATE); 2201 xmesa->xm_draw_buffer->FXwindowHack = GL_TRUE; 2202 return GL_TRUE; 2203 } 2204 } 2205 else if (mode == XMESA_FX_FULLSCREEN) { 2206 FX_grSstControl(GR_CONTROL_ACTIVATE); 2207 xmesa->xm_draw_buffer->FXwindowHack = GL_FALSE; 2208 return GL_TRUE; 2209 } 2210 else { 2211 /* Error: Bad mode value */ 2212 } 2213 } 2214 } 2215 /*fprintf(stderr, "fallthrough\n");*/ 2216#else 2217 (void) mode; 2218#endif 2219 return GL_FALSE; 2220} 2221 2222 2223 2224#ifdef FX 2225/* 2226 * Read image from VooDoo frame buffer into X/Mesa's back XImage. 2227 */ 2228static void FXgetImage( XMesaBuffer b ) 2229{ 2230 GET_CURRENT_CONTEXT(ctx); 2231 static unsigned short pixbuf[MAX_WIDTH]; 2232 GLuint x, y; 2233 int xpos, ypos; 2234 XMesaWindow root; 2235 unsigned int bw, depth, width, height; 2236 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2237 2238#ifdef XFree86Server 2239 x = b->frontbuffer->x; 2240 y = b->frontbuffer->y; 2241 width = b->frontbuffer->width; 2242 height = b->frontbuffer->height; 2243 depth = b->frontbuffer->depth; 2244#else 2245 XGetGeometry( b->xm_visual->display, b->frontbuffer, 2246 &root, &xpos, &ypos, &width, &height, &bw, &depth); 2247#endif 2248 if (b->width != width || b->height != height) { 2249 b->width = MIN2((int)width, b->FXctx->width); 2250 b->height = MIN2((int)height, b->FXctx->height); 2251 if (b->width & 1) 2252 b->width--; /* prevent odd width */ 2253 xmesa_alloc_back_buffer( b ); 2254 } 2255 2256 grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); 2257 if (b->xm_visual->undithered_pf==PF_5R6G5B) { 2258 /* Special case: 16bpp RGB */ 2259 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ 2260 0, b->FXctx->height - b->height, /*pos*/ 2261 b->width, b->height, /* size */ 2262 b->width * sizeof(GLushort), /* stride */ 2263 b->backimage->data); /* dest buffer */ 2264 } 2265 else if (b->xm_visual->dithered_pf==PF_DITHER 2266 && GET_VISUAL_DEPTH(b->xm_visual)==8) { 2267 /* Special case: 8bpp RGB */ 2268 for (y=0;y<b->height;y++) { 2269 GLubyte *ptr = (GLubyte*) b->backimage->data 2270 + b->backimage->bytes_per_line * y; 2271 XDITHER_SETUP(y); 2272 2273 /* read row from 3Dfx frame buffer */ 2274 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2275 0, b->FXctx->height-(b->height-y), 2276 b->width, 1, 2277 0, 2278 pixbuf ); 2279 2280 /* write to XImage back buffer */ 2281 for (x=0;x<b->width;x++) { 2282 GLubyte r = (pixbuf[x] & 0xf800) >> 8; 2283 GLubyte g = (pixbuf[x] & 0x07e0) >> 3; 2284 GLubyte b = (pixbuf[x] & 0x001f) << 3; 2285 *ptr++ = XDITHER( x, r, g, b); 2286 } 2287 } 2288 } 2289 else { 2290 /* General case: slow! */ 2291 for (y=0;y<b->height;y++) { 2292 /* read row from 3Dfx frame buffer */ 2293 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2294 0, b->FXctx->height-(b->height-y), 2295 b->width, 1, 2296 0, 2297 pixbuf ); 2298 2299 /* write to XImage back buffer */ 2300 for (x=0;x<b->width;x++) { 2301 XMesaPutPixel(b->backimage,x,y, 2302 xmesa_color_to_pixel(xmesa, 2303 (pixbuf[x] & 0xf800) >> 8, 2304 (pixbuf[x] & 0x07e0) >> 3, 2305 (pixbuf[x] & 0x001f) << 3, 2306 0xff, 2307 b->xm_visual->undithered_pf)); 2308 } 2309 } 2310 } 2311 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); 2312} 2313#endif 2314 2315 2316/* 2317 * Copy the back buffer to the front buffer. If there's no back buffer 2318 * this is a no-op. 2319 */ 2320void XMesaSwapBuffers( XMesaBuffer b ) 2321{ 2322 GET_CURRENT_CONTEXT(ctx); 2323 2324 /* If we're swapping the buffer associated with the current context 2325 * we have to flush any pending rendering commands first. 2326 */ 2327 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2328 _mesa_notifySwapBuffers(ctx); 2329 2330 if (b->db_state) { 2331#ifdef FX 2332 if (b->FXctx) { 2333 fxMesaSwapBuffers(); 2334 2335 if (b->FXwindowHack) 2336 FXgetImage(b); 2337 else 2338 return; 2339 } 2340#endif 2341 if (b->backimage) { 2342 /* Copy Ximage from host's memory to server's window */ 2343#if defined(USE_XSHM) && !defined(XFree86Server) 2344 if (b->shm) { 2345 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2346 XShmPutImage( b->xm_visual->display, b->frontbuffer, 2347 b->swapgc, 2348 b->backimage, 0, 0, 2349 0, 0, b->width, b->height, False ); 2350 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2351 } 2352 else 2353#endif 2354 { 2355 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2356 XMesaPutImage( b->xm_visual->display, b->frontbuffer, 2357 b->swapgc, 2358 b->backimage, 0, 0, 2359 0, 0, b->width, b->height ); 2360 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2361 } 2362 } 2363 else { 2364 /* Copy pixmap to window on server */ 2365 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2366 XMesaCopyArea( b->xm_visual->display, 2367 b->backpixmap, /* source drawable */ 2368 b->frontbuffer, /* dest. drawable */ 2369 b->swapgc, 2370 0, 0, b->width, b->height, /* source region */ 2371 0, 0 /* dest region */ 2372 ); 2373 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2374 } 2375 } 2376#if !defined(XFree86Server) 2377 XSync( b->xm_visual->display, False ); 2378#endif 2379} 2380 2381 2382 2383/* 2384 * Copy sub-region of back buffer to front buffer 2385 */ 2386void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 2387{ 2388 GET_CURRENT_CONTEXT(ctx); 2389 2390 /* If we're swapping the buffer associated with the current context 2391 * we have to flush any pending rendering commands first. 2392 */ 2393 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2394 _mesa_notifySwapBuffers(ctx); 2395 2396 if (b->db_state) { 2397 int yTop = b->height - y - height; 2398#ifdef FX 2399 if (b->FXctx) { 2400 fxMesaSwapBuffers(); 2401 if (b->FXwindowHack) 2402 FXgetImage(b); 2403 else 2404 return; 2405 } 2406#endif 2407 if (b->backimage) { 2408 /* Copy Ximage from host's memory to server's window */ 2409#if defined(USE_XSHM) && !defined(XFree86Server) 2410 if (b->shm) { 2411 /* XXX assuming width and height aren't too large! */ 2412 XShmPutImage( b->xm_visual->display, b->frontbuffer, 2413 b->swapgc, 2414 b->backimage, x, yTop, 2415 x, yTop, width, height, False ); 2416 /* wait for finished event??? */ 2417 } 2418 else 2419#endif 2420 { 2421 /* XXX assuming width and height aren't too large! */ 2422 XMesaPutImage( b->xm_visual->display, b->frontbuffer, 2423 b->swapgc, 2424 b->backimage, x, yTop, 2425 x, yTop, width, height ); 2426 } 2427 } 2428 else { 2429 /* Copy pixmap to window on server */ 2430 XMesaCopyArea( b->xm_visual->display, 2431 b->backpixmap, /* source drawable */ 2432 b->frontbuffer, /* dest. drawable */ 2433 b->swapgc, 2434 x, yTop, width, height, /* source region */ 2435 x, yTop /* dest region */ 2436 ); 2437 } 2438 } 2439} 2440 2441 2442/* 2443 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function 2444 * is a way to get "under the hood" of X/Mesa so one can manipulate the 2445 * back buffer directly. 2446 * Output: pixmap - pointer to back buffer's Pixmap, or 0 2447 * ximage - pointer to back buffer's XImage, or NULL 2448 * Return: GL_TRUE = context is double buffered 2449 * GL_FALSE = context is single buffered 2450 */ 2451GLboolean XMesaGetBackBuffer( XMesaBuffer b, 2452 XMesaPixmap *pixmap, 2453 XMesaImage **ximage ) 2454{ 2455 if (b->db_state) { 2456 if (pixmap) *pixmap = b->backpixmap; 2457 if (ximage) *ximage = b->backimage; 2458 return GL_TRUE; 2459 } 2460 else { 2461 *pixmap = 0; 2462 *ximage = NULL; 2463 return GL_FALSE; 2464 } 2465} 2466 2467 2468/* 2469 * Return the depth buffer associated with an XMesaBuffer. 2470 * Input: b - the XMesa buffer handle 2471 * Output: width, height - size of buffer in pixels 2472 * bytesPerValue - bytes per depth value (2 or 4) 2473 * buffer - pointer to depth buffer values 2474 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 2475 */ 2476GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, 2477 GLint *bytesPerValue, void **buffer ) 2478{ 2479 if (!b->mesa_buffer.DepthBuffer) { 2480 *width = 0; 2481 *height = 0; 2482 *bytesPerValue = 0; 2483 *buffer = 0; 2484 return GL_FALSE; 2485 } 2486 else { 2487 *width = b->mesa_buffer.Width; 2488 *height = b->mesa_buffer.Height; 2489 *bytesPerValue = sizeof(GLdepth); 2490 *buffer = b->mesa_buffer.DepthBuffer; 2491 return GL_TRUE; 2492 } 2493} 2494 2495 2496void XMesaFlush( XMesaContext c ) 2497{ 2498 if (c && c->xm_visual) { 2499#ifdef XFree86Server 2500 /* NOT_NEEDED */ 2501#else 2502 XSync( c->xm_visual->display, False ); 2503#endif 2504 } 2505} 2506 2507 2508 2509const char *XMesaGetString( XMesaContext c, int name ) 2510{ 2511 (void) c; 2512 if (name==XMESA_VERSION) { 2513 return "3.5"; 2514 } 2515 else if (name==XMESA_EXTENSIONS) { 2516 return ""; 2517 } 2518 else { 2519 return NULL; 2520 } 2521} 2522 2523 2524 2525XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) 2526{ 2527 XMesaBuffer b; 2528 for (b=XMesaBufferList; b; b=b->Next) { 2529 if (b->frontbuffer==d && b->display==dpy) { 2530 return b; 2531 } 2532 } 2533 return NULL; 2534} 2535 2536 2537 2538/* 2539 * Look for XMesaBuffers whose X window has been destroyed. 2540 * Deallocate any such XMesaBuffers. 2541 */ 2542void XMesaGarbageCollect( void ) 2543{ 2544 XMesaBuffer b, next; 2545 for (b=XMesaBufferList; b; b=next) { 2546 next = b->Next; 2547 if (b->display && b->frontbuffer && b->type == WINDOW) { 2548#ifdef XFree86Server 2549 /* NOT_NEEDED */ 2550#else 2551 XSync(b->display, False); 2552 if (!window_exists( b->display, b->frontbuffer )) { 2553 /* found a dead window, free the ancillary info */ 2554 XMesaDestroyBuffer( b ); 2555 } 2556#endif 2557 } 2558 } 2559} 2560 2561 2562void XMesaReset( void ) 2563{ 2564 while (XMesaBufferList) 2565 XMesaDestroyBuffer(XMesaBufferList); 2566 2567 XMesaBufferList = NULL; 2568} 2569 2570 2571unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, 2572 GLfloat red, GLfloat green, 2573 GLfloat blue, GLfloat alpha ) 2574{ 2575 GLint r = (GLint) (red * 255.0F); 2576 GLint g = (GLint) (green * 255.0F); 2577 GLint b = (GLint) (blue * 255.0F); 2578 GLint a = (GLint) (alpha * 255.0F); 2579 2580 switch (xmesa->pixelformat) { 2581 case PF_INDEX: 2582 return 0; 2583 case PF_TRUECOLOR: 2584 { 2585 unsigned long p; 2586 PACK_TRUECOLOR( p, r, g, b ); 2587 return p; 2588 } 2589 case PF_8A8B8G8R: 2590 return PACK_8A8B8G8R( r, g, b, a ); 2591 case PF_8R8G8B: 2592 return PACK_8R8G8B( r, g, b ); 2593 case PF_5R6G5B: 2594 return PACK_5R6G5B( r, g, b ); 2595 case PF_DITHER: 2596 { 2597 DITHER_SETUP; 2598 return DITHER( x, y, r, g, b ); 2599 } 2600 case PF_1BIT: 2601 /* 382 = (3*255)/2 */ 2602 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 2603 case PF_HPCR: 2604 return DITHER_HPCR(x, y, r, g, b); 2605 case PF_LOOKUP: 2606 { 2607 LOOKUP_SETUP; 2608 return LOOKUP( r, g, b ); 2609 } 2610 case PF_GRAYSCALE: 2611 return GRAY_RGB( r, g, b ); 2612 case PF_DITHER_5R6G5B: 2613 /* fall through */ 2614 case PF_TRUEDITHER: 2615 { 2616 unsigned long p; 2617 PACK_TRUEDITHER(p, x, y, r, g, b); 2618 return p; 2619 } 2620 default: 2621 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); 2622 } 2623 return 0; 2624} 2625 2626 2627/* 2628 * This is typically called when the window size changes and we need 2629 * to reallocate the buffer's back/depth/stencil/accum buffers. 2630 */ 2631void XMesaResizeBuffers( XMesaBuffer b ) 2632{ 2633 xmesa_resize_buffers( &(b->mesa_buffer) ); 2634 2635} 2636 2637