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