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