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