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