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