xm_api.c revision 18a285a5e244b7405b85feb7315a30d99920ec5d
1/* $Id: xm_api.c,v 1.35 2002/03/16 00:53:15 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 "matrix.h" 73#include "mem.h" 74#include "mmath.h" 75#include "mtypes.h" 76#ifdef HAVE_CONFIG_H 77#include "conf.h" 78#endif 79#include "macros.h" 80#include "texformat.h" 81#include "texstore.h" 82#include "swrast/swrast.h" 83#include "swrast_setup/swrast_setup.h" 84#include "array_cache/acache.h" 85#include "tnl/tnl.h" 86 87#ifndef GLX_NONE_EXT 88#define GLX_NONE_EXT 0x8000 89#endif 90 91 92/* 93 * Global X driver lock 94 */ 95_glthread_Mutex _xmesa_lock; 96 97 98 99/* 100 * Lookup tables for HPCR pixel format: 101 */ 102static short hpcr_rgbTbl[3][256] = { 103{ 104 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 105 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 106 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 107 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 108 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 109 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 110 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 111 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 113128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 114144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 115160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 116176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 117192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 118208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 119224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239 120}, 121{ 122 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 123 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 124 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 125 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 126 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 127 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 128 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 129 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 130112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 131128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 132144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 133160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 134176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 135192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 136208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 137224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239 138}, 139{ 140 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 141 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 142 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 143 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 144 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 145 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 146 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, 147 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 148 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 149112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 150128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 151144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 152160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 153176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 154192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 155208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223 156} 157}; 158 159 160 161/**********************************************************************/ 162/***** X Utility Functions *****/ 163/**********************************************************************/ 164 165 166/* 167 * X/Mesa error reporting function: 168 */ 169static void error( const char *msg ) 170{ 171 (void)DitherValues; /* Muffle compiler */ 172 173 if (getenv("MESA_DEBUG")) 174 fprintf( stderr, "X/Mesa error: %s\n", msg ); 175} 176 177 178/* 179 * Return the host's byte order as LSBFirst or MSBFirst ala X. 180 */ 181#ifndef XFree86Server 182static int host_byte_order( void ) 183{ 184 int i = 1; 185 char *cptr = (char *) &i; 186 return (*cptr==1) ? LSBFirst : MSBFirst; 187} 188#endif 189 190 191/* 192 * Error handling. 193 */ 194#ifndef XFree86Server 195static int mesaXErrorFlag = 0; 196 197static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event ) 198{ 199 (void) dpy; 200 (void) event; 201 mesaXErrorFlag = 1; 202 return 0; 203} 204#endif 205 206 207/* 208 * Check if the X Shared Memory extension is available. 209 * Return: 0 = not available 210 * 1 = shared XImage support available 211 * 2 = shared Pixmap support available also 212 */ 213#ifndef XFree86Server 214static int check_for_xshm( XMesaDisplay *display ) 215{ 216#ifdef USE_XSHM 217 int major, minor, ignore; 218 Bool pixmaps; 219 220 if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { 221 if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { 222 return (pixmaps==True) ? 2 : 1; 223 } 224 else { 225 return 0; 226 } 227 } 228 else { 229 return 0; 230 } 231#else 232 /* Can't compile XSHM support */ 233 return 0; 234#endif 235} 236#endif 237 238 239/* 240 * Return the width and height of the given drawable. 241 */ 242static void get_drawable_size( XMesaDisplay *dpy, XMesaDrawable d, 243 unsigned int *width, unsigned int *height) 244{ 245#ifdef XFree86Server 246 (void) dpy; 247 *width = d->width; 248 *height = d->height; 249#else 250 Window root; 251 int x, y; 252 unsigned int bw, depth; 253 254 _glthread_LOCK_MUTEX(_xmesa_lock); 255 XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth ); 256 _glthread_UNLOCK_MUTEX(_xmesa_lock); 257#endif 258} 259 260 261/* 262 * Apply gamma correction to an intensity value in [0..max]. Return the 263 * new intensity value. 264 */ 265static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max ) 266{ 267 if (gamma == 1.0) { 268 return value; 269 } 270 else { 271 double x = (double) value / (double) max; 272 return IROUND_POS((GLfloat) max * pow(x, 1.0F/gamma)); 273 } 274} 275 276 277 278/* 279 * Return the true number of bits per pixel for XImages. 280 * For example, if we request a 24-bit deep visual we may actually need/get 281 * 32bpp XImages. This function returns the appropriate bpp. 282 * Input: dpy - the X display 283 * visinfo - desribes the visual to be used for XImages 284 * Return: true number of bits per pixel for XImages 285 */ 286#define GET_BITS_PER_PIXEL(xmv) bits_per_pixel(xmv) 287 288#ifdef XFree86Server 289 290static int bits_per_pixel( XMesaVisual xmv ) 291{ 292 XMesaVisualInfo visinfo = xmv->visinfo; 293 const int depth = visinfo->nplanes; 294 int i; 295 for (i = 0; i < screenInfo.numPixmapFormats; i++) { 296 if (screenInfo.formats[i].depth == depth) 297 return screenInfo.formats[i].bitsPerPixel; 298 } 299 return depth; /* should never get here, but this should be safe */ 300} 301 302#else 303 304static int bits_per_pixel( XMesaVisual xmv ) 305{ 306 XMesaDisplay *dpy = xmv->display; 307 XMesaVisualInfo visinfo = xmv->visinfo; 308 XMesaImage *img; 309 int bitsPerPixel; 310 /* Create a temporary XImage */ 311 img = XCreateImage( dpy, visinfo->visual, visinfo->depth, 312 ZPixmap, 0, /*format, offset*/ 313 (char*) MALLOC(8), /*data*/ 314 1, 1, /*width, height*/ 315 32, /*bitmap_pad*/ 316 0 /*bytes_per_line*/ 317 ); 318 assert(img); 319 /* grab the bits/pixel value */ 320 bitsPerPixel = img->bits_per_pixel; 321 /* free the XImage */ 322 FREE( img->data ); 323 img->data = NULL; 324 XMesaDestroyImage( img ); 325 return bitsPerPixel; 326} 327#endif 328 329 330 331/* 332 * Determine if a given X window ID is valid (window exists). 333 * Do this by calling XGetWindowAttributes() for the window and 334 * checking if we catch an X error. 335 * Input: dpy - the display 336 * win - the window to check for existance 337 * Return: GL_TRUE - window exists 338 * GL_FALSE - window doesn't exist 339 */ 340#ifndef XFree86Server 341static GLboolean WindowExistsFlag; 342 343static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr ) 344{ 345 (void) dpy; 346 if (xerr->error_code == BadWindow) { 347 WindowExistsFlag = GL_FALSE; 348 } 349 return 0; 350} 351 352static GLboolean window_exists( XMesaDisplay *dpy, Window win ) 353{ 354 XWindowAttributes wa; 355 int (*old_handler)( XMesaDisplay*, XErrorEvent* ); 356 WindowExistsFlag = GL_TRUE; 357 old_handler = XSetErrorHandler(window_exists_err_handler); 358 XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ 359 XSetErrorHandler(old_handler); 360 return WindowExistsFlag; 361} 362#endif 363 364 365 366/**********************************************************************/ 367/***** Linked list of XMesaBuffers *****/ 368/**********************************************************************/ 369 370static XMesaBuffer XMesaBufferList = NULL; 371 372 373/* Allocate a new XMesaBuffer, add to linked list */ 374static XMesaBuffer alloc_xmesa_buffer(void) 375{ 376 XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); 377 if (b) { 378 b->Next = XMesaBufferList; 379 XMesaBufferList = b; 380 } 381 return b; 382} 383 384 385/* 386 * Find an XMesaBuffer by matching X display and colormap but NOT matching 387 * the notThis buffer. 388 */ 389static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy, 390 XMesaColormap cmap, 391 XMesaBuffer notThis) 392{ 393 XMesaBuffer b; 394 for (b=XMesaBufferList; b; b=b->Next) { 395 if (b->display==dpy && b->cmap==cmap && b!=notThis) { 396 return b; 397 } 398 } 399 return NULL; 400} 401 402 403/* 404 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap 405 * entries. 406 */ 407static void free_xmesa_buffer(int client, XMesaBuffer buffer) 408{ 409 XMesaBuffer prev = NULL, b; 410 (void) client; 411 for (b=XMesaBufferList; b; b=b->Next) { 412 if (b==buffer) { 413 /* unlink bufer from list */ 414 if (prev) 415 prev->Next = buffer->Next; 416 else 417 XMesaBufferList = buffer->Next; 418 /* Check to free X colors */ 419 if (buffer->num_alloced>0) { 420 /* If no other buffer uses this X colormap then free the colors. */ 421 if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) { 422#ifdef XFree86Server 423 (void)FreeColors(buffer->cmap, client, 424 buffer->num_alloced, buffer->alloced_colors, 425 0); 426#else 427 XFreeColors(buffer->display, buffer->cmap, 428 buffer->alloced_colors, buffer->num_alloced, 0); 429#endif 430 } 431 } 432 433 _mesa_free_framebuffer_data(&buffer->mesa_buffer); 434 FREE(buffer); 435 436 return; 437 } 438 /* continue search */ 439 prev = b; 440 } 441 /* buffer not found in XMesaBufferList */ 442 _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n"); 443} 444 445 446/* Copy X color table stuff from one XMesaBuffer to another. */ 447static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src) 448{ 449 MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table)); 450 MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r)); 451 MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g)); 452 MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b)); 453 dst->num_alloced = src->num_alloced; 454 MEMCPY(dst->alloced_colors, src->alloced_colors, 455 sizeof(src->alloced_colors)); 456} 457 458 459 460/**********************************************************************/ 461/***** Misc Private Functions *****/ 462/**********************************************************************/ 463 464 465/* 466 * Return number of bits set in n. 467 */ 468static int bitcount( unsigned long n ) 469{ 470 int bits; 471 for (bits=0; n>0; n=n>>1) { 472 if (n&1) { 473 bits++; 474 } 475 } 476 return bits; 477} 478 479 480 481/* 482 * Allocate a shared memory XImage back buffer for the given XMesaBuffer. 483 * Return: GL_TRUE if success, GL_FALSE if error 484 */ 485#ifndef XFree86Server 486static GLboolean alloc_shm_back_buffer( XMesaBuffer b ) 487{ 488#ifdef USE_XSHM 489 /* 490 * We have to do a _lot_ of error checking here to be sure we can 491 * really use the XSHM extension. It seems different servers trigger 492 * errors at different points if the extension won't work. Therefore 493 * we have to be very careful... 494 */ 495 GC gc; 496 int (*old_handler)( XMesaDisplay *, XErrorEvent * ); 497 498 b->backimage = XShmCreateImage( b->xm_visual->display, 499 b->xm_visual->visinfo->visual, 500 b->xm_visual->visinfo->depth, 501 ZPixmap, NULL, &b->shminfo, 502 b->width, b->height ); 503 if (b->backimage == NULL) { 504 error("alloc_back_buffer: Shared memory error (XShmCreateImage), disabling."); 505 b->shm = 0; 506 return GL_FALSE; 507 } 508 509 b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line 510 * b->backimage->height, IPC_CREAT|0777 ); 511 if (b->shminfo.shmid < 0) { 512 if (getenv("MESA_DEBUG")) 513 perror("alloc_back_buffer"); 514 XDestroyImage( b->backimage ); 515 b->backimage = NULL; 516 error("alloc_back_buffer: Shared memory error (shmget), disabling."); 517 b->shm = 0; 518 return GL_FALSE; 519 } 520 521 b->shminfo.shmaddr = b->backimage->data 522 = (char*)shmat( b->shminfo.shmid, 0, 0 ); 523 if (b->shminfo.shmaddr == (char *) -1) { 524 if (getenv("MESA_DEBUG")) 525 perror("alloc_back_buffer"); 526 XDestroyImage( b->backimage ); 527 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); 528 b->backimage = NULL; 529 error("alloc_back_buffer: Shared memory error (shmat), disabling."); 530 b->shm = 0; 531 return GL_FALSE; 532 } 533 534 b->shminfo.readOnly = False; 535 mesaXErrorFlag = 0; 536 old_handler = XSetErrorHandler( mesaHandleXError ); 537 /* This may trigger the X protocol error we're ready to catch: */ 538 XShmAttach( b->xm_visual->display, &b->shminfo ); 539 XSync( b->xm_visual->display, False ); 540 541 if (mesaXErrorFlag) { 542 /* we are on a remote display, this error is normal, don't print it */ 543 XFlush( b->xm_visual->display ); 544 mesaXErrorFlag = 0; 545 XDestroyImage( b->backimage ); 546 shmdt( b->shminfo.shmaddr ); 547 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); 548 b->backimage = NULL; 549 b->shm = 0; 550 (void) XSetErrorHandler( old_handler ); 551 return GL_FALSE; 552 } 553 554 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */ 555 556 /* Finally, try an XShmPutImage to be really sure the extension works */ 557 gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL ); 558 XShmPutImage( b->xm_visual->display, b->frontbuffer, gc, 559 b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False ); 560 XSync( b->xm_visual->display, False ); 561 XFreeGC( b->xm_visual->display, gc ); 562 (void) XSetErrorHandler( old_handler ); 563 if (mesaXErrorFlag) { 564 XFlush( b->xm_visual->display ); 565 mesaXErrorFlag = 0; 566 XDestroyImage( b->backimage ); 567 shmdt( b->shminfo.shmaddr ); 568 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); 569 b->backimage = NULL; 570 b->shm = 0; 571 return GL_FALSE; 572 } 573 574 if (b->backimage) { 575 int height = b->backimage->height; 576 /* Needed by PIXELADDR1 macro */ 577 b->ximage_width1 = b->backimage->bytes_per_line; 578 b->ximage_origin1 = (GLubyte *) b->backimage->data 579 + b->ximage_width1 * (height-1); 580 /* Needed by PIXELADDR2 macro */ 581 b->ximage_width2 = b->backimage->bytes_per_line / 2; 582 b->ximage_origin2 = (GLushort *) b->backimage->data 583 + b->ximage_width2 * (height-1); 584 /* Needed by PIXELADDR3 macro */ 585 b->ximage_width3 = b->backimage->bytes_per_line; 586 b->ximage_origin3 = (GLubyte *) b->backimage->data 587 + b->ximage_width3 * (height-1); 588 /* Needed by PIXELADDR4 macro */ 589 b->ximage_width4 = b->backimage->width; 590 b->ximage_origin4 = (GLuint *) b->backimage->data 591 + b->ximage_width4 * (height-1); 592 } 593 594 return GL_TRUE; 595#else 596 /* Can't compile XSHM support */ 597 return GL_FALSE; 598#endif 599} 600#endif 601 602 603 604/* 605 * Setup an off-screen pixmap or Ximage to use as the back buffer. 606 * Input: b - the X/Mesa buffer 607 */ 608void xmesa_alloc_back_buffer( XMesaBuffer b ) 609{ 610 if (b->db_state==BACK_XIMAGE) { 611 /* Deallocate the old backimage, if any */ 612 if (b->backimage) { 613#if defined(USE_XSHM) && !defined(XFree86Server) 614 if (b->shm) { 615 XShmDetach( b->xm_visual->display, &b->shminfo ); 616 XDestroyImage( b->backimage ); 617 shmdt( b->shminfo.shmaddr ); 618 } 619 else 620#endif 621 XMesaDestroyImage( b->backimage ); 622 b->backimage = NULL; 623 } 624 625 /* Allocate new back buffer */ 626#ifdef XFree86Server 627 { 628 /* Allocate a regular XImage for the back buffer. */ 629 b->backimage = XMesaCreateImage(b->xm_visual->BitsPerPixel, 630 b->width, b->height, NULL); 631#else 632 if (b->shm==0 633 || alloc_shm_back_buffer(b)==GL_FALSE 634 ) { 635 /* Allocate a regular XImage for the back buffer. */ 636 b->backimage = XCreateImage( b->xm_visual->display, 637 b->xm_visual->visinfo->visual, 638 GET_VISUAL_DEPTH(b->xm_visual), 639 ZPixmap, 0, /* format, offset */ 640 NULL, b->width, b->height, 641 8, 0 ); /* pad, bytes_per_line */ 642#endif 643 if (!b->backimage) { 644 error("alloc_back_buffer: XCreateImage failed."); 645 } 646 b->backimage->data = (char *) MALLOC( b->backimage->height 647 * b->backimage->bytes_per_line ); 648 if (!b->backimage->data) { 649 error("alloc_back_buffer: MALLOC failed."); 650 XMesaDestroyImage( b->backimage ); 651 b->backimage = NULL; 652 } 653 } 654 b->backpixmap = None; 655 } 656 else if (b->db_state==BACK_PIXMAP) { 657 XMesaPixmap old_pixmap = b->backpixmap; 658 /* Free the old back pixmap */ 659 if (b->backpixmap) { 660 XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); 661 } 662 /* Allocate new back pixmap */ 663 b->backpixmap = XMesaCreatePixmap( b->xm_visual->display, b->frontbuffer, 664 b->width, b->height, 665 GET_VISUAL_DEPTH(b->xm_visual) ); 666 b->backimage = NULL; 667 /* update other references to backpixmap */ 668 if (b->buffer==(XMesaDrawable)old_pixmap) { 669 b->buffer = (XMesaDrawable)b->backpixmap; 670 } 671 } 672} 673 674 675 676/* 677 * A replacement for XAllocColor. This function should never 678 * fail to allocate a color. When XAllocColor fails, we return 679 * the nearest matching color. If we have to allocate many colors 680 * this function isn't too efficient; the XQueryColors() could be 681 * done just once. 682 * Written by Michael Pichler, Brian Paul, Mark Kilgard 683 * Input: dpy - X display 684 * cmap - X colormap 685 * cmapSize - size of colormap 686 * In/Out: color - the XColor struct 687 * Output: exact - 1=exact color match, 0=closest match 688 * alloced - 1=XAlloc worked, 0=XAlloc failed 689 */ 690static void 691noFaultXAllocColor( int client, 692 XMesaDisplay *dpy, 693 XMesaColormap cmap, 694 int cmapSize, 695 XMesaColor *color, 696 int *exact, int *alloced ) 697{ 698#ifdef XFree86Server 699 Pixel *ppixIn; 700 xrgb *ctable; 701#else 702 /* we'll try to cache ctable for better remote display performance */ 703 static Display *prevDisplay = NULL; 704 static XMesaColormap prevCmap = 0; 705 static int prevCmapSize = 0; 706 static XMesaColor *ctable = NULL; 707#endif 708 XMesaColor subColor; 709 int i, bestmatch; 710 double mindist; /* 3*2^16^2 exceeds long int precision. */ 711 712 (void) client; 713 714 /* First try just using XAllocColor. */ 715#ifdef XFree86Server 716 if (AllocColor(cmap, 717 &color->red, &color->green, &color->blue, 718 &color->pixel, 719 client) == Success) { 720#else 721 if (XAllocColor(dpy, cmap, color)) { 722#endif 723 *exact = 1; 724 *alloced = 1; 725 return; 726 } 727 728 /* Alloc failed, search for closest match */ 729 730 /* Retrieve color table entries. */ 731 /* XXX alloca candidate. */ 732#ifdef XFree86Server 733 ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel)); 734 ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb)); 735 for (i = 0; i < cmapSize; i++) { 736 ppixIn[i] = i; 737 } 738 QueryColors(cmap, cmapSize, ppixIn, ctable); 739#else 740 if (prevDisplay != dpy || prevCmap != cmap 741 || prevCmapSize != cmapSize || !ctable) { 742 /* free previously cached color table */ 743 if (ctable) 744 FREE(ctable); 745 /* Get the color table from X */ 746 ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor)); 747 assert(ctable); 748 for (i = 0; i < cmapSize; i++) { 749 ctable[i].pixel = i; 750 } 751 XQueryColors(dpy, cmap, ctable, cmapSize); 752 prevDisplay = dpy; 753 prevCmap = cmap; 754 prevCmapSize = cmapSize; 755 } 756#endif 757 758 /* Find best match. */ 759 bestmatch = -1; 760 mindist = 0.0; 761 for (i = 0; i < cmapSize; i++) { 762 double dr = 0.30 * ((double) color->red - (double) ctable[i].red); 763 double dg = 0.59 * ((double) color->green - (double) ctable[i].green); 764 double db = 0.11 * ((double) color->blue - (double) ctable[i].blue); 765 double dist = dr * dr + dg * dg + db * db; 766 if (bestmatch < 0 || dist < mindist) { 767 bestmatch = i; 768 mindist = dist; 769 } 770 } 771 772 /* Return result. */ 773 subColor.red = ctable[bestmatch].red; 774 subColor.green = ctable[bestmatch].green; 775 subColor.blue = ctable[bestmatch].blue; 776 /* Try to allocate the closest match color. This should only 777 * fail if the cell is read/write. Otherwise, we're incrementing 778 * the cell's reference count. 779 */ 780#ifdef XFree86Server 781 if (AllocColor(cmap, 782 &subColor.red, &subColor.green, &subColor.blue, 783 &subColor.pixel, 784 client) == Success) { 785#else 786 if (XAllocColor(dpy, cmap, &subColor)) { 787#endif 788 *alloced = 1; 789 } 790 else { 791 /* do this to work around a problem reported by Frank Ortega */ 792 subColor.pixel = (unsigned long) bestmatch; 793 subColor.red = ctable[bestmatch].red; 794 subColor.green = ctable[bestmatch].green; 795 subColor.blue = ctable[bestmatch].blue; 796 subColor.flags = DoRed | DoGreen | DoBlue; 797 *alloced = 0; 798 } 799#ifdef XFree86Server 800 FREE(ppixIn); 801 FREE(ctable); 802#else 803 /* don't free table, save it for next time */ 804#endif 805 806 *color = subColor; 807 *exact = 0; 808} 809 810 811 812 813/* 814 * Do setup for PF_GRAYSCALE pixel format. 815 * Note that buffer may be NULL. 816 */ 817static GLboolean setup_grayscale( int client, XMesaVisual v, 818 XMesaBuffer buffer, XMesaColormap cmap ) 819{ 820 if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { 821 return GL_FALSE; 822 } 823 824 if (buffer) { 825 XMesaBuffer prevBuffer; 826 827 if (!cmap) { 828 return GL_FALSE; 829 } 830 831 prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); 832 if (prevBuffer && 833 (buffer->xm_visual->mesa_visual.rgbMode == 834 prevBuffer->xm_visual->mesa_visual.rgbMode)) { 835 /* Copy colormap stuff from previous XMesaBuffer which uses same 836 * X colormap. Do this to avoid time spent in noFaultXAllocColor. 837 */ 838 copy_colortable_info(buffer, prevBuffer); 839 } 840 else { 841 /* Allocate 256 shades of gray */ 842 int gray; 843 int colorsfailed = 0; 844 for (gray=0;gray<256;gray++) { 845 GLint r = gamma_adjust( v->RedGamma, gray, 255 ); 846 GLint g = gamma_adjust( v->GreenGamma, gray, 255 ); 847 GLint b = gamma_adjust( v->BlueGamma, gray, 255 ); 848 int exact, alloced; 849 XMesaColor xcol; 850 xcol.red = (r << 8) | r; 851 xcol.green = (g << 8) | g; 852 xcol.blue = (b << 8) | b; 853 noFaultXAllocColor( client, v->display, 854 cmap, GET_COLORMAP_SIZE(v), 855 &xcol, &exact, &alloced ); 856 if (!exact) { 857 colorsfailed++; 858 } 859 if (alloced) { 860 assert(buffer->num_alloced<256); 861 buffer->alloced_colors[buffer->num_alloced] = xcol.pixel; 862 buffer->num_alloced++; 863 } 864 865 /*OLD 866 assert(gray < 576); 867 buffer->color_table[gray*3+0] = xcol.pixel; 868 buffer->color_table[gray*3+1] = xcol.pixel; 869 buffer->color_table[gray*3+2] = xcol.pixel; 870 assert(xcol.pixel < 65536); 871 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100; 872 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100; 873 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100; 874 */ 875 buffer->color_table[gray] = xcol.pixel; 876 assert(xcol.pixel < 65536); 877 buffer->pixel_to_r[xcol.pixel] = gray; 878 buffer->pixel_to_g[xcol.pixel] = gray; 879 buffer->pixel_to_b[xcol.pixel] = gray; 880 } 881 882 if (colorsfailed && getenv("MESA_DEBUG")) { 883 fprintf( stderr, 884 "Note: %d out of 256 needed colors do not match exactly.\n", 885 colorsfailed ); 886 } 887 } 888 } 889 890 v->dithered_pf = PF_GRAYSCALE; 891 v->undithered_pf = PF_GRAYSCALE; 892 return GL_TRUE; 893} 894 895 896 897/* 898 * Setup RGB rendering for a window with a PseudoColor, StaticColor, 899 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225 900 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB 901 * color. While this function was originally designed just for 8-bit 902 * visuals, it has also proven to work from 4-bit up to 16-bit visuals. 903 * Dithering code contributed by Bob Mercier. 904 */ 905static GLboolean setup_dithered_color( int client, XMesaVisual v, 906 XMesaBuffer buffer, XMesaColormap cmap ) 907{ 908 if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { 909 return GL_FALSE; 910 } 911 912 if (buffer) { 913 XMesaBuffer prevBuffer; 914 915 if (!cmap) { 916 return GL_FALSE; 917 } 918 919 prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); 920 if (prevBuffer && 921 (buffer->xm_visual->mesa_visual.rgbMode == 922 prevBuffer->xm_visual->mesa_visual.rgbMode)) { 923 /* Copy colormap stuff from previous, matching XMesaBuffer. 924 * Do this to avoid time spent in noFaultXAllocColor. 925 */ 926 copy_colortable_info(buffer, prevBuffer); 927 } 928 else { 929 /* Allocate X colors and initialize color_table[], red_table[], etc */ 930 int r, g, b, i; 931 int colorsfailed = 0; 932 for (r = 0; r < _R; r++) { 933 for (g = 0; g < _G; g++) { 934 for (b = 0; b < _B; b++) { 935 XMesaColor xcol; 936 int exact, alloced; 937 xcol.red =gamma_adjust(v->RedGamma, r*65535/(_R-1),65535); 938 xcol.green=gamma_adjust(v->GreenGamma, g*65535/(_G-1),65535); 939 xcol.blue =gamma_adjust(v->BlueGamma, b*65535/(_B-1),65535); 940 noFaultXAllocColor( client, v->display, 941 cmap, GET_COLORMAP_SIZE(v), 942 &xcol, &exact, &alloced ); 943 if (!exact) { 944 colorsfailed++; 945 } 946 if (alloced) { 947 assert(buffer->num_alloced<256); 948 buffer->alloced_colors[buffer->num_alloced] = xcol.pixel; 949 buffer->num_alloced++; 950 } 951 i = _MIX( r, g, b ); 952 assert(i < 576); 953 buffer->color_table[i] = xcol.pixel; 954 assert(xcol.pixel < 65536); 955 buffer->pixel_to_r[xcol.pixel] = r * 255 / (_R-1); 956 buffer->pixel_to_g[xcol.pixel] = g * 255 / (_G-1); 957 buffer->pixel_to_b[xcol.pixel] = b * 255 / (_B-1); 958 } 959 } 960 } 961 962 if (colorsfailed && getenv("MESA_DEBUG")) { 963 fprintf( stderr, 964 "Note: %d out of %d needed colors do not match exactly.\n", 965 colorsfailed, _R*_G*_B ); 966 } 967 } 968 } 969 970 v->dithered_pf = PF_DITHER; 971 v->undithered_pf = PF_LOOKUP; 972 return GL_TRUE; 973} 974 975 976/* 977 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode. 978 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer. 979 * Special dithering tables have to be initialized. 980 */ 981static void setup_8bit_hpcr( XMesaVisual v ) 982{ 983 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be) 984 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined 985 * on the root window AND the colormap obtainable by XGetRGBColormaps 986 * for that atom must be set on the window. (see also tkInitWindow) 987 * If that colormap is not set, the output will look stripy. 988 */ 989 990 /* Setup color tables with gamma correction */ 991 int i; 992 double g; 993 994 g = 1.0 / v->RedGamma; 995 for (i=0; i<256; i++) { 996 GLint red = IROUND_POS(255.0 * pow( hpcr_rgbTbl[0][i]/255.0, g )); 997 v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 ); 998 } 999 1000 g = 1.0 / v->GreenGamma; 1001 for (i=0; i<256; i++) { 1002 GLint green = IROUND_POS(255.0 * pow( hpcr_rgbTbl[1][i]/255.0, g )); 1003 v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 ); 1004 } 1005 1006 g = 1.0 / v->BlueGamma; 1007 for (i=0; i<256; i++) { 1008 GLint blue = IROUND_POS(255.0 * pow( hpcr_rgbTbl[2][i]/255.0, g )); 1009 v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 ); 1010 } 1011 v->undithered_pf = PF_HPCR; /* can't really disable dithering for now */ 1012 v->dithered_pf = PF_HPCR; 1013 1014 /* which method should I use to clear */ 1015 /* GL_FALSE: keep the ordinary method */ 1016 /* GL_TRUE : clear with dither pattern */ 1017 v->hpcr_clear_flag = getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE; 1018 1019 if (v->hpcr_clear_flag) { 1020 v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display, 1021 DefaultRootWindow(v->display), 1022 16, 2, 8); 1023#ifndef XFree86Server 1024 v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap, 1025 0, 0, 16, 2, AllPlanes, ZPixmap); 1026#endif 1027 } 1028} 1029 1030 1031/* 1032 * Setup RGB rendering for a window with a True/DirectColor visual. 1033 */ 1034static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer, 1035 XMesaColormap cmap ) 1036{ 1037 unsigned long rmask, gmask, bmask; 1038 (void) buffer; 1039 (void) cmap; 1040 1041 /* Compute red multiplier (mask) and bit shift */ 1042 v->rshift = 0; 1043 rmask = GET_REDMASK(v); 1044 while ((rmask & 1)==0) { 1045 v->rshift++; 1046 rmask = rmask >> 1; 1047 } 1048 1049 /* Compute green multiplier (mask) and bit shift */ 1050 v->gshift = 0; 1051 gmask = GET_GREENMASK(v); 1052 while ((gmask & 1)==0) { 1053 v->gshift++; 1054 gmask = gmask >> 1; 1055 } 1056 1057 /* Compute blue multiplier (mask) and bit shift */ 1058 v->bshift = 0; 1059 bmask = GET_BLUEMASK(v); 1060 while ((bmask & 1)==0) { 1061 v->bshift++; 1062 bmask = bmask >> 1; 1063 } 1064 1065 /* 1066 * Compute component-to-pixel lookup tables and dithering kernel 1067 */ 1068 { 1069 static GLubyte kernel[16] = { 1070 0*16, 8*16, 2*16, 10*16, 1071 12*16, 4*16, 14*16, 6*16, 1072 3*16, 11*16, 1*16, 9*16, 1073 15*16, 7*16, 13*16, 5*16, 1074 }; 1075 GLint rBits = bitcount(rmask); 1076 GLint gBits = bitcount(gmask); 1077 GLint bBits = bitcount(bmask); 1078 GLint maxBits; 1079 GLuint i; 1080 1081 /* convert pixel components in [0,_mask] to RGB values in [0,255] */ 1082 for (i=0; i<=rmask; i++) 1083 v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); 1084 for (i=0; i<=gmask; i++) 1085 v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); 1086 for (i=0; i<=bmask; i++) 1087 v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); 1088 1089 /* convert RGB values from [0,255] to pixel components */ 1090 1091 for (i=0;i<256;i++) { 1092 GLint r = gamma_adjust(v->RedGamma, i, 255); 1093 GLint g = gamma_adjust(v->GreenGamma, i, 255); 1094 GLint b = gamma_adjust(v->BlueGamma, i, 255); 1095 v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; 1096 v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; 1097 v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; 1098 } 1099 /* overflow protection */ 1100 for (i=256;i<512;i++) { 1101 v->RtoPixel[i] = v->RtoPixel[255]; 1102 v->GtoPixel[i] = v->GtoPixel[255]; 1103 v->BtoPixel[i] = v->BtoPixel[255]; 1104 } 1105 1106 /* setup dithering kernel */ 1107 maxBits = rBits; 1108 if (gBits > maxBits) maxBits = gBits; 1109 if (bBits > maxBits) maxBits = bBits; 1110 for (i=0;i<16;i++) { 1111 v->Kernel[i] = kernel[i] >> maxBits; 1112 } 1113 1114 v->undithered_pf = PF_TRUECOLOR; 1115 v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_TRUEDITHER : PF_TRUECOLOR; 1116 } 1117 1118 /* 1119 * Now check for TrueColor visuals which we can optimize. 1120 */ 1121 if ( GET_REDMASK(v) ==0x0000ff 1122 && GET_GREENMASK(v)==0x00ff00 1123 && GET_BLUEMASK(v) ==0xff0000 1124 && CHECK_BYTE_ORDER(v) 1125 && v->BitsPerPixel==32 1126 && sizeof(GLuint)==4 1127 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 1128 /* common 32 bpp config used on SGI, Sun */ 1129 v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; 1130 } 1131 else if (GET_REDMASK(v) ==0xff0000 1132 && GET_GREENMASK(v)==0x00ff00 1133 && GET_BLUEMASK(v) ==0x0000ff 1134 && CHECK_BYTE_ORDER(v) 1135 && v->BitsPerPixel==32 1136 && sizeof(GLuint)==4 1137 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 1138 /* common 32 bpp config used on Linux, HP, IBM */ 1139 v->undithered_pf = v->dithered_pf = PF_8R8G8B; 1140 } 1141 else if (GET_REDMASK(v) ==0xff0000 1142 && GET_GREENMASK(v)==0x00ff00 1143 && GET_BLUEMASK(v) ==0x0000ff 1144 && CHECK_BYTE_ORDER(v) 1145 && v->BitsPerPixel==24 1146 && sizeof(GLuint)==4 1147 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 1148 /* common packed 24 bpp config used on Linux */ 1149 v->undithered_pf = v->dithered_pf = PF_8R8G8B24; 1150 } 1151 else if (GET_REDMASK(v) ==0xf800 1152 && GET_GREENMASK(v)==0x07e0 1153 && GET_BLUEMASK(v) ==0x001f 1154 && CHECK_BYTE_ORDER(v) 1155 && v->BitsPerPixel==16 1156 && sizeof(GLushort)==2 1157 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 1158 /* 5-6-5 color weight on common PC VGA boards */ 1159 v->undithered_pf = PF_5R6G5B; 1160 v->dithered_pf = PF_DITHER_5R6G5B; 1161 } 1162 else if (GET_REDMASK(v) ==0xe0 1163 && GET_GREENMASK(v)==0x1c 1164 && GET_BLUEMASK(v) ==0x03 1165 && CHECK_FOR_HPCR(v)) { 1166 setup_8bit_hpcr( v ); 1167 } 1168} 1169 1170 1171 1172/* 1173 * Setup RGB rendering for a window with a monochrome visual. 1174 */ 1175static void setup_monochrome( XMesaVisual v, XMesaBuffer b ) 1176{ 1177 (void) b; 1178 v->dithered_pf = v->undithered_pf = PF_1BIT; 1179 /* if black=1 then we must flip pixel values */ 1180 v->bitFlip = (GET_BLACK_PIXEL(v) != 0); 1181} 1182 1183 1184 1185/* 1186 * When a context is "made current" for the first time, we can finally 1187 * finish initializing the context's visual and buffer information. 1188 * Input: v - the XMesaVisual to initialize 1189 * b - the XMesaBuffer to initialize (may be NULL) 1190 * rgb_flag - TRUE = RGBA mode, FALSE = color index mode 1191 * window - the window/pixmap we're rendering into 1192 * cmap - the colormap associated with the window/pixmap 1193 * Return: GL_TRUE=success, GL_FALSE=failure 1194 */ 1195static GLboolean initialize_visual_and_buffer( int client, 1196 XMesaVisual v, 1197 XMesaBuffer b, 1198 GLboolean rgb_flag, 1199 XMesaDrawable window, 1200 XMesaColormap cmap 1201 ) 1202{ 1203#ifndef XFree86Server 1204 XGCValues gcvalues; 1205#endif 1206 1207 if (b) { 1208 assert(b->xm_visual == v); 1209 } 1210 1211 /* Save true bits/pixel */ 1212 v->BitsPerPixel = GET_BITS_PER_PIXEL(v); 1213 assert(v->BitsPerPixel > 0); 1214 1215 1216 if (rgb_flag==GL_FALSE) { 1217 /* COLOR-INDEXED WINDOW: 1218 * Even if the visual is TrueColor or DirectColor we treat it as 1219 * being color indexed. This is weird but might be useful to someone. 1220 */ 1221 v->dithered_pf = v->undithered_pf = PF_INDEX; 1222 v->index_bits = GET_VISUAL_DEPTH(v); 1223 } 1224 else { 1225 /* RGB WINDOW: 1226 * We support RGB rendering into almost any kind of visual. 1227 */ 1228 int xclass; 1229 xclass = GET_VISUAL_CLASS(v); 1230 if (xclass==TrueColor || xclass==DirectColor) { 1231 setup_truecolor( v, b, cmap ); 1232 } 1233 else if (xclass==StaticGray && GET_VISUAL_DEPTH(v)==1) { 1234 setup_monochrome( v, b ); 1235 } 1236 else if (xclass==GrayScale || xclass==StaticGray) { 1237 if (!setup_grayscale( client, v, b, cmap )) { 1238 return GL_FALSE; 1239 } 1240 } 1241 else if ((xclass==PseudoColor || xclass==StaticColor) 1242 && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) { 1243 if (!setup_dithered_color( client, v, b, cmap )) { 1244 return GL_FALSE; 1245 } 1246 } 1247 else { 1248 error("XMesa: RGB mode rendering not supported in given visual."); 1249 return GL_FALSE; 1250 } 1251 v->index_bits = 0; 1252 1253 if (getenv("MESA_NO_DITHER")) { 1254 v->dithered_pf = v->undithered_pf; 1255 } 1256 } 1257 1258 1259 /* 1260 * If MESA_INFO env var is set print out some debugging info 1261 * which can help Brian figure out what's going on when a user 1262 * reports bugs. 1263 */ 1264 if (getenv("MESA_INFO")) { 1265 fprintf(stderr, "X/Mesa visual = %p\n", (void *) v); 1266 fprintf(stderr, "X/Mesa dithered pf = %u\n", v->dithered_pf); 1267 fprintf(stderr, "X/Mesa undithered pf = %u\n", v->undithered_pf); 1268 fprintf(stderr, "X/Mesa level = %d\n", v->level); 1269 fprintf(stderr, "X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); 1270 fprintf(stderr, "X/Mesa bits per pixel = %d\n", v->BitsPerPixel); 1271 } 1272 1273 if (b && window) { 1274 /* Do window-specific initializations */ 1275 1276 /* Window dimensions */ 1277 unsigned int w, h; 1278 get_drawable_size( v->display, window, &w, &h ); 1279 b->width = w; 1280 b->height = h; 1281 1282 b->frontbuffer = window; 1283 1284 /* Setup for single/double buffering */ 1285 if (v->mesa_visual.doubleBufferMode) { 1286 /* Double buffered */ 1287#ifndef XFree86Server 1288 b->shm = check_for_xshm( v->display ); 1289#endif 1290 xmesa_alloc_back_buffer( b ); 1291 if (b->db_state==BACK_PIXMAP) { 1292 b->buffer = (XMesaDrawable)b->backpixmap; 1293 } 1294 else { 1295 b->buffer = XIMAGE; 1296 } 1297 } 1298 else { 1299 /* Single Buffered */ 1300 b->buffer = b->frontbuffer; 1301 } 1302 1303 /* X11 graphics contexts */ 1304#ifdef XFree86Server 1305 b->gc = CreateScratchGC(v->display, window->depth); 1306#else 1307 b->gc = XCreateGC( v->display, window, 0, NULL ); 1308#endif 1309 XMesaSetFunction( v->display, b->gc, GXcopy ); 1310 1311 /* cleargc - for glClear() */ 1312#ifdef XFree86Server 1313 b->cleargc = CreateScratchGC(v->display, window->depth); 1314#else 1315 b->cleargc = XCreateGC( v->display, window, 0, NULL ); 1316#endif 1317 XMesaSetFunction( v->display, b->cleargc, GXcopy ); 1318 1319 /* 1320 * Don't generate Graphics Expose/NoExpose events in swapbuffers(). 1321 * Patch contributed by Michael Pichler May 15, 1995. 1322 */ 1323#ifdef XFree86Server 1324 b->swapgc = CreateScratchGC(v->display, window->depth); 1325 { 1326 CARD32 v[1]; 1327 v[0] = FALSE; 1328 dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL); 1329 } 1330#else 1331 gcvalues.graphics_exposures = False; 1332 b->swapgc = XCreateGC( v->display, window, 1333 GCGraphicsExposures, &gcvalues); 1334#endif 1335 XMesaSetFunction( v->display, b->swapgc, GXcopy ); 1336 /* 1337 * Set fill style and tile pixmap once for all for HPCR stuff 1338 * (instead of doing it each time in clear_color_HPCR_pixmap()) 1339 * Initialize whole stuff 1340 * Patch contributed by Jacques Leroy March 8, 1998. 1341 */ 1342 if (v->hpcr_clear_flag && b->buffer!=XIMAGE) { 1343 int i; 1344 for (i=0; i<16; i++) 1345 { 1346 XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0); 1347 XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0); 1348 } 1349 XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap, 1350 b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); 1351 XMesaSetFillStyle( v->display, b->cleargc, FillTiled); 1352 XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap ); 1353 } 1354 1355 /* Initialize the row buffer XImage for use in write_color_span() */ 1356#ifdef XFree86Server 1357 b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, 1358 (char *)MALLOC(MAX_WIDTH*4)); 1359#else 1360 b->rowimage = XCreateImage( v->display, 1361 v->visinfo->visual, 1362 v->visinfo->depth, 1363 ZPixmap, 0, /*format, offset*/ 1364 (char*) MALLOC(MAX_WIDTH*4), /*data*/ 1365 MAX_WIDTH, 1, /*width, height*/ 1366 32, /*bitmap_pad*/ 1367 0 /*bytes_per_line*/ ); 1368#endif 1369 } 1370 1371 return GL_TRUE; 1372} 1373 1374 1375 1376/* 1377 * Convert an RGBA color to a pixel value. 1378 */ 1379unsigned long 1380xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a, 1381 GLuint pixelFormat) 1382{ 1383 switch (pixelFormat) { 1384 case PF_INDEX: 1385 return 0; 1386 case PF_TRUECOLOR: 1387 { 1388 unsigned long p; 1389 PACK_TRUECOLOR( p, r, g, b ); 1390 return p; 1391 } 1392 case PF_8A8B8G8R: 1393 return PACK_8A8B8G8R( r, g, b, a ); 1394 case PF_8R8G8B: 1395 /* fall through */ 1396 case PF_8R8G8B24: 1397 return PACK_8R8G8B( r, g, b ); 1398 case PF_5R6G5B: 1399 return PACK_5R6G5B( r, g, b ); 1400 case PF_DITHER: 1401 { 1402 DITHER_SETUP; 1403 return DITHER( 1, 0, r, g, b ); 1404 } 1405 case PF_1BIT: 1406 /* 382 = (3*255)/2 */ 1407 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 1408 case PF_HPCR: 1409 return DITHER_HPCR(1, 1, r, g, b); 1410 case PF_LOOKUP: 1411 { 1412 LOOKUP_SETUP; 1413 return LOOKUP( r, g, b ); 1414 } 1415 case PF_GRAYSCALE: 1416 return GRAY_RGB( r, g, b ); 1417 case PF_TRUEDITHER: 1418 /* fall through */ 1419 case PF_DITHER_5R6G5B: 1420 { 1421 unsigned long p; 1422 PACK_TRUEDITHER(p, 1, 0, r, g, b); 1423 return p; 1424 } 1425 default: 1426 _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel"); 1427 } 1428 return 0; 1429} 1430 1431 1432/**********************************************************************/ 1433/***** Public Functions *****/ 1434/**********************************************************************/ 1435 1436 1437/* 1438 * Create a new X/Mesa visual. 1439 * Input: display - X11 display 1440 * visinfo - an XVisualInfo pointer 1441 * rgb_flag - GL_TRUE = RGB mode, 1442 * GL_FALSE = color index mode 1443 * alpha_flag - alpha buffer requested? 1444 * db_flag - GL_TRUE = double-buffered, 1445 * GL_FALSE = single buffered 1446 * stereo_flag - stereo visual? 1447 * ximage_flag - GL_TRUE = use an XImage for back buffer, 1448 * GL_FALSE = use an off-screen pixmap for back buffer 1449 * depth_size - requested bits/depth values, or zero 1450 * stencil_size - requested bits/stencil values, or zero 1451 * accum_red_size - requested bits/red accum values, or zero 1452 * accum_green_size - requested bits/green accum values, or zero 1453 * accum_blue_size - requested bits/blue accum values, or zero 1454 * accum_alpha_size - requested bits/alpha accum values, or zero 1455 * num_samples - number of samples/pixel if multisampling, or zero 1456 * level - visual level, usually 0 1457 * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT 1458 * Return; a new XMesaVisual or 0 if error. 1459 */ 1460XMesaVisual XMesaCreateVisual( XMesaDisplay *display, 1461 XMesaVisualInfo visinfo, 1462 GLboolean rgb_flag, 1463 GLboolean alpha_flag, 1464 GLboolean db_flag, 1465 GLboolean stereo_flag, 1466 GLboolean ximage_flag, 1467 GLint depth_size, 1468 GLint stencil_size, 1469 GLint accum_red_size, 1470 GLint accum_green_size, 1471 GLint accum_blue_size, 1472 GLint accum_alpha_size, 1473 GLint num_samples, 1474 GLint level, 1475 GLint visualCaveat ) 1476{ 1477 char *gamma; 1478 XMesaVisual v; 1479 GLint red_bits, green_bits, blue_bits, alpha_bits; 1480 1481 /* For debugging only */ 1482 if (getenv("MESA_XSYNC")) { 1483 /* This makes debugging X easier. 1484 * In your debugger, set a breakpoint on _XError to stop when an 1485 * X protocol error is generated. 1486 */ 1487#ifdef XFree86Server 1488 /* NOT_NEEDED */ 1489#else 1490 XSynchronize( display, 1 ); 1491#endif 1492 } 1493 1494 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); 1495 if (!v) { 1496 return NULL; 1497 } 1498 1499 /* 1500 * In the X server, NULL is passed in for the display. It will have 1501 * to be set before using this visual. See XMesaSetVisualDisplay() 1502 * below. 1503 */ 1504 v->display = display; 1505 1506 /* Save a copy of the XVisualInfo struct because the user may XFREE() 1507 * the struct but we may need some of the information contained in it 1508 * at a later time. 1509 */ 1510#ifdef XFree86Server 1511 v->visinfo = visinfo; 1512#else 1513 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); 1514 if(!v->visinfo) { 1515 FREE(v); 1516 return NULL; 1517 } 1518 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); 1519 1520 /* Save a copy of the pointer now so we can find this visual again 1521 * if we need to search for it in find_glx_visual(). 1522 */ 1523 v->vishandle = visinfo; 1524#endif 1525 1526#ifdef XFree86Server 1527 /* Initialize the depth of the screen */ 1528 { 1529 PixmapFormatRec *format; 1530 1531 for (format = screenInfo.formats; 1532 format->depth != display->rootDepth; 1533 format++) 1534 ; 1535 v->screen_depth = format->bitsPerPixel; 1536 } 1537#endif 1538 1539 /* check for MESA_GAMMA environment variable */ 1540 gamma = getenv("MESA_GAMMA"); 1541 if (gamma) { 1542 v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; 1543 sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); 1544 if (v->RedGamma<=0.0) v->RedGamma = 1.0; 1545 if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; 1546 if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; 1547 } 1548 else { 1549 v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; 1550 } 1551 1552 v->ximage_flag = ximage_flag; 1553 v->level = level; 1554 v->VisualCaveat = visualCaveat; 1555 1556 (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 ); 1557 1558 { 1559 int xclass; 1560 xclass = GET_VISUAL_CLASS(v); 1561 if (xclass==TrueColor || xclass==DirectColor) { 1562 red_bits = bitcount(GET_REDMASK(v)); 1563 green_bits = bitcount(GET_GREENMASK(v)); 1564 blue_bits = bitcount(GET_BLUEMASK(v)); 1565 alpha_bits = 0; 1566 } 1567 else { 1568 /* this is an approximation */ 1569 int depth; 1570 depth = GET_VISUAL_DEPTH(v); 1571 red_bits = depth / 3; 1572 depth -= red_bits; 1573 green_bits = depth / 2; 1574 depth -= green_bits; 1575 blue_bits = depth; 1576 alpha_bits = 0; 1577 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); 1578 } 1579 } 1580 1581 if (alpha_flag && alpha_bits == 0) 1582 alpha_bits = 8; 1583 1584 _mesa_initialize_visual( &v->mesa_visual, 1585 rgb_flag, db_flag, stereo_flag, 1586 red_bits, green_bits, 1587 blue_bits, alpha_bits, 1588 v->index_bits, 1589 depth_size, 1590 stencil_size, 1591 accum_red_size, accum_green_size, 1592 accum_blue_size, accum_alpha_size, 1593 0 ); 1594 return v; 1595} 1596 1597 1598void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ) 1599{ 1600 v->display = dpy; 1601} 1602 1603 1604void XMesaDestroyVisual( XMesaVisual v ) 1605{ 1606#ifndef XFree86Server 1607 FREE(v->visinfo); 1608#endif 1609 FREE(v); 1610} 1611 1612 1613 1614/* 1615 * Create a new XMesaContext. 1616 * Input: v - XMesaVisual 1617 * share_list - another XMesaContext with which to share display 1618 * lists or NULL if no sharing is wanted. 1619 * Return: an XMesaContext or NULL if error. 1620 */ 1621XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 1622{ 1623 XMesaContext c; 1624 GLcontext *ctx; 1625 GLboolean direct = GL_TRUE; /* XXXX */ 1626 /* NOT_DONE: should this be GL_FALSE??? */ 1627 static GLboolean firstTime = GL_TRUE; 1628 1629 if (firstTime) { 1630 _glthread_INIT_MUTEX(_xmesa_lock); 1631 firstTime = GL_FALSE; 1632 } 1633 1634 c = (XMesaContext) CALLOC_STRUCT(xmesa_context); 1635 if (!c) { 1636 return NULL; 1637 } 1638 1639 ctx = c->gl_ctx = _mesa_create_context( &v->mesa_visual, 1640 share_list ? share_list->gl_ctx : (GLcontext *) NULL, 1641 (void *) c, direct ); 1642 if (!c->gl_ctx) { 1643 FREE(c); 1644 return NULL; 1645 } 1646 1647 _mesa_enable_sw_extensions(ctx); 1648 _mesa_enable_1_3_extensions(ctx); 1649 1650 if (CHECK_BYTE_ORDER(v)) { 1651 c->swapbytes = GL_FALSE; 1652 } 1653 else { 1654 c->swapbytes = GL_TRUE; 1655 } 1656 1657 c->xm_visual = v; 1658 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ 1659 c->display = v->display; 1660 c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ 1661 1662 ctx->Driver.UpdateState = xmesa_update_state; 1663 1664 /* Initialize the software rasterizer and helper modules. 1665 */ 1666 _swrast_CreateContext( ctx ); 1667 _ac_CreateContext( ctx ); 1668 _tnl_CreateContext( ctx ); 1669 _swsetup_CreateContext( ctx ); 1670 1671 xmesa_register_swrast_functions( ctx ); 1672 1673 /* Set up some constant pointers: 1674 */ 1675 xmesa_init_pointers( ctx ); 1676 1677 1678 /* Run the config file 1679 */ 1680 _mesa_read_config_file( ctx ); 1681 1682 1683 return c; 1684} 1685 1686 1687 1688 1689void XMesaDestroyContext( XMesaContext c ) 1690{ 1691#ifdef FX 1692 if (c->xm_buffer && c->xm_buffer->FXctx) 1693 fxMesaDestroyContext(c->xm_buffer->FXctx); 1694#endif 1695 if (c->gl_ctx) { 1696 _swsetup_DestroyContext( c->gl_ctx ); 1697 _swrast_DestroyContext( c->gl_ctx ); 1698 _tnl_DestroyContext( c->gl_ctx ); 1699 _ac_DestroyContext( c->gl_ctx ); 1700 _mesa_destroy_context( c->gl_ctx ); 1701 } 1702 1703 FREE( c ); 1704} 1705 1706 1707 1708/* 1709 * XXX this isn't a public function! It's a hack for the 3Dfx driver. 1710 * Create a new XMesaBuffer from an X window. 1711 * Input: v - the XMesaVisual 1712 * w - the window 1713 * c - the context 1714 * Return: new XMesaBuffer or NULL if error 1715 */ 1716XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w, 1717 XMesaContext c ) 1718{ 1719#ifndef XFree86Server 1720 XWindowAttributes attr; 1721#endif 1722#ifdef FX 1723 char *fxEnvVar; 1724#endif 1725 int client = 0; 1726 1727 XMesaBuffer b = alloc_xmesa_buffer(); 1728 if (!b) { 1729 return NULL; 1730 } 1731 1732 (void) c; 1733 1734#ifdef XFree86Server 1735 client = CLIENT_ID(((XMesaDrawable)w)->id); 1736#endif 1737 1738 assert(v); 1739 1740#ifdef XFree86Server 1741 if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) { 1742#else 1743 XGetWindowAttributes( v->display, w, &attr ); 1744 1745 if (GET_VISUAL_DEPTH(v) != attr.depth) { 1746#endif 1747 if (getenv("MESA_DEBUG")) { 1748 fprintf(stderr, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n"); 1749 } 1750 return NULL; 1751 } 1752 1753 b->xm_visual = v; 1754 b->pixmap_flag = GL_FALSE; 1755 b->display = v->display; 1756#ifdef XFree86Server 1757 b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); 1758#else 1759 if (attr.colormap) { 1760 b->cmap = attr.colormap; 1761 } 1762 else { 1763 if (getenv("MESA_DEBUG")) { 1764 fprintf(stderr, "Window %u has no colormap!\n", (unsigned int) w); 1765 } 1766 /* this is weird, a window w/out a colormap!? */ 1767 /* OK, let's just allocate a new one and hope for the best */ 1768 b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); 1769 } 1770#endif 1771 1772 /* determine back buffer implementation */ 1773 if (v->mesa_visual.doubleBufferMode) { 1774 if (v->ximage_flag) { 1775 b->db_state = BACK_XIMAGE; 1776 } 1777 else { 1778 b->db_state = BACK_PIXMAP; 1779 } 1780 } 1781 else { 1782 b->db_state = 0; 1783 } 1784 1785 _mesa_initialize_framebuffer(&b->mesa_buffer, 1786 &v->mesa_visual, 1787 v->mesa_visual.depthBits > 0, 1788 v->mesa_visual.stencilBits > 0, 1789 v->mesa_visual.accumRedBits > 0, 1790 v->mesa_visual.alphaBits > 0 ); 1791 1792 if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode, 1793 (XMesaDrawable)w, b->cmap )) { 1794 free_xmesa_buffer(client, b); 1795 return NULL; 1796 } 1797 1798#ifdef FX 1799 fxEnvVar = getenv("MESA_GLX_FX"); 1800 if (fxEnvVar) { 1801 if (fxEnvVar[0]!='d') { 1802 int attribs[100]; 1803 int numAttribs = 0; 1804 int hw; 1805 if (v->mesa_visual.depthBits > 0) { 1806 attribs[numAttribs++] = FXMESA_DEPTH_SIZE; 1807 attribs[numAttribs++] = 1; 1808 } 1809 if (v->mesa_visual.doubleBufferMode) { 1810 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; 1811 } 1812 if (v->mesa_visual.accumRedBits > 0) { 1813 attribs[numAttribs++] = FXMESA_ACCUM_SIZE; 1814 attribs[numAttribs++] = v->mesa_visual.accumRedBits; 1815 } 1816 if (v->mesa_visual.stencilBits > 0) { 1817 attribs[numAttribs++] = FXMESA_STENCIL_SIZE; 1818 attribs[numAttribs++] = v->mesa_visual.stencilBits; 1819 } 1820 if (v->mesa_visual.alphaBits > 0) { 1821 attribs[numAttribs++] = FXMESA_ALPHA_SIZE; 1822 attribs[numAttribs++] = 1; 1823 } 1824 if (c->gl_ctx) { 1825#define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with fxapi.c! */ 1826 attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; 1827 attribs[numAttribs++] = (int) c->gl_ctx; 1828 } 1829 attribs[numAttribs++] = FXMESA_NONE; 1830 1831 if ((hw = fxQueryHardware())==GR_SSTTYPE_VOODOO) { 1832 b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); 1833 if ((v->undithered_pf!=PF_INDEX) && (b->backimage)) { 1834 b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; 1835 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') 1836 b->FXwindowHack = b->FXctx ? GL_TRUE : GL_FALSE; 1837 else 1838 b->FXwindowHack = GL_FALSE; 1839 } 1840 } 1841 else { 1842 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') 1843 b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, 1844 GR_REFRESH_75Hz, attribs); 1845 else 1846 b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); 1847 b->FXisHackUsable = GL_FALSE; 1848 b->FXwindowHack = GL_FALSE; 1849 } 1850 /* 1851 fprintf(stderr, 1852 "voodoo %d, wid %d height %d hack: usable %d active %d\n", 1853 hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack); 1854 */ 1855 } 1856 } 1857 else { 1858 fprintf(stderr,"WARNING: This Mesa Library includes the Glide driver but\n"); 1859 fprintf(stderr," you have not defined the MESA_GLX_FX env. var.\n"); 1860 fprintf(stderr," (check the README.3DFX file for more information).\n\n"); 1861 fprintf(stderr," you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); 1862 } 1863#endif 1864 1865 return b; 1866} 1867 1868 1869XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w ) 1870{ 1871 return XMesaCreateWindowBuffer2( v, w, NULL ); 1872} 1873 1874 1875/* 1876 * Create a new XMesaBuffer from an X pixmap. 1877 * Input: v - the XMesaVisual 1878 * p - the pixmap 1879 * cmap - the colormap, may be 0 if using a TrueColor or DirectColor 1880 * visual for the pixmap 1881 * Return: new XMesaBuffer or NULL if error 1882 */ 1883XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, 1884 XMesaPixmap p, XMesaColormap cmap ) 1885{ 1886 int client = 0; 1887 XMesaBuffer b = alloc_xmesa_buffer(); 1888 if (!b) { 1889 return NULL; 1890 } 1891 1892 1893#ifdef XFree86Server 1894 client = CLIENT_ID(((XMesaDrawable)p)->id); 1895#endif 1896 1897 assert(v); 1898 1899 b->xm_visual = v; 1900 b->pixmap_flag = GL_TRUE; 1901 b->display = v->display; 1902 b->cmap = cmap; 1903 1904 /* determine back buffer implementation */ 1905 if (v->mesa_visual.doubleBufferMode) { 1906 if (v->ximage_flag) { 1907 b->db_state = BACK_XIMAGE; 1908 } 1909 else { 1910 b->db_state = BACK_PIXMAP; 1911 } 1912 } 1913 else { 1914 b->db_state = 0; 1915 } 1916 1917 _mesa_initialize_framebuffer(&b->mesa_buffer, 1918 &v->mesa_visual, 1919 v->mesa_visual.depthBits > 0, 1920 v->mesa_visual.stencilBits > 0, 1921 v->mesa_visual.accumRedBits + 1922 v->mesa_visual.accumGreenBits + 1923 v->mesa_visual.accumBlueBits > 0, 1924 v->mesa_visual.alphaBits > 0 ); 1925 1926 if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, 1927 (XMesaDrawable)p, cmap)) { 1928 free_xmesa_buffer(client, b); 1929 return NULL; 1930 } 1931 1932 return b; 1933} 1934 1935 1936 1937#if 0 /* not done */ 1938XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap, 1939 unsigned int width, unsigned int height ) 1940{ 1941 int client = 0; 1942 XMesaBuffer b = alloc_xmesa_buffer(); 1943 if (!b) { 1944 return NULL; 1945 } 1946 1947 b->xm_visual = v; 1948 b->pbuffer_flag = GL_TRUE; 1949 b->display = v->display; 1950 b->cmap = cmap; 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 0, cmap)) { 1976 free_xmesa_buffer(client, b); 1977 return NULL; 1978 } 1979 1980 return b; 1981} 1982#endif 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_buffer = drawBuffer; 2056 c->xm_read_buffer = readBuffer; 2057 c->use_read_buffer = (drawBuffer != readBuffer); 2058 2059 return GL_TRUE; 2060 } 2061#endif 2062 if (c->gl_ctx == _mesa_get_current_context() 2063 && c->xm_buffer == drawBuffer 2064 && c->xm_read_buffer == readBuffer 2065 && c->xm_buffer->wasCurrent) { 2066 /* same context and buffer, do nothing */ 2067 return GL_TRUE; 2068 } 2069 2070 c->xm_buffer = drawBuffer; 2071 c->xm_read_buffer = readBuffer; 2072 c->use_read_buffer = (drawBuffer != readBuffer); 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_buffer->cleargc, c->clearpixel); 2097 } 2098 2099 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 2100 c->xm_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_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_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_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_buffer->FXisHackUsable) { 2204 FX_grSstControl(GR_CONTROL_DEACTIVATE); 2205 xmesa->xm_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_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 assert(xmesa->xm_buffer->FXctx); 2243 2244#ifdef XFree86Server 2245 x = b->frontbuffer->x; 2246 y = b->frontbuffer->y; 2247 width = b->frontbuffer->width; 2248 height = b->frontbuffer->height; 2249 depth = b->frontbuffer->depth; 2250#else 2251 XGetGeometry( xmesa->xm_visual->display, b->frontbuffer, 2252 &root, &xpos, &ypos, &width, &height, &bw, &depth); 2253#endif 2254 if (b->width != width || b->height != height) { 2255 b->width = MIN2((int)width, xmesa->xm_buffer->FXctx->width); 2256 b->height = MIN2((int)height, xmesa->xm_buffer->FXctx->height); 2257 if (b->width & 1) 2258 b->width--; /* prevent odd width */ 2259 xmesa_alloc_back_buffer( b ); 2260 } 2261 2262 grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); 2263 if (xmesa->xm_visual->undithered_pf==PF_5R6G5B) { 2264 /* Special case: 16bpp RGB */ 2265 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ 2266 0, xmesa->xm_buffer->FXctx->height - b->height, /*pos*/ 2267 b->width, b->height, /* size */ 2268 b->width * sizeof(GLushort), /* stride */ 2269 b->backimage->data); /* dest buffer */ 2270 } 2271 else if (xmesa->xm_visual->dithered_pf==PF_DITHER 2272 && GET_VISUAL_DEPTH(xmesa->xm_visual)==8) { 2273 /* Special case: 8bpp RGB */ 2274 for (y=0;y<b->height;y++) { 2275 GLubyte *ptr = (GLubyte*) xmesa->xm_buffer->backimage->data 2276 + xmesa->xm_buffer->backimage->bytes_per_line * y; 2277 XDITHER_SETUP(y); 2278 2279 /* read row from 3Dfx frame buffer */ 2280 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2281 0, xmesa->xm_buffer->FXctx->height-(b->height-y), 2282 b->width, 1, 2283 0, 2284 pixbuf ); 2285 2286 /* write to XImage back buffer */ 2287 for (x=0;x<b->width;x++) { 2288 GLubyte r = (pixbuf[x] & 0xf800) >> 8; 2289 GLubyte g = (pixbuf[x] & 0x07e0) >> 3; 2290 GLubyte b = (pixbuf[x] & 0x001f) << 3; 2291 *ptr++ = XDITHER( x, r, g, b); 2292 } 2293 } 2294 } 2295 else { 2296 /* General case: slow! */ 2297 for (y=0;y<b->height;y++) { 2298 /* read row from 3Dfx frame buffer */ 2299 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2300 0, xmesa->xm_buffer->FXctx->height-(b->height-y), 2301 b->width, 1, 2302 0, 2303 pixbuf ); 2304 2305 /* write to XImage back buffer */ 2306 for (x=0;x<b->width;x++) { 2307 XMesaPutPixel(b->backimage,x,y, 2308 xmesa_color_to_pixel(xmesa, 2309 (pixbuf[x] & 0xf800) >> 8, 2310 (pixbuf[x] & 0x07e0) >> 3, 2311 (pixbuf[x] & 0x001f) << 3, 2312 0xff, xmesa->pixelformat)); 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_swapbuffers(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_swapbuffers(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->pixmap_flag) { 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