xm_api.c revision d834e8da8847dd411d189684c56e1d7960f97303
1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* $Id: xm_api.c,v 1.38 2002/06/16 01:11:10 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 b->mesa_buffer.Width = w; 1281 b->mesa_buffer.Height = h; 1282 1283 b->frontbuffer = window; 1284 1285 /* Setup for single/double buffering */ 1286 if (v->mesa_visual.doubleBufferMode) { 1287 /* Double buffered */ 1288#ifndef XFree86Server 1289 b->shm = check_for_xshm( v->display ); 1290#endif 1291 xmesa_alloc_back_buffer( b ); 1292 if (b->db_state==BACK_PIXMAP) { 1293 b->buffer = (XMesaDrawable)b->backpixmap; 1294 } 1295 else { 1296 b->buffer = XIMAGE; 1297 } 1298 } 1299 else { 1300 /* Single Buffered */ 1301 b->buffer = b->frontbuffer; 1302 } 1303 1304 /* X11 graphics contexts */ 1305#ifdef XFree86Server 1306 b->gc = CreateScratchGC(v->display, window->depth); 1307#else 1308 b->gc = XCreateGC( v->display, window, 0, NULL ); 1309#endif 1310 XMesaSetFunction( v->display, b->gc, GXcopy ); 1311 1312 /* cleargc - for glClear() */ 1313#ifdef XFree86Server 1314 b->cleargc = CreateScratchGC(v->display, window->depth); 1315#else 1316 b->cleargc = XCreateGC( v->display, window, 0, NULL ); 1317#endif 1318 XMesaSetFunction( v->display, b->cleargc, GXcopy ); 1319 1320 /* 1321 * Don't generate Graphics Expose/NoExpose events in swapbuffers(). 1322 * Patch contributed by Michael Pichler May 15, 1995. 1323 */ 1324#ifdef XFree86Server 1325 b->swapgc = CreateScratchGC(v->display, window->depth); 1326 { 1327 CARD32 v[1]; 1328 v[0] = FALSE; 1329 dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL); 1330 } 1331#else 1332 gcvalues.graphics_exposures = False; 1333 b->swapgc = XCreateGC( v->display, window, 1334 GCGraphicsExposures, &gcvalues); 1335#endif 1336 XMesaSetFunction( v->display, b->swapgc, GXcopy ); 1337 /* 1338 * Set fill style and tile pixmap once for all for HPCR stuff 1339 * (instead of doing it each time in clear_color_HPCR_pixmap()) 1340 * Initialize whole stuff 1341 * Patch contributed by Jacques Leroy March 8, 1998. 1342 */ 1343 if (v->hpcr_clear_flag && b->buffer!=XIMAGE) { 1344 int i; 1345 for (i=0; i<16; i++) 1346 { 1347 XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0); 1348 XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0); 1349 } 1350 XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap, 1351 b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); 1352 XMesaSetFillStyle( v->display, b->cleargc, FillTiled); 1353 XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap ); 1354 } 1355 1356 /* Initialize the row buffer XImage for use in write_color_span() */ 1357#ifdef XFree86Server 1358 b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, 1359 (char *)MALLOC(MAX_WIDTH*4)); 1360#else 1361 b->rowimage = XCreateImage( v->display, 1362 v->visinfo->visual, 1363 v->visinfo->depth, 1364 ZPixmap, 0, /*format, offset*/ 1365 (char*) MALLOC(MAX_WIDTH*4), /*data*/ 1366 MAX_WIDTH, 1, /*width, height*/ 1367 32, /*bitmap_pad*/ 1368 0 /*bytes_per_line*/ ); 1369#endif 1370 } 1371 1372 return GL_TRUE; 1373} 1374 1375 1376 1377/* 1378 * Convert an RGBA color to a pixel value. 1379 */ 1380unsigned long 1381xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a, 1382 GLuint pixelFormat) 1383{ 1384 switch (pixelFormat) { 1385 case PF_INDEX: 1386 return 0; 1387 case PF_TRUECOLOR: 1388 { 1389 unsigned long p; 1390 PACK_TRUECOLOR( p, r, g, b ); 1391 return p; 1392 } 1393 case PF_8A8B8G8R: 1394 return PACK_8A8B8G8R( r, g, b, a ); 1395 case PF_8R8G8B: 1396 /* fall through */ 1397 case PF_8R8G8B24: 1398 return PACK_8R8G8B( r, g, b ); 1399 case PF_5R6G5B: 1400 return PACK_5R6G5B( r, g, b ); 1401 case PF_DITHER: 1402 { 1403 DITHER_SETUP; 1404 return DITHER( 1, 0, r, g, b ); 1405 } 1406 case PF_1BIT: 1407 /* 382 = (3*255)/2 */ 1408 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 1409 case PF_HPCR: 1410 return DITHER_HPCR(1, 1, r, g, b); 1411 case PF_LOOKUP: 1412 { 1413 LOOKUP_SETUP; 1414 return LOOKUP( r, g, b ); 1415 } 1416 case PF_GRAYSCALE: 1417 return GRAY_RGB( r, g, b ); 1418 case PF_TRUEDITHER: 1419 /* fall through */ 1420 case PF_DITHER_5R6G5B: 1421 { 1422 unsigned long p; 1423 PACK_TRUEDITHER(p, 1, 0, r, g, b); 1424 return p; 1425 } 1426 default: 1427 _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel"); 1428 } 1429 return 0; 1430} 1431 1432 1433/**********************************************************************/ 1434/***** Public Functions *****/ 1435/**********************************************************************/ 1436 1437 1438/* 1439 * Create a new X/Mesa visual. 1440 * Input: display - X11 display 1441 * visinfo - an XVisualInfo pointer 1442 * rgb_flag - GL_TRUE = RGB mode, 1443 * GL_FALSE = color index mode 1444 * alpha_flag - alpha buffer requested? 1445 * db_flag - GL_TRUE = double-buffered, 1446 * GL_FALSE = single buffered 1447 * stereo_flag - stereo visual? 1448 * ximage_flag - GL_TRUE = use an XImage for back buffer, 1449 * GL_FALSE = use an off-screen pixmap for back buffer 1450 * depth_size - requested bits/depth values, or zero 1451 * stencil_size - requested bits/stencil values, or zero 1452 * accum_red_size - requested bits/red accum values, or zero 1453 * accum_green_size - requested bits/green accum values, or zero 1454 * accum_blue_size - requested bits/blue accum values, or zero 1455 * accum_alpha_size - requested bits/alpha accum values, or zero 1456 * num_samples - number of samples/pixel if multisampling, or zero 1457 * level - visual level, usually 0 1458 * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT 1459 * Return; a new XMesaVisual or 0 if error. 1460 */ 1461XMesaVisual XMesaCreateVisual( XMesaDisplay *display, 1462 XMesaVisualInfo visinfo, 1463 GLboolean rgb_flag, 1464 GLboolean alpha_flag, 1465 GLboolean db_flag, 1466 GLboolean stereo_flag, 1467 GLboolean ximage_flag, 1468 GLint depth_size, 1469 GLint stencil_size, 1470 GLint accum_red_size, 1471 GLint accum_green_size, 1472 GLint accum_blue_size, 1473 GLint accum_alpha_size, 1474 GLint num_samples, 1475 GLint level, 1476 GLint visualCaveat ) 1477{ 1478 char *gamma; 1479 XMesaVisual v; 1480 GLint red_bits, green_bits, blue_bits, alpha_bits; 1481 1482 /* For debugging only */ 1483 if (getenv("MESA_XSYNC")) { 1484 /* This makes debugging X easier. 1485 * In your debugger, set a breakpoint on _XError to stop when an 1486 * X protocol error is generated. 1487 */ 1488#ifdef XFree86Server 1489 /* NOT_NEEDED */ 1490#else 1491 XSynchronize( display, 1 ); 1492#endif 1493 } 1494 1495 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); 1496 if (!v) { 1497 return NULL; 1498 } 1499 1500 /* 1501 * In the X server, NULL is passed in for the display. It will have 1502 * to be set before using this visual. See XMesaSetVisualDisplay() 1503 * below. 1504 */ 1505 v->display = display; 1506 1507 /* Save a copy of the XVisualInfo struct because the user may XFREE() 1508 * the struct but we may need some of the information contained in it 1509 * at a later time. 1510 */ 1511#ifdef XFree86Server 1512 v->visinfo = visinfo; 1513#else 1514 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); 1515 if(!v->visinfo) { 1516 FREE(v); 1517 return NULL; 1518 } 1519 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); 1520 1521 /* Save a copy of the pointer now so we can find this visual again 1522 * if we need to search for it in find_glx_visual(). 1523 */ 1524 v->vishandle = visinfo; 1525#endif 1526 1527#ifdef XFree86Server 1528 /* Initialize the depth of the screen */ 1529 { 1530 PixmapFormatRec *format; 1531 1532 for (format = screenInfo.formats; 1533 format->depth != display->rootDepth; 1534 format++) 1535 ; 1536 v->screen_depth = format->bitsPerPixel; 1537 } 1538#endif 1539 1540 /* check for MESA_GAMMA environment variable */ 1541 gamma = getenv("MESA_GAMMA"); 1542 if (gamma) { 1543 v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; 1544 sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); 1545 if (v->RedGamma<=0.0) v->RedGamma = 1.0; 1546 if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; 1547 if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; 1548 } 1549 else { 1550 v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; 1551 } 1552 1553 v->ximage_flag = ximage_flag; 1554 v->level = level; 1555 v->VisualCaveat = visualCaveat; 1556 1557 (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 ); 1558 1559 { 1560 int xclass; 1561 xclass = GET_VISUAL_CLASS(v); 1562 if (xclass==TrueColor || xclass==DirectColor) { 1563 red_bits = bitcount(GET_REDMASK(v)); 1564 green_bits = bitcount(GET_GREENMASK(v)); 1565 blue_bits = bitcount(GET_BLUEMASK(v)); 1566 alpha_bits = 0; 1567 } 1568 else { 1569 /* this is an approximation */ 1570 int depth; 1571 depth = GET_VISUAL_DEPTH(v); 1572 red_bits = depth / 3; 1573 depth -= red_bits; 1574 green_bits = depth / 2; 1575 depth -= green_bits; 1576 blue_bits = depth; 1577 alpha_bits = 0; 1578 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); 1579 } 1580 } 1581 1582 if (alpha_flag && alpha_bits == 0) 1583 alpha_bits = 8; 1584 1585 _mesa_initialize_visual( &v->mesa_visual, 1586 rgb_flag, db_flag, stereo_flag, 1587 red_bits, green_bits, 1588 blue_bits, alpha_bits, 1589 v->index_bits, 1590 depth_size, 1591 stencil_size, 1592 accum_red_size, accum_green_size, 1593 accum_blue_size, accum_alpha_size, 1594 0 ); 1595 return v; 1596} 1597 1598 1599void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ) 1600{ 1601 v->display = dpy; 1602} 1603 1604 1605void XMesaDestroyVisual( XMesaVisual v ) 1606{ 1607#ifndef XFree86Server 1608 FREE(v->visinfo); 1609#endif 1610 FREE(v); 1611} 1612 1613 1614 1615/* 1616 * Create a new XMesaContext. 1617 * Input: v - XMesaVisual 1618 * share_list - another XMesaContext with which to share display 1619 * lists or NULL if no sharing is wanted. 1620 * Return: an XMesaContext or NULL if error. 1621 */ 1622XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 1623{ 1624 static GLboolean firstTime = GL_TRUE; 1625 XMesaContext c; 1626 GLcontext *ctx; 1627 __GLimports imports; 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 _mesa_init_default_imports( &imports, (void *) c ); 1640 ctx = c->gl_ctx = _mesa_create_context( &v->mesa_visual, 1641 share_list ? share_list->gl_ctx : (GLcontext *) NULL, 1642 &imports ); 1643 if (!c->gl_ctx) { 1644 FREE(c); 1645 return NULL; 1646 } 1647 1648 _mesa_enable_sw_extensions(ctx); 1649 _mesa_enable_1_3_extensions(ctx); 1650 1651 if (CHECK_BYTE_ORDER(v)) { 1652 c->swapbytes = GL_FALSE; 1653 } 1654 else { 1655 c->swapbytes = GL_TRUE; 1656 } 1657 1658 c->xm_visual = v; 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_buffer && c->xm_buffer->FXctx) 1688 fxMesaDestroyContext(c->xm_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_buffer = drawBuffer; 2051 c->xm_read_buffer = readBuffer; 2052 c->use_read_buffer = (drawBuffer != readBuffer); 2053 2054 return GL_TRUE; 2055 } 2056#endif 2057 if (c->gl_ctx == _mesa_get_current_context() 2058 && c->xm_buffer == drawBuffer 2059 && c->xm_read_buffer == readBuffer 2060 && c->xm_buffer->wasCurrent) { 2061 /* same context and buffer, do nothing */ 2062 return GL_TRUE; 2063 } 2064 2065 c->xm_buffer = drawBuffer; 2066 c->xm_read_buffer = readBuffer; 2067 c->use_read_buffer = (drawBuffer != readBuffer); 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_buffer->cleargc, c->clearpixel); 2092 } 2093 2094 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 2095 c->xm_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_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_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_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_buffer->FXisHackUsable) { 2199 FX_grSstControl(GR_CONTROL_DEACTIVATE); 2200 xmesa->xm_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_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 assert(xmesa->xm_buffer->FXctx); 2238 2239#ifdef XFree86Server 2240 x = b->frontbuffer->x; 2241 y = b->frontbuffer->y; 2242 width = b->frontbuffer->width; 2243 height = b->frontbuffer->height; 2244 depth = b->frontbuffer->depth; 2245#else 2246 XGetGeometry( xmesa->xm_visual->display, b->frontbuffer, 2247 &root, &xpos, &ypos, &width, &height, &bw, &depth); 2248#endif 2249 if (b->width != width || b->height != height) { 2250 b->width = MIN2((int)width, xmesa->xm_buffer->FXctx->width); 2251 b->height = MIN2((int)height, xmesa->xm_buffer->FXctx->height); 2252 if (b->width & 1) 2253 b->width--; /* prevent odd width */ 2254 xmesa_alloc_back_buffer( b ); 2255 } 2256 2257 grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); 2258 if (xmesa->xm_visual->undithered_pf==PF_5R6G5B) { 2259 /* Special case: 16bpp RGB */ 2260 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ 2261 0, xmesa->xm_buffer->FXctx->height - b->height, /*pos*/ 2262 b->width, b->height, /* size */ 2263 b->width * sizeof(GLushort), /* stride */ 2264 b->backimage->data); /* dest buffer */ 2265 } 2266 else if (xmesa->xm_visual->dithered_pf==PF_DITHER 2267 && GET_VISUAL_DEPTH(xmesa->xm_visual)==8) { 2268 /* Special case: 8bpp RGB */ 2269 for (y=0;y<b->height;y++) { 2270 GLubyte *ptr = (GLubyte*) xmesa->xm_buffer->backimage->data 2271 + xmesa->xm_buffer->backimage->bytes_per_line * y; 2272 XDITHER_SETUP(y); 2273 2274 /* read row from 3Dfx frame buffer */ 2275 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2276 0, xmesa->xm_buffer->FXctx->height-(b->height-y), 2277 b->width, 1, 2278 0, 2279 pixbuf ); 2280 2281 /* write to XImage back buffer */ 2282 for (x=0;x<b->width;x++) { 2283 GLubyte r = (pixbuf[x] & 0xf800) >> 8; 2284 GLubyte g = (pixbuf[x] & 0x07e0) >> 3; 2285 GLubyte b = (pixbuf[x] & 0x001f) << 3; 2286 *ptr++ = XDITHER( x, r, g, b); 2287 } 2288 } 2289 } 2290 else { 2291 /* General case: slow! */ 2292 for (y=0;y<b->height;y++) { 2293 /* read row from 3Dfx frame buffer */ 2294 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2295 0, xmesa->xm_buffer->FXctx->height-(b->height-y), 2296 b->width, 1, 2297 0, 2298 pixbuf ); 2299 2300 /* write to XImage back buffer */ 2301 for (x=0;x<b->width;x++) { 2302 XMesaPutPixel(b->backimage,x,y, 2303 xmesa_color_to_pixel(xmesa, 2304 (pixbuf[x] & 0xf800) >> 8, 2305 (pixbuf[x] & 0x07e0) >> 3, 2306 (pixbuf[x] & 0x001f) << 3, 2307 0xff, xmesa->pixelformat)); 2308 } 2309 } 2310 } 2311 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); 2312} 2313#endif 2314 2315 2316/* 2317 * Copy the back buffer to the front buffer. If there's no back buffer 2318 * this is a no-op. 2319 */ 2320void XMesaSwapBuffers( XMesaBuffer b ) 2321{ 2322 GET_CURRENT_CONTEXT(ctx); 2323 2324 /* If we're swapping the buffer associated with the current context 2325 * we have to flush any pending rendering commands first. 2326 */ 2327 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2328 _mesa_swapbuffers(ctx); 2329 2330 if (b->db_state) { 2331#ifdef FX 2332 if (b->FXctx) { 2333 fxMesaSwapBuffers(); 2334 2335 if (b->FXwindowHack) 2336 FXgetImage(b); 2337 else 2338 return; 2339 } 2340#endif 2341 if (b->backimage) { 2342 /* Copy Ximage from host's memory to server's window */ 2343#if defined(USE_XSHM) && !defined(XFree86Server) 2344 if (b->shm) { 2345 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2346 XShmPutImage( b->xm_visual->display, b->frontbuffer, 2347 b->swapgc, 2348 b->backimage, 0, 0, 2349 0, 0, b->width, b->height, False ); 2350 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2351 } 2352 else 2353#endif 2354 { 2355 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2356 XMesaPutImage( b->xm_visual->display, b->frontbuffer, 2357 b->swapgc, 2358 b->backimage, 0, 0, 2359 0, 0, b->width, b->height ); 2360 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2361 } 2362 } 2363 else { 2364 /* Copy pixmap to window on server */ 2365 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2366 XMesaCopyArea( b->xm_visual->display, 2367 b->backpixmap, /* source drawable */ 2368 b->frontbuffer, /* dest. drawable */ 2369 b->swapgc, 2370 0, 0, b->width, b->height, /* source region */ 2371 0, 0 /* dest region */ 2372 ); 2373 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2374 } 2375 } 2376#if !defined(XFree86Server) 2377 XSync( b->xm_visual->display, False ); 2378#endif 2379} 2380 2381 2382 2383/* 2384 * Copy sub-region of back buffer to front buffer 2385 */ 2386void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 2387{ 2388 GET_CURRENT_CONTEXT(ctx); 2389 2390 /* If we're swapping the buffer associated with the current context 2391 * we have to flush any pending rendering commands first. 2392 */ 2393 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2394 _mesa_swapbuffers(ctx); 2395 2396 if (b->db_state) { 2397 int yTop = b->height - y - height; 2398#ifdef FX 2399 if (b->FXctx) { 2400 fxMesaSwapBuffers(); 2401 if (b->FXwindowHack) 2402 FXgetImage(b); 2403 else 2404 return; 2405 } 2406#endif 2407 if (b->backimage) { 2408 /* Copy Ximage from host's memory to server's window */ 2409#if defined(USE_XSHM) && !defined(XFree86Server) 2410 if (b->shm) { 2411 /* XXX assuming width and height aren't too large! */ 2412 XShmPutImage( b->xm_visual->display, b->frontbuffer, 2413 b->swapgc, 2414 b->backimage, x, yTop, 2415 x, yTop, width, height, False ); 2416 /* wait for finished event??? */ 2417 } 2418 else 2419#endif 2420 { 2421 /* XXX assuming width and height aren't too large! */ 2422 XMesaPutImage( b->xm_visual->display, b->frontbuffer, 2423 b->swapgc, 2424 b->backimage, x, yTop, 2425 x, yTop, width, height ); 2426 } 2427 } 2428 else { 2429 /* Copy pixmap to window on server */ 2430 XMesaCopyArea( b->xm_visual->display, 2431 b->backpixmap, /* source drawable */ 2432 b->frontbuffer, /* dest. drawable */ 2433 b->swapgc, 2434 x, yTop, width, height, /* source region */ 2435 x, yTop /* dest region */ 2436 ); 2437 } 2438 } 2439} 2440 2441 2442/* 2443 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function 2444 * is a way to get "under the hood" of X/Mesa so one can manipulate the 2445 * back buffer directly. 2446 * Output: pixmap - pointer to back buffer's Pixmap, or 0 2447 * ximage - pointer to back buffer's XImage, or NULL 2448 * Return: GL_TRUE = context is double buffered 2449 * GL_FALSE = context is single buffered 2450 */ 2451GLboolean XMesaGetBackBuffer( XMesaBuffer b, 2452 XMesaPixmap *pixmap, 2453 XMesaImage **ximage ) 2454{ 2455 if (b->db_state) { 2456 if (pixmap) *pixmap = b->backpixmap; 2457 if (ximage) *ximage = b->backimage; 2458 return GL_TRUE; 2459 } 2460 else { 2461 *pixmap = 0; 2462 *ximage = NULL; 2463 return GL_FALSE; 2464 } 2465} 2466 2467 2468/* 2469 * Return the depth buffer associated with an XMesaBuffer. 2470 * Input: b - the XMesa buffer handle 2471 * Output: width, height - size of buffer in pixels 2472 * bytesPerValue - bytes per depth value (2 or 4) 2473 * buffer - pointer to depth buffer values 2474 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 2475 */ 2476GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, 2477 GLint *bytesPerValue, void **buffer ) 2478{ 2479 if (!b->mesa_buffer.DepthBuffer) { 2480 *width = 0; 2481 *height = 0; 2482 *bytesPerValue = 0; 2483 *buffer = 0; 2484 return GL_FALSE; 2485 } 2486 else { 2487 *width = b->mesa_buffer.Width; 2488 *height = b->mesa_buffer.Height; 2489 *bytesPerValue = sizeof(GLdepth); 2490 *buffer = b->mesa_buffer.DepthBuffer; 2491 return GL_TRUE; 2492 } 2493} 2494 2495 2496void XMesaFlush( XMesaContext c ) 2497{ 2498 if (c && c->xm_visual) { 2499#ifdef XFree86Server 2500 /* NOT_NEEDED */ 2501#else 2502 XSync( c->xm_visual->display, False ); 2503#endif 2504 } 2505} 2506 2507 2508 2509const char *XMesaGetString( XMesaContext c, int name ) 2510{ 2511 (void) c; 2512 if (name==XMESA_VERSION) { 2513 return "3.5"; 2514 } 2515 else if (name==XMESA_EXTENSIONS) { 2516 return ""; 2517 } 2518 else { 2519 return NULL; 2520 } 2521} 2522 2523 2524 2525XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) 2526{ 2527 XMesaBuffer b; 2528 for (b=XMesaBufferList; b; b=b->Next) { 2529 if (b->frontbuffer==d && b->display==dpy) { 2530 return b; 2531 } 2532 } 2533 return NULL; 2534} 2535 2536 2537 2538/* 2539 * Look for XMesaBuffers whose X window has been destroyed. 2540 * Deallocate any such XMesaBuffers. 2541 */ 2542void XMesaGarbageCollect( void ) 2543{ 2544 XMesaBuffer b, next; 2545 for (b=XMesaBufferList; b; b=next) { 2546 next = b->Next; 2547 if (b->display && b->frontbuffer && b->type == WINDOW) { 2548#ifdef XFree86Server 2549 /* NOT_NEEDED */ 2550#else 2551 XSync(b->display, False); 2552 if (!window_exists( b->display, b->frontbuffer )) { 2553 /* found a dead window, free the ancillary info */ 2554 XMesaDestroyBuffer( b ); 2555 } 2556#endif 2557 } 2558 } 2559} 2560 2561 2562void XMesaReset( void ) 2563{ 2564 while (XMesaBufferList) 2565 XMesaDestroyBuffer(XMesaBufferList); 2566 2567 XMesaBufferList = NULL; 2568} 2569 2570 2571unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, 2572 GLfloat red, GLfloat green, 2573 GLfloat blue, GLfloat alpha ) 2574{ 2575 GLint r = (GLint) (red * 255.0F); 2576 GLint g = (GLint) (green * 255.0F); 2577 GLint b = (GLint) (blue * 255.0F); 2578 GLint a = (GLint) (alpha * 255.0F); 2579 2580 switch (xmesa->pixelformat) { 2581 case PF_INDEX: 2582 return 0; 2583 case PF_TRUECOLOR: 2584 { 2585 unsigned long p; 2586 PACK_TRUECOLOR( p, r, g, b ); 2587 return p; 2588 } 2589 case PF_8A8B8G8R: 2590 return PACK_8A8B8G8R( r, g, b, a ); 2591 case PF_8R8G8B: 2592 return PACK_8R8G8B( r, g, b ); 2593 case PF_5R6G5B: 2594 return PACK_5R6G5B( r, g, b ); 2595 case PF_DITHER: 2596 { 2597 DITHER_SETUP; 2598 return DITHER( x, y, r, g, b ); 2599 } 2600 case PF_1BIT: 2601 /* 382 = (3*255)/2 */ 2602 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 2603 case PF_HPCR: 2604 return DITHER_HPCR(x, y, r, g, b); 2605 case PF_LOOKUP: 2606 { 2607 LOOKUP_SETUP; 2608 return LOOKUP( r, g, b ); 2609 } 2610 case PF_GRAYSCALE: 2611 return GRAY_RGB( r, g, b ); 2612 case PF_DITHER_5R6G5B: 2613 /* fall through */ 2614 case PF_TRUEDITHER: 2615 { 2616 unsigned long p; 2617 PACK_TRUEDITHER(p, x, y, r, g, b); 2618 return p; 2619 } 2620 default: 2621 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); 2622 } 2623 return 0; 2624} 2625 2626 2627/* 2628 * This is typically called when the window size changes and we need 2629 * to reallocate the buffer's back/depth/stencil/accum buffers. 2630 */ 2631void XMesaResizeBuffers( XMesaBuffer b ) 2632{ 2633 xmesa_resize_buffers( &(b->mesa_buffer) ); 2634 2635} 2636 2637