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