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