xm_api.c revision a96308c37db0bc0086a017d318bc3504aa5f0b1a
1/* $Id: xm_api.c,v 1.4 2000/10/30 13:32:03 keithw 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#include "macros.h" 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 /* These flags cover all the tests made in UpdateState, plus what 1659 * the software rasterizer needs to choose line,point and triangle 1660 * functions. 1661 */ 1662 c->gl_ctx->Driver.UpdateStateNotify = (_NEW_POINT| 1663 _NEW_TEXTURE| 1664 _NEW_LINE| 1665 _NEW_LIGHT| 1666 _NEW_DEPTH| 1667 _NEW_POLYGON| 1668 _NEW_TEXTURE| 1669 _SWRAST_NEW_RASTERMASK| 1670 _SWRAST_NEW_TRIANGLE| 1671 _SWRAST_NEW_LINE| 1672 _SWRAST_NEW_POINT); 1673 1674#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server) 1675 c->driContextPriv = driContextPriv; 1676#endif 1677 1678 /* Run the config file */ 1679 _mesa_context_initialize( c->gl_ctx ); 1680 1681 return c; 1682} 1683 1684 1685 1686 1687void XMesaDestroyContext( XMesaContext c ) 1688{ 1689#ifdef FX 1690 if (c->xm_buffer && c->xm_buffer->FXctx) 1691 fxMesaDestroyContext(c->xm_buffer->FXctx); 1692#endif 1693 if (c->gl_ctx) 1694 _mesa_destroy_context( c->gl_ctx ); 1695 1696 /* Disassociate old buffer with this context */ 1697 if (c->xm_buffer) 1698 c->xm_buffer->xm_context = NULL; 1699 1700 /* Destroy any buffers which are using this context. If we don't 1701 * we may have dangling references. Hmm, maybe we should just 1702 * set the buffer's context pointer to NULL instead of deleting it? 1703 * Let's see if we get any bug reports... 1704 * This contributed by Doug Rabson <dfr@calcaphon.com> 1705 */ 1706 { 1707 XMesaBuffer b, next; 1708 for (b = XMesaBufferList; b; b = next) { 1709 next = b->Next; 1710 if (!b->pixmap_flag) { 1711#ifndef XFree86Server 1712 XSync(b->display, False); 1713#endif 1714 if (b->xm_context == c) { 1715 /* found a context created for this context */ 1716 XMesaDestroyBuffer( b ); 1717 } 1718 } 1719 } 1720 } 1721 1722 FREE( c ); 1723} 1724 1725 1726 1727/* 1728 * XXX this isn't a public function! It's a hack for the 3Dfx driver. 1729 * Create a new XMesaBuffer from an X window. 1730 * Input: v - the XMesaVisual 1731 * w - the window 1732 * c - the context 1733 * Return: new XMesaBuffer or NULL if error 1734 */ 1735XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w, 1736 XMesaContext c ) 1737{ 1738#ifndef XFree86Server 1739 XWindowAttributes attr; 1740#endif 1741#ifdef FX 1742 char *fxEnvVar; 1743#endif 1744 int client = 0; 1745 1746 XMesaBuffer b = alloc_xmesa_buffer(); 1747 if (!b) { 1748 return NULL; 1749 } 1750 1751 (void) c; 1752 1753#ifdef XFree86Server 1754 client = CLIENT_ID(((XMesaDrawable)w)->id); 1755#endif 1756 1757 assert(v); 1758 1759#ifdef XFree86Server 1760 if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) { 1761#else 1762 XGetWindowAttributes( v->display, w, &attr ); 1763 1764 if (GET_VISUAL_DEPTH(v) != attr.depth) { 1765#endif 1766 if (getenv("MESA_DEBUG")) { 1767 fprintf(stderr, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n"); 1768 } 1769 return NULL; 1770 } 1771 1772 b->xm_context = NULL; /* Associate no context with this buffer */ 1773 1774 b->xm_visual = v; 1775 b->pixmap_flag = GL_FALSE; 1776 b->display = v->display; 1777#ifdef XFree86Server 1778 b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); 1779#else 1780 if (attr.colormap) { 1781 b->cmap = attr.colormap; 1782 } 1783 else { 1784 if (getenv("MESA_DEBUG")) { 1785 fprintf(stderr, "Window %u has no colormap!\n", (unsigned int) w); 1786 } 1787 /* this is weird, a window w/out a colormap!? */ 1788 /* OK, let's just allocate a new one and hope for the best */ 1789 b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); 1790 } 1791#endif 1792 1793 /* determine back buffer implementation */ 1794 if (v->gl_visual->DBflag) { 1795 if (v->ximage_flag) { 1796 b->db_state = BACK_XIMAGE; 1797 } 1798 else { 1799 b->db_state = BACK_PIXMAP; 1800 } 1801 } 1802 else { 1803 b->db_state = 0; 1804 } 1805 1806 b->gl_buffer = _mesa_create_framebuffer( v->gl_visual, 1807 v->gl_visual->DepthBits > 0, 1808 v->gl_visual->StencilBits > 0, 1809 v->gl_visual->AccumRedBits > 0, 1810 v->gl_visual->AlphaBits > 0 ); 1811 if (!b->gl_buffer) { 1812 free_xmesa_buffer(client, b); 1813 return NULL; 1814 } 1815 1816 if (!initialize_visual_and_buffer( client, v, b, v->gl_visual->RGBAflag, 1817 (XMesaDrawable)w, b->cmap )) { 1818 _mesa_destroy_framebuffer( b->gl_buffer ); 1819 free_xmesa_buffer(client, b); 1820 return NULL; 1821 } 1822 1823#ifdef FX 1824 fxEnvVar = getenv("MESA_GLX_FX"); 1825 if (fxEnvVar) { 1826 if (fxEnvVar[0]!='d') { 1827 int attribs[100]; 1828 int numAttribs = 0; 1829 int hw; 1830 if (v->gl_visual->DepthBits > 0) { 1831 attribs[numAttribs++] = FXMESA_DEPTH_SIZE; 1832 attribs[numAttribs++] = 1; 1833 } 1834 if (v->gl_visual->DBflag) { 1835 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; 1836 } 1837 if (v->gl_visual->AccumRedBits > 0) { 1838 attribs[numAttribs++] = FXMESA_ACCUM_SIZE; 1839 attribs[numAttribs++] = v->gl_visual->AccumRedBits; 1840 } 1841 if (v->gl_visual->StencilBits > 0) { 1842 attribs[numAttribs++] = FXMESA_STENCIL_SIZE; 1843 attribs[numAttribs++] = v->gl_visual->StencilBits; 1844 } 1845 if (v->gl_visual->AlphaBits > 0) { 1846 attribs[numAttribs++] = FXMESA_ALPHA_SIZE; 1847 attribs[numAttribs++] = 1; 1848 } 1849 if (c->gl_ctx) { 1850#define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with fxapi.c! */ 1851 attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; 1852 attribs[numAttribs++] = (int) c->gl_ctx; 1853 } 1854 attribs[numAttribs++] = FXMESA_NONE; 1855 1856 if ((hw = fxQueryHardware())==GR_SSTTYPE_VOODOO) { 1857 b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); 1858 if ((v->undithered_pf!=PF_INDEX) && (b->backimage)) { 1859 b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; 1860 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') 1861 b->FXwindowHack = b->FXctx ? GL_TRUE : GL_FALSE; 1862 else 1863 b->FXwindowHack = GL_FALSE; 1864 } 1865 } 1866 else { 1867 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') 1868 b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, 1869 GR_REFRESH_75Hz, attribs); 1870 else 1871 b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); 1872 b->FXisHackUsable = GL_FALSE; 1873 b->FXwindowHack = GL_FALSE; 1874 } 1875 /* 1876 fprintf(stderr, 1877 "voodoo %d, wid %d height %d hack: usable %d active %d\n", 1878 hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack); 1879 */ 1880 } 1881 } 1882 else { 1883 fprintf(stderr,"WARNING: This Mesa Library includes the Glide driver but\n"); 1884 fprintf(stderr," you have not defined the MESA_GLX_FX env. var.\n"); 1885 fprintf(stderr," (check the README.3DFX file for more information).\n\n"); 1886 fprintf(stderr," you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); 1887 } 1888#endif 1889 1890#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server) 1891 b->driDrawPriv = driDrawPriv; 1892#endif 1893 1894 return b; 1895} 1896 1897 1898XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w ) 1899{ 1900 return XMesaCreateWindowBuffer2( v, w, NULL ); 1901} 1902 1903 1904/* 1905 * Create a new XMesaBuffer from an X pixmap. 1906 * Input: v - the XMesaVisual 1907 * p - the pixmap 1908 * cmap - the colormap, may be 0 if using a TrueColor or DirectColor 1909 * visual for the pixmap 1910 * Return: new XMesaBuffer or NULL if error 1911 */ 1912XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, 1913 XMesaPixmap p, XMesaColormap cmap ) 1914{ 1915 int client = 0; 1916 XMesaBuffer b = alloc_xmesa_buffer(); 1917 if (!b) { 1918 return NULL; 1919 } 1920 1921 1922#ifdef XFree86Server 1923 client = CLIENT_ID(((XMesaDrawable)p)->id); 1924#endif 1925 1926 assert(v); 1927 1928 b->xm_context = NULL; /* Associate no context with this buffer */ 1929 1930 b->xm_visual = v; 1931 b->pixmap_flag = GL_TRUE; 1932 b->display = v->display; 1933 b->cmap = cmap; 1934 1935 /* determine back buffer implementation */ 1936 if (v->gl_visual->DBflag) { 1937 if (v->ximage_flag) { 1938 b->db_state = BACK_XIMAGE; 1939 } 1940 else { 1941 b->db_state = BACK_PIXMAP; 1942 } 1943 } 1944 else { 1945 b->db_state = 0; 1946 } 1947 1948 b->gl_buffer = _mesa_create_framebuffer( v->gl_visual, 1949 v->gl_visual->DepthBits > 0, 1950 v->gl_visual->StencilBits > 0, 1951 v->gl_visual->AccumRedBits + 1952 v->gl_visual->AccumGreenBits + 1953 v->gl_visual->AccumBlueBits > 0, 1954 v->gl_visual->AlphaBits > 0 ); 1955 if (!b->gl_buffer) { 1956 free_xmesa_buffer(client, b); 1957 return NULL; 1958 } 1959 1960 if (!initialize_visual_and_buffer(client, v, b, v->gl_visual->RGBAflag, 1961 (XMesaDrawable)p, cmap)) { 1962 _mesa_destroy_framebuffer( b->gl_buffer ); 1963 free_xmesa_buffer(client, b); 1964 return NULL; 1965 } 1966 1967#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server) 1968 b->driDrawPriv = driDrawPriv; 1969#endif 1970 1971 return b; 1972} 1973 1974 1975 1976/* 1977 * Deallocate an XMesaBuffer structure and all related info. 1978 */ 1979void XMesaDestroyBuffer( XMesaBuffer b ) 1980{ 1981 int client = 0; 1982 1983#ifdef XFree86Server 1984 if (b->frontbuffer) 1985 client = CLIENT_ID(b->frontbuffer->id); 1986#endif 1987 1988 if (b->gc1) XMesaFreeGC( b->xm_visual->display, b->gc1 ); 1989 if (b->gc2) XMesaFreeGC( b->xm_visual->display, b->gc2 ); 1990 if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc ); 1991 1992 if (b->backimage) { 1993#if defined(USE_XSHM) && !defined(XFree86Server) 1994 if (b->shm) { 1995 XShmDetach( b->xm_visual->display, &b->shminfo ); 1996 XDestroyImage( b->backimage ); 1997 shmdt( b->shminfo.shmaddr ); 1998 } 1999 else 2000#endif 2001 XMesaDestroyImage( b->backimage ); 2002 } 2003 if (b->backpixmap) { 2004 XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); 2005 if (b->xm_visual->hpcr_clear_flag) { 2006 XMesaFreePixmap( b->xm_visual->display, 2007 b->xm_visual->hpcr_clear_pixmap ); 2008 XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); 2009 } 2010 } 2011 if (b->rowimage) { 2012 FREE( b->rowimage->data ); 2013 b->rowimage->data = NULL; 2014 XMesaDestroyImage( b->rowimage ); 2015 } 2016 2017 if (b->xm_context) 2018 b->xm_context->xm_buffer = NULL; 2019 2020 _mesa_destroy_framebuffer( b->gl_buffer ); 2021 free_xmesa_buffer(client, b); 2022} 2023 2024 2025 2026/* 2027 * Bind buffer b to context c and make c the current rendering context. 2028 */ 2029GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) 2030{ 2031 return XMesaMakeCurrent2( c, b, b ); 2032} 2033 2034 2035/* 2036 * Bind buffer b to context c and make c the current rendering context. 2037 */ 2038GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, 2039 XMesaBuffer readBuffer ) 2040{ 2041 if (c) { 2042 if (!drawBuffer || !readBuffer) 2043 return GL_FALSE; /* must specify buffers! */ 2044 2045#ifdef FX 2046 if (drawBuffer->FXctx) { 2047 fxMesaMakeCurrent(drawBuffer->FXctx); 2048 2049 /* Disassociate old buffer from this context */ 2050 if (c->xm_buffer) 2051 c->xm_buffer->xm_context = NULL; 2052 2053 /* Associate the context with this buffer */ 2054 drawBuffer->xm_context = c; 2055 2056 c->xm_buffer = drawBuffer; 2057 c->xm_read_buffer = readBuffer; 2058 c->use_read_buffer = (drawBuffer != readBuffer); 2059 2060 return GL_TRUE; 2061 } 2062#endif 2063 if (c->gl_ctx == _mesa_get_current_context() 2064 && c->xm_buffer == drawBuffer 2065 && c->xm_read_buffer == readBuffer 2066 && c->xm_buffer->wasCurrent) { 2067 /* same context and buffer, do nothing */ 2068 return GL_TRUE; 2069 } 2070 2071 /* Disassociate old buffer with this context */ 2072 if (c->xm_buffer) 2073 c->xm_buffer->xm_context = NULL; 2074 drawBuffer->xm_context = c; /* Associate the context with this buffer */ 2075 2076 c->xm_buffer = drawBuffer; 2077 c->xm_read_buffer = readBuffer; 2078 c->use_read_buffer = (drawBuffer != readBuffer); 2079 2080 _mesa_make_current2(c->gl_ctx, drawBuffer->gl_buffer, readBuffer->gl_buffer); 2081 2082 if (c->gl_ctx->Viewport.Width == 0) { 2083 /* initialize viewport to window size */ 2084 _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height ); 2085 c->gl_ctx->Scissor.Width = drawBuffer->width; 2086 c->gl_ctx->Scissor.Height = drawBuffer->height; 2087 } 2088 2089 if (c->xm_visual->gl_visual->RGBAflag) { 2090 /* 2091 * Must recompute and set these pixel values because colormap 2092 * can be different for different windows. 2093 */ 2094 c->pixel = xmesa_color_to_pixel( c, c->red, c->green, 2095 c->blue, c->alpha, c->pixelformat ); 2096 XMesaSetForeground( c->display, c->xm_buffer->gc1, c->pixel ); 2097 c->clearpixel = xmesa_color_to_pixel( c, 2098 c->clearcolor[0], 2099 c->clearcolor[1], 2100 c->clearcolor[2], 2101 c->clearcolor[3], 2102 c->xm_visual->undithered_pf); 2103 XMesaSetForeground(c->display, c->xm_buffer->cleargc, c->clearpixel); 2104 } 2105 2106 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 2107 c->xm_buffer->wasCurrent = GL_TRUE; 2108 } 2109 else { 2110 /* Detach */ 2111 _mesa_make_current2( NULL, NULL, NULL ); 2112 } 2113 return GL_TRUE; 2114} 2115 2116 2117/* 2118 * Unbind the context c from its buffer. 2119 */ 2120GLboolean XMesaUnbindContext( XMesaContext c ) 2121{ 2122 /* A no-op for XFree86 integration purposes */ 2123 return GL_TRUE; 2124} 2125 2126 2127XMesaContext XMesaGetCurrentContext( void ) 2128{ 2129 GET_CURRENT_CONTEXT(ctx); 2130 if (ctx) { 2131 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2132 return xmesa; 2133 } 2134 else { 2135 return 0; 2136 } 2137} 2138 2139 2140XMesaBuffer XMesaGetCurrentBuffer( void ) 2141{ 2142 GET_CURRENT_CONTEXT(ctx); 2143 if (ctx) { 2144 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2145 return xmesa->xm_buffer; 2146 } 2147 else { 2148 return 0; 2149 } 2150} 2151 2152 2153/* New in Mesa 3.1 */ 2154XMesaBuffer XMesaGetCurrentReadBuffer( void ) 2155{ 2156 GET_CURRENT_CONTEXT(ctx); 2157 if (ctx) { 2158 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2159 return xmesa->xm_buffer; 2160 } 2161 else { 2162 return 0; 2163 } 2164} 2165 2166 2167GLboolean XMesaForceCurrent(XMesaContext c) 2168{ 2169 if (c) { 2170 if (c->gl_ctx != _mesa_get_current_context()) { 2171 _mesa_make_current(c->gl_ctx, c->xm_buffer->gl_buffer); 2172 } 2173 } 2174 else { 2175 _mesa_make_current(NULL, NULL); 2176 } 2177 return GL_TRUE; 2178} 2179 2180 2181GLboolean XMesaLoseCurrent(XMesaContext c) 2182{ 2183 (void) c; 2184 _mesa_make_current(NULL, NULL); 2185 return GL_TRUE; 2186} 2187 2188 2189/* 2190 * Switch 3Dfx support hack between window and full-screen mode. 2191 */ 2192GLboolean XMesaSetFXmode( GLint mode ) 2193{ 2194#ifdef FX 2195 const char *fx = getenv("MESA_GLX_FX"); 2196 if (fx && fx[0] != 'd') { 2197 GET_CURRENT_CONTEXT(ctx); 2198 GrHwConfiguration hw; 2199 if (!FX_grSstQueryHardware(&hw)) { 2200 /*fprintf(stderr, "!grSstQueryHardware\n");*/ 2201 return GL_FALSE; 2202 } 2203 if (hw.num_sst < 1) { 2204 /*fprintf(stderr, "hw.num_sst < 1\n");*/ 2205 return GL_FALSE; 2206 } 2207 if (ctx) { 2208 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 2209 if (mode == XMESA_FX_WINDOW) { 2210 if (xmesa->xm_buffer->FXisHackUsable) { 2211 FX_grSstControl(GR_CONTROL_DEACTIVATE); 2212 xmesa->xm_buffer->FXwindowHack = GL_TRUE; 2213 return GL_TRUE; 2214 } 2215 } 2216 else if (mode == XMESA_FX_FULLSCREEN) { 2217 FX_grSstControl(GR_CONTROL_ACTIVATE); 2218 xmesa->xm_buffer->FXwindowHack = GL_FALSE; 2219 return GL_TRUE; 2220 } 2221 else { 2222 /* Error: Bad mode value */ 2223 } 2224 } 2225 } 2226 /*fprintf(stderr, "fallthrough\n");*/ 2227#else 2228 (void) mode; 2229#endif 2230 return GL_FALSE; 2231} 2232 2233 2234 2235#ifdef FX 2236/* 2237 * Read image from VooDoo frame buffer into X/Mesa's back XImage. 2238 */ 2239static void FXgetImage( XMesaBuffer b ) 2240{ 2241 static unsigned short pixbuf[MAX_WIDTH]; 2242 int x, y; 2243 XMesaWindow root; 2244 unsigned int bw, depth, width, height; 2245 XMesaContext xmesa = (XMesaContext) b->xm_context->gl_ctx->DriverCtx; 2246 2247 assert(xmesa->xm_buffer->FXctx); 2248 2249#ifdef XFree86Server 2250 x = b->frontbuffer->x; 2251 y = b->frontbuffer->y; 2252 width = b->frontbuffer->width; 2253 height = b->frontbuffer->height; 2254 depth = b->frontbuffer->depth; 2255#else 2256 XGetGeometry( xmesa->xm_visual->display, b->frontbuffer, 2257 &root, &x, &y, &width, &height, &bw, &depth); 2258#endif 2259 if (b->width != width || b->height != height) { 2260 b->width = MIN2((int)width, xmesa->xm_buffer->FXctx->width); 2261 b->height = MIN2((int)height, xmesa->xm_buffer->FXctx->height); 2262 if (b->width & 1) 2263 b->width--; /* prevent odd width */ 2264 xmesa_alloc_back_buffer( b ); 2265 } 2266 2267 grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); 2268 if (xmesa->xm_visual->undithered_pf==PF_5R6G5B) { 2269 /* Special case: 16bpp RGB */ 2270 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ 2271 0, xmesa->xm_buffer->FXctx->height - b->height, /*pos*/ 2272 b->width, b->height, /* size */ 2273 b->width * sizeof(GLushort), /* stride */ 2274 b->backimage->data); /* dest buffer */ 2275 } 2276 else if (xmesa->xm_visual->dithered_pf==PF_DITHER 2277 && GET_VISUAL_DEPTH(xmesa->xm_visual)==8) { 2278 /* Special case: 8bpp RGB */ 2279 for (y=0;y<b->height;y++) { 2280 GLubyte *ptr = (GLubyte*) xmesa->xm_buffer->backimage->data 2281 + xmesa->xm_buffer->backimage->bytes_per_line * y; 2282 XDITHER_SETUP(y); 2283 2284 /* read row from 3Dfx frame buffer */ 2285 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2286 0, xmesa->xm_buffer->FXctx->height-(b->height-y), 2287 b->width, 1, 2288 0, 2289 pixbuf ); 2290 2291 /* write to XImage back buffer */ 2292 for (x=0;x<b->width;x++) { 2293 GLubyte r = (pixbuf[x] & 0xf800) >> 8; 2294 GLubyte g = (pixbuf[x] & 0x07e0) >> 3; 2295 GLubyte b = (pixbuf[x] & 0x001f) << 3; 2296 *ptr++ = XDITHER( x, r, g, b); 2297 } 2298 } 2299 } 2300 else { 2301 /* General case: slow! */ 2302 for (y=0;y<b->height;y++) { 2303 /* read row from 3Dfx frame buffer */ 2304 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2305 0, xmesa->xm_buffer->FXctx->height-(b->height-y), 2306 b->width, 1, 2307 0, 2308 pixbuf ); 2309 2310 /* write to XImage back buffer */ 2311 for (x=0;x<b->width;x++) { 2312 XMesaPutPixel(b->backimage,x,y, 2313 xmesa_color_to_pixel(xmesa, 2314 (pixbuf[x] & 0xf800) >> 8, 2315 (pixbuf[x] & 0x07e0) >> 3, 2316 (pixbuf[x] & 0x001f) << 3, 2317 0xff, xmesa->pixelformat)); 2318 } 2319 } 2320 } 2321 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); 2322} 2323#endif 2324 2325 2326/* 2327 * Copy the back buffer to the front buffer. If there's no back buffer 2328 * this is a no-op. 2329 */ 2330void XMesaSwapBuffers( XMesaBuffer b ) 2331{ 2332 GET_CURRENT_CONTEXT(ctx); 2333 2334 /* If we're swapping the buffer associated with the current context 2335 * we have to flush any pending rendering commands first. 2336 */ 2337 if (b->xm_context && b->xm_context->gl_ctx == ctx) 2338 _mesa_swapbuffers(ctx); 2339 2340 if (b->db_state) { 2341#ifdef FX 2342 if (b->FXctx) { 2343 fxMesaSwapBuffers(); 2344 2345 if (b->FXwindowHack) 2346 FXgetImage(b); 2347 else 2348 return; 2349 } 2350#endif 2351 if (b->backimage) { 2352 /* Copy Ximage from host's memory to server's window */ 2353#if defined(USE_XSHM) && !defined(XFree86Server) 2354 if (b->shm) { 2355 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2356 XShmPutImage( b->xm_visual->display, b->frontbuffer, 2357 b->cleargc, 2358 b->backimage, 0, 0, 2359 0, 0, b->width, b->height, False ); 2360 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2361 } 2362 else 2363#endif 2364 { 2365#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server) 2366 XMesaDriSwapBuffers( b ); 2367#else 2368 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2369 XMesaPutImage( b->xm_visual->display, b->frontbuffer, 2370 b->cleargc, 2371 b->backimage, 0, 0, 2372 0, 0, b->width, b->height ); 2373 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2374#endif 2375 } 2376 } 2377 else { 2378 /* Copy pixmap to window on server */ 2379 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2380 XMesaCopyArea( b->xm_visual->display, 2381 b->backpixmap, /* source drawable */ 2382 b->frontbuffer, /* dest. drawable */ 2383 b->cleargc, 2384 0, 0, b->width, b->height, /* source region */ 2385 0, 0 /* dest region */ 2386 ); 2387 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2388 } 2389 } 2390#if !defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server) 2391 XSync( b->xm_visual->display, False ); 2392#endif 2393} 2394 2395 2396 2397/* 2398 * Copy sub-region of back buffer to front buffer 2399 */ 2400void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 2401{ 2402 GET_CURRENT_CONTEXT(ctx); 2403 2404 /* If we're swapping the buffer associated with the current context 2405 * we have to flush any pending rendering commands first. 2406 */ 2407 if (b->xm_context->gl_ctx == ctx) 2408 _mesa_swapbuffers(ctx); 2409 2410 if (b->db_state) { 2411 int yTop = b->bottom - y - height; 2412#ifdef FX 2413 if (b->FXctx) { 2414 fxMesaSwapBuffers(); 2415 if (b->FXwindowHack) 2416 FXgetImage(b); 2417 else 2418 return; 2419 } 2420#endif 2421 if (b->backimage) { 2422 /* Copy Ximage from host's memory to server's window */ 2423#if defined(USE_XSHM) && !defined(XFree86Server) 2424 if (b->shm) { 2425 /* XXX assuming width and height aren't too large! */ 2426 XShmPutImage( b->xm_visual->display, b->frontbuffer, 2427 b->cleargc, 2428 b->backimage, x, yTop, 2429 x, yTop, width, height, False ); 2430 /* wait for finished event??? */ 2431 } 2432 else 2433#endif 2434 { 2435 /* XXX assuming width and height aren't too large! */ 2436 XMesaPutImage( b->xm_visual->display, b->frontbuffer, 2437 b->cleargc, 2438 b->backimage, x, yTop, 2439 x, yTop, width, height ); 2440 } 2441 } 2442 else { 2443 /* Copy pixmap to window on server */ 2444 XMesaCopyArea( b->xm_visual->display, 2445 b->backpixmap, /* source drawable */ 2446 b->frontbuffer, /* dest. drawable */ 2447 b->cleargc, 2448 x, yTop, width, height, /* source region */ 2449 x, yTop /* dest region */ 2450 ); 2451 } 2452 } 2453} 2454 2455 2456/* 2457 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function 2458 * is a way to get "under the hood" of X/Mesa so one can manipulate the 2459 * back buffer directly. 2460 * Output: pixmap - pointer to back buffer's Pixmap, or 0 2461 * ximage - pointer to back buffer's XImage, or NULL 2462 * Return: GL_TRUE = context is double buffered 2463 * GL_FALSE = context is single buffered 2464 */ 2465GLboolean XMesaGetBackBuffer( XMesaBuffer b, 2466 XMesaPixmap *pixmap, 2467 XMesaImage **ximage ) 2468{ 2469 if (b->db_state) { 2470 if (pixmap) *pixmap = b->backpixmap; 2471 if (ximage) *ximage = b->backimage; 2472 return GL_TRUE; 2473 } 2474 else { 2475 *pixmap = 0; 2476 *ximage = NULL; 2477 return GL_FALSE; 2478 } 2479} 2480 2481 2482/* 2483 * Return the depth buffer associated with an XMesaBuffer. 2484 * Input: b - the XMesa buffer handle 2485 * Output: width, height - size of buffer in pixels 2486 * bytesPerValue - bytes per depth value (2 or 4) 2487 * buffer - pointer to depth buffer values 2488 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 2489 */ 2490GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, 2491 GLint *bytesPerValue, void **buffer ) 2492{ 2493 if ((!b->gl_buffer) || (!b->gl_buffer->DepthBuffer)) { 2494 *width = 0; 2495 *height = 0; 2496 *bytesPerValue = 0; 2497 *buffer = 0; 2498 return GL_FALSE; 2499 } 2500 else { 2501 *width = b->gl_buffer->Width; 2502 *height = b->gl_buffer->Height; 2503 *bytesPerValue = sizeof(GLdepth); 2504 *buffer = b->gl_buffer->DepthBuffer; 2505 return GL_TRUE; 2506 } 2507} 2508 2509 2510void XMesaFlush( XMesaContext c ) 2511{ 2512 if (c && c->xm_visual) { 2513#ifdef XFree86Server 2514 /* NOT_NEEDED */ 2515#else 2516 XSync( c->xm_visual->display, False ); 2517#endif 2518 } 2519} 2520 2521 2522 2523const char *XMesaGetString( XMesaContext c, int name ) 2524{ 2525 (void) c; 2526 if (name==XMESA_VERSION) { 2527 return "3.1"; 2528 } 2529 else if (name==XMESA_EXTENSIONS) { 2530 return ""; 2531 } 2532 else { 2533 return NULL; 2534 } 2535} 2536 2537 2538 2539XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) 2540{ 2541 XMesaBuffer b; 2542 for (b=XMesaBufferList; b; b=b->Next) { 2543 if (b->frontbuffer==d && b->display==dpy) { 2544 return b; 2545 } 2546 } 2547 return NULL; 2548} 2549 2550 2551 2552/* 2553 * Look for XMesaBuffers whose X window has been destroyed. 2554 * Deallocate any such XMesaBuffers. 2555 */ 2556void XMesaGarbageCollect( void ) 2557{ 2558 XMesaBuffer b, next; 2559 for (b=XMesaBufferList; b; b=next) { 2560 next = b->Next; 2561 if (!b->pixmap_flag) { 2562#ifdef XFree86Server 2563 /* NOT_NEEDED */ 2564#else 2565 XSync(b->display, False); 2566 if (!window_exists( b->display, b->frontbuffer )) { 2567 /* found a dead window, free the ancillary info */ 2568 XMesaDestroyBuffer( b ); 2569 } 2570#endif 2571 } 2572 } 2573} 2574 2575 2576void XMesaReset( void ) 2577{ 2578 while (XMesaBufferList) 2579 XMesaDestroyBuffer(XMesaBufferList); 2580 2581 XMesaBufferList = NULL; 2582} 2583 2584 2585unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, 2586 GLfloat red, GLfloat green, 2587 GLfloat blue, GLfloat alpha ) 2588{ 2589 GLint r = (GLint) (red * 255.0F); 2590 GLint g = (GLint) (green * 255.0F); 2591 GLint b = (GLint) (blue * 255.0F); 2592 GLint a = (GLint) (alpha * 255.0F); 2593 2594 switch (xmesa->pixelformat) { 2595 case PF_INDEX: 2596 return 0; 2597 case PF_TRUECOLOR: 2598 { 2599 unsigned long p; 2600 PACK_TRUECOLOR( p, r, g, b ); 2601 return p; 2602 } 2603 case PF_8A8B8G8R: 2604 return PACK_8A8B8G8R( r, g, b, a ); 2605 case PF_8R8G8B: 2606 return PACK_8R8G8B( r, g, b ); 2607 case PF_5R6G5B: 2608 return PACK_5R6G5B( r, g, b ); 2609 case PF_DITHER: 2610 { 2611 DITHER_SETUP; 2612 return DITHER( x, y, r, g, b ); 2613 } 2614 case PF_1BIT: 2615 /* 382 = (3*255)/2 */ 2616 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 2617 case PF_HPCR: 2618 return DITHER_HPCR(x, y, r, g, b); 2619 case PF_LOOKUP: 2620 { 2621 LOOKUP_SETUP; 2622 return LOOKUP( r, g, b ); 2623 } 2624 case PF_GRAYSCALE: 2625 return GRAY_RGB( r, g, b ); 2626 case PF_DITHER_5R6G5B: 2627 /* fall through */ 2628 case PF_TRUEDITHER: 2629 { 2630 unsigned long p; 2631 PACK_TRUEDITHER(p, x, y, r, g, b); 2632 return p; 2633 } 2634 default: 2635 gl_problem(NULL, "Bad pixel format in XMesaDitherColor"); 2636 } 2637 return 0; 2638} 2639 2640 2641