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