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