xm_api.c revision 63f6802077c2279e1b9551f9a628e6a313488f8d
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.2 4 * 5 * Copyright (C) 1999-2006 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 assert(depth > 0); 257 for (i = 0; i < screenInfo.numPixmapFormats; i++) { 258 if (screenInfo.formats[i].depth == depth) 259 return screenInfo.formats[i].bitsPerPixel; 260 } 261 return depth; /* should never get here, but this should be safe */ 262} 263 264#else 265 266static int bits_per_pixel( XMesaVisual xmv ) 267{ 268 XMesaDisplay *dpy = xmv->display; 269 XMesaVisualInfo visinfo = xmv->visinfo; 270 XMesaImage *img; 271 int bitsPerPixel; 272 /* Create a temporary XImage */ 273 img = XCreateImage( dpy, visinfo->visual, visinfo->depth, 274 ZPixmap, 0, /*format, offset*/ 275 (char*) MALLOC(8), /*data*/ 276 1, 1, /*width, height*/ 277 32, /*bitmap_pad*/ 278 0 /*bytes_per_line*/ 279 ); 280 assert(img); 281 /* grab the bits/pixel value */ 282 bitsPerPixel = img->bits_per_pixel; 283 /* free the XImage */ 284 _mesa_free( img->data ); 285 img->data = NULL; 286 XMesaDestroyImage( img ); 287 return bitsPerPixel; 288} 289#endif 290 291 292 293/* 294 * Determine if a given X window ID is valid (window exists). 295 * Do this by calling XGetWindowAttributes() for the window and 296 * checking if we catch an X error. 297 * Input: dpy - the display 298 * win - the window to check for existance 299 * Return: GL_TRUE - window exists 300 * GL_FALSE - window doesn't exist 301 */ 302#ifndef XFree86Server 303static GLboolean WindowExistsFlag; 304 305static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr ) 306{ 307 (void) dpy; 308 if (xerr->error_code == BadWindow) { 309 WindowExistsFlag = GL_FALSE; 310 } 311 return 0; 312} 313 314static GLboolean window_exists( XMesaDisplay *dpy, Window win ) 315{ 316 XWindowAttributes wa; 317 int (*old_handler)( XMesaDisplay*, XErrorEvent* ); 318 WindowExistsFlag = GL_TRUE; 319 old_handler = XSetErrorHandler(window_exists_err_handler); 320 XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ 321 XSetErrorHandler(old_handler); 322 return WindowExistsFlag; 323} 324#endif 325 326 327 328/**********************************************************************/ 329/***** Linked list of XMesaBuffers *****/ 330/**********************************************************************/ 331 332static XMesaBuffer XMesaBufferList = NULL; 333 334 335/** 336 * Allocate a new XMesaBuffer, initialize basic fields and add to 337 * the list of all buffers. 338 */ 339static XMesaBuffer 340alloc_xmesa_buffer(XMesaVisual vis, BufferType type, XMesaColormap cmap) 341{ 342 XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); 343 if (b) { 344 GLboolean swAlpha; 345 346 b->display = vis->display; 347 b->xm_visual = vis; 348 b->type = type; 349 b->cmap = cmap; 350 351 _mesa_initialize_framebuffer(&b->mesa_buffer, &vis->mesa_visual); 352 353 /* Allocate the framebuffer's renderbuffers */ 354 assert(!b->mesa_buffer.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); 355 assert(!b->mesa_buffer.Attachment[BUFFER_BACK_LEFT].Renderbuffer); 356 357 /* front renderbuffer */ 358 b->frontxrb = xmesa_new_renderbuffer(NULL, 0, &vis->mesa_visual, 359 GL_FALSE); 360 _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_FRONT_LEFT, 361 &b->frontxrb->Base); 362 363 /* back renderbuffer */ 364 if (vis->mesa_visual.doubleBufferMode) { 365 b->backxrb = xmesa_new_renderbuffer(NULL, 0, &vis->mesa_visual, 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 bound for the first time, we can finally finish 1189 * initializing the context's visual and buffer information. 1190 * \param v the XMesaVisual to initialize 1191 * \param b the XMesaBuffer to initialize (may be NULL) 1192 * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode 1193 * \param window the window/pixmap we're rendering into 1194 * \param cmap the colormap associated with the window/pixmap 1195 * \return GL_TRUE=success, GL_FALSE=failure 1196 */ 1197static GLboolean 1198initialize_visual_and_buffer(int client, XMesaVisual v, XMesaBuffer b, 1199 GLboolean rgb_flag, XMesaDrawable window, 1200 XMesaColormap cmap) 1201{ 1202 ASSERT(!b || b->xm_visual == v); 1203 1204 /* Save true bits/pixel */ 1205 v->BitsPerPixel = bits_per_pixel(v); 1206 assert(v->BitsPerPixel > 0); 1207 1208 if (rgb_flag==GL_FALSE) { 1209 /* COLOR-INDEXED WINDOW: 1210 * Even if the visual is TrueColor or DirectColor we treat it as 1211 * being color indexed. This is weird but might be useful to someone. 1212 */ 1213 v->dithered_pf = v->undithered_pf = PF_Index; 1214 v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v); 1215 } 1216 else { 1217 /* RGB WINDOW: 1218 * We support RGB rendering into almost any kind of visual. 1219 */ 1220 const int xclass = v->mesa_visual.visualType; 1221 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { 1222 setup_truecolor( v, b, cmap ); 1223 } 1224 else if (xclass == GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v) == 1) { 1225 setup_monochrome( v, b ); 1226 } 1227 else if (xclass == GLX_GRAY_SCALE || xclass == GLX_STATIC_GRAY) { 1228 if (!setup_grayscale( client, v, b, cmap )) { 1229 return GL_FALSE; 1230 } 1231 } 1232 else if ((xclass == GLX_PSEUDO_COLOR || xclass == GLX_STATIC_COLOR) 1233 && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) { 1234 if (!setup_dithered_color( client, v, b, cmap )) { 1235 return GL_FALSE; 1236 } 1237 } 1238 else { 1239 _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n"); 1240 return GL_FALSE; 1241 } 1242 v->mesa_visual.indexBits = 0; 1243 1244 if (_mesa_getenv("MESA_NO_DITHER")) { 1245 v->dithered_pf = v->undithered_pf; 1246 } 1247 } 1248 1249 1250 /* 1251 * If MESA_INFO env var is set print out some debugging info 1252 * which can help Brian figure out what's going on when a user 1253 * reports bugs. 1254 */ 1255 if (_mesa_getenv("MESA_INFO")) { 1256 _mesa_printf("X/Mesa visual = %p\n", (void *) v); 1257 _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf); 1258 _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf); 1259 _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level); 1260 _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); 1261 _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); 1262 } 1263 1264 if (b && window) { 1265 /* Do window-specific initializations */ 1266 1267 b->frontxrb->drawable = window; 1268 b->frontxrb->pixmap = (XMesaPixmap) window; 1269 1270 /* Setup for single/double buffering */ 1271 if (v->mesa_visual.doubleBufferMode) { 1272 /* Double buffered */ 1273 b->shm = check_for_xshm( v->display ); 1274 xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height); 1275 } 1276 1277 /* X11 graphics contexts */ 1278#ifdef XFree86Server 1279 b->gc = CreateScratchGC(v->display, window->depth); 1280#else 1281 b->gc = XCreateGC( v->display, window, 0, NULL ); 1282#endif 1283 XMesaSetFunction( v->display, b->gc, GXcopy ); 1284 1285 /* cleargc - for glClear() */ 1286#ifdef XFree86Server 1287 b->cleargc = CreateScratchGC(v->display, window->depth); 1288#else 1289 b->cleargc = XCreateGC( v->display, window, 0, NULL ); 1290#endif 1291 XMesaSetFunction( v->display, b->cleargc, GXcopy ); 1292 1293 /* 1294 * Don't generate Graphics Expose/NoExpose events in swapbuffers(). 1295 * Patch contributed by Michael Pichler May 15, 1995. 1296 */ 1297#ifdef XFree86Server 1298 b->swapgc = CreateScratchGC(v->display, window->depth); 1299 { 1300 CARD32 v[1]; 1301 v[0] = FALSE; 1302 dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL); 1303 } 1304#else 1305 { 1306 XGCValues gcvalues; 1307 gcvalues.graphics_exposures = False; 1308 b->swapgc = XCreateGC(v->display, window, 1309 GCGraphicsExposures, &gcvalues); 1310 } 1311#endif 1312 XMesaSetFunction( v->display, b->swapgc, GXcopy ); 1313 /* 1314 * Set fill style and tile pixmap once for all for HPCR stuff 1315 * (instead of doing it each time in clear_color_HPCR_pixmap()) 1316 * Initialize whole stuff 1317 * Patch contributed by Jacques Leroy March 8, 1998. 1318 */ 1319 if (v->hpcr_clear_flag && b->backxrb && b->backxrb->pixmap) { 1320 int i; 1321 for (i = 0; i < 16; i++) { 1322 XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0); 1323 XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0); 1324 } 1325 XMesaPutImage(b->display, (XMesaDrawable) v->hpcr_clear_pixmap, 1326 b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); 1327 XMesaSetFillStyle( v->display, b->cleargc, FillTiled); 1328 XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap ); 1329 } 1330 1331 /* Initialize the row buffer XImage for use in write_color_span() */ 1332#ifdef XFree86Server 1333 b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, 1334 (char *)MALLOC(MAX_WIDTH*4)); 1335#else 1336 b->rowimage = XCreateImage( v->display, 1337 v->visinfo->visual, 1338 v->visinfo->depth, 1339 ZPixmap, 0, /*format, offset*/ 1340 (char*) MALLOC(MAX_WIDTH*4), /*data*/ 1341 MAX_WIDTH, 1, /*width, height*/ 1342 32, /*bitmap_pad*/ 1343 0 /*bytes_per_line*/ ); 1344#endif 1345 if (!b->rowimage) 1346 return GL_FALSE; 1347 } 1348 1349 return GL_TRUE; 1350} 1351 1352 1353 1354/* 1355 * Convert an RGBA color to a pixel value. 1356 */ 1357unsigned long 1358xmesa_color_to_pixel(GLcontext *ctx, 1359 GLubyte r, GLubyte g, GLubyte b, GLubyte a, 1360 GLuint pixelFormat) 1361{ 1362 XMesaContext xmesa = XMESA_CONTEXT(ctx); 1363 switch (pixelFormat) { 1364 case PF_Index: 1365 return 0; 1366 case PF_Truecolor: 1367 { 1368 unsigned long p; 1369 PACK_TRUECOLOR( p, r, g, b ); 1370 return p; 1371 } 1372 case PF_8A8B8G8R: 1373 return PACK_8A8B8G8R( r, g, b, a ); 1374 case PF_8A8R8G8B: 1375 return PACK_8A8R8G8B( r, g, b, a ); 1376 case PF_8R8G8B: 1377 /* fall through */ 1378 case PF_8R8G8B24: 1379 return PACK_8R8G8B( r, g, b ); 1380 case PF_5R6G5B: 1381 return PACK_5R6G5B( r, g, b ); 1382 case PF_Dither: 1383 { 1384 DITHER_SETUP; 1385 return DITHER( 1, 0, r, g, b ); 1386 } 1387 case PF_1Bit: 1388 /* 382 = (3*255)/2 */ 1389 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 1390 case PF_HPCR: 1391 return DITHER_HPCR(1, 1, r, g, b); 1392 case PF_Lookup: 1393 { 1394 LOOKUP_SETUP; 1395 return LOOKUP( r, g, b ); 1396 } 1397 case PF_Grayscale: 1398 return GRAY_RGB( r, g, b ); 1399 case PF_Dither_True: 1400 /* fall through */ 1401 case PF_Dither_5R6G5B: 1402 { 1403 unsigned long p; 1404 PACK_TRUEDITHER(p, 1, 0, r, g, b); 1405 return p; 1406 } 1407 default: 1408 _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel"); 1409 } 1410 return 0; 1411} 1412 1413 1414#define NUM_VISUAL_TYPES 6 1415 1416/** 1417 * Convert an X visual type to a GLX visual type. 1418 * 1419 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) 1420 * to be converted. 1421 * \return If \c visualType is a valid X visual type, a GLX visual type will 1422 * be returned. Otherwise \c GLX_NONE will be returned. 1423 * 1424 * \note 1425 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the 1426 * DRI CVS tree. 1427 */ 1428static GLint 1429xmesa_convert_from_x_visual_type( int visualType ) 1430{ 1431 static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { 1432 GLX_STATIC_GRAY, GLX_GRAY_SCALE, 1433 GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, 1434 GLX_TRUE_COLOR, GLX_DIRECT_COLOR 1435 }; 1436 1437 return ( (unsigned) visualType < NUM_VISUAL_TYPES ) 1438 ? glx_visual_types[ visualType ] : GLX_NONE; 1439} 1440 1441 1442/**********************************************************************/ 1443/***** Public Functions *****/ 1444/**********************************************************************/ 1445 1446 1447/* 1448 * Create a new X/Mesa visual. 1449 * Input: display - X11 display 1450 * visinfo - an XVisualInfo pointer 1451 * rgb_flag - GL_TRUE = RGB mode, 1452 * GL_FALSE = color index mode 1453 * alpha_flag - alpha buffer requested? 1454 * db_flag - GL_TRUE = double-buffered, 1455 * GL_FALSE = single buffered 1456 * stereo_flag - stereo visual? 1457 * ximage_flag - GL_TRUE = use an XImage for back buffer, 1458 * GL_FALSE = use an off-screen pixmap for back buffer 1459 * depth_size - requested bits/depth values, or zero 1460 * stencil_size - requested bits/stencil values, or zero 1461 * accum_red_size - requested bits/red accum values, or zero 1462 * accum_green_size - requested bits/green accum values, or zero 1463 * accum_blue_size - requested bits/blue accum values, or zero 1464 * accum_alpha_size - requested bits/alpha accum values, or zero 1465 * num_samples - number of samples/pixel if multisampling, or zero 1466 * level - visual level, usually 0 1467 * visualCaveat - ala the GLX extension, usually GLX_NONE 1468 * Return; a new XMesaVisual or 0 if error. 1469 */ 1470XMesaVisual XMesaCreateVisual( XMesaDisplay *display, 1471 XMesaVisualInfo visinfo, 1472 GLboolean rgb_flag, 1473 GLboolean alpha_flag, 1474 GLboolean db_flag, 1475 GLboolean stereo_flag, 1476 GLboolean ximage_flag, 1477 GLint depth_size, 1478 GLint stencil_size, 1479 GLint accum_red_size, 1480 GLint accum_green_size, 1481 GLint accum_blue_size, 1482 GLint accum_alpha_size, 1483 GLint num_samples, 1484 GLint level, 1485 GLint visualCaveat ) 1486{ 1487 char *gamma; 1488 XMesaVisual v; 1489 GLint red_bits, green_bits, blue_bits, alpha_bits; 1490 1491#ifndef XFree86Server 1492 /* For debugging only */ 1493 if (_mesa_getenv("MESA_XSYNC")) { 1494 /* This makes debugging X easier. 1495 * In your debugger, set a breakpoint on _XError to stop when an 1496 * X protocol error is generated. 1497 */ 1498 XSynchronize( display, 1 ); 1499 } 1500#endif 1501 1502 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); 1503 if (!v) { 1504 return NULL; 1505 } 1506 1507 /* 1508 * In the X server, NULL is passed in for the display. It will have 1509 * to be set before using this visual. See XMesaSetVisualDisplay() 1510 * below. 1511 */ 1512 v->display = display; 1513 1514 /* Save a copy of the XVisualInfo struct because the user may X_mesa_free() 1515 * the struct but we may need some of the information contained in it 1516 * at a later time. 1517 */ 1518#ifndef XFree86Server 1519 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); 1520 if(!v->visinfo) { 1521 _mesa_free(v); 1522 return NULL; 1523 } 1524 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); 1525#endif 1526 1527 /* check for MESA_GAMMA environment variable */ 1528 gamma = _mesa_getenv("MESA_GAMMA"); 1529 if (gamma) { 1530 v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; 1531 sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); 1532 if (v->RedGamma<=0.0) v->RedGamma = 1.0; 1533 if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; 1534 if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; 1535 } 1536 else { 1537 v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; 1538 } 1539 1540 v->ximage_flag = ximage_flag; 1541 1542#ifdef XFree86Server 1543 /* We could calculate these values by ourselves. nplanes is either the sum 1544 * of the red, green, and blue bits or the number index bits. 1545 * ColormapEntries is either (1U << index_bits) or 1546 * (1U << max(redBits, greenBits, blueBits)). 1547 */ 1548 assert(visinfo->nplanes > 0); 1549 v->nplanes = visinfo->nplanes; 1550 v->ColormapEntries = visinfo->ColormapEntries; 1551 1552 v->mesa_visual.redMask = visinfo->redMask; 1553 v->mesa_visual.greenMask = visinfo->greenMask; 1554 v->mesa_visual.blueMask = visinfo->blueMask; 1555 v->mesa_visual.visualID = visinfo->vid; 1556 v->mesa_visual.screen = 0; /* FIXME: What should be done here? */ 1557#else 1558 v->mesa_visual.redMask = visinfo->red_mask; 1559 v->mesa_visual.greenMask = visinfo->green_mask; 1560 v->mesa_visual.blueMask = visinfo->blue_mask; 1561 v->mesa_visual.visualID = visinfo->visualid; 1562 v->mesa_visual.screen = visinfo->screen; 1563#endif 1564 1565#if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus)) 1566 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class); 1567#else 1568 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); 1569#endif 1570 1571 v->mesa_visual.visualRating = visualCaveat; 1572 1573 (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 ); 1574 1575 { 1576 const int xclass = v->mesa_visual.visualType; 1577 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { 1578 red_bits = _mesa_bitcount(GET_REDMASK(v)); 1579 green_bits = _mesa_bitcount(GET_GREENMASK(v)); 1580 blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); 1581 alpha_bits = 0; 1582 } 1583 else { 1584 /* this is an approximation */ 1585 int depth; 1586 depth = GET_VISUAL_DEPTH(v); 1587 red_bits = depth / 3; 1588 depth -= red_bits; 1589 green_bits = depth / 2; 1590 depth -= green_bits; 1591 blue_bits = depth; 1592 alpha_bits = 0; 1593 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); 1594 } 1595 } 1596 1597 if (alpha_flag && alpha_bits == 0) 1598 alpha_bits = 8; 1599 1600 _mesa_initialize_visual( &v->mesa_visual, 1601 rgb_flag, db_flag, stereo_flag, 1602 red_bits, green_bits, 1603 blue_bits, alpha_bits, 1604 v->mesa_visual.indexBits, 1605 depth_size, 1606 stencil_size, 1607 accum_red_size, accum_green_size, 1608 accum_blue_size, accum_alpha_size, 1609 0 ); 1610 1611 /* XXX minor hack */ 1612 v->mesa_visual.level = level; 1613 return v; 1614} 1615 1616 1617void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ) 1618{ 1619 v->display = dpy; 1620} 1621 1622 1623void XMesaDestroyVisual( XMesaVisual v ) 1624{ 1625#ifndef XFree86Server 1626 _mesa_free(v->visinfo); 1627#endif 1628 _mesa_free(v); 1629} 1630 1631 1632 1633/** 1634 * Create a new XMesaContext. 1635 * \param v the XMesaVisual 1636 * \param share_list another XMesaContext with which to share display 1637 * lists or NULL if no sharing is wanted. 1638 * \return an XMesaContext or NULL if error. 1639 */ 1640XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 1641{ 1642 static GLboolean firstTime = GL_TRUE; 1643 XMesaContext c; 1644 GLcontext *mesaCtx; 1645 struct dd_function_table functions; 1646 TNLcontext *tnl; 1647 1648 if (firstTime) { 1649 _glthread_INIT_MUTEX(_xmesa_lock); 1650 firstTime = GL_FALSE; 1651 } 1652 1653 /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ 1654 c = (XMesaContext) CALLOC_STRUCT(xmesa_context); 1655 if (!c) 1656 return NULL; 1657 1658 mesaCtx = &(c->mesa); 1659 1660 /* initialize with default driver functions, then plug in XMesa funcs */ 1661 _mesa_init_driver_functions(&functions); 1662 xmesa_init_driver_functions(v, &functions); 1663 if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual, 1664 share_list ? &(share_list->mesa) : (GLcontext *) NULL, 1665 &functions, (void *) c)) { 1666 _mesa_free(c); 1667 return NULL; 1668 } 1669 1670 _mesa_enable_sw_extensions(mesaCtx); 1671 _mesa_enable_1_3_extensions(mesaCtx); 1672 _mesa_enable_1_4_extensions(mesaCtx); 1673 _mesa_enable_1_5_extensions(mesaCtx); 1674 _mesa_enable_2_0_extensions(mesaCtx); 1675#if ENABLE_EXT_texure_compression_s3tc 1676 if (c->Mesa_DXTn) { 1677 _mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc"); 1678 _mesa_enable_extension(mesaCtx, "GL_S3_s3tc"); 1679 } 1680 _mesa_enable_extension(mesaCtx, "GL_3DFX_texture_compression_FXT1"); 1681#endif 1682#if ENABLE_EXT_timer_query 1683 _mesa_enable_extension(mesaCtx, "GL_EXT_timer_query"); 1684#endif 1685 1686 /* finish up xmesa context initializations */ 1687 c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE; 1688 c->xm_visual = v; 1689 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ 1690 c->display = v->display; 1691 c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ 1692 1693 /* Initialize the software rasterizer and helper modules. 1694 */ 1695 if (!_swrast_CreateContext( mesaCtx ) || 1696 !_ac_CreateContext( mesaCtx ) || 1697 !_tnl_CreateContext( mesaCtx ) || 1698 !_swsetup_CreateContext( mesaCtx )) { 1699 _mesa_free_context_data(&c->mesa); 1700 _mesa_free(c); 1701 return NULL; 1702 } 1703 1704 /* tnl setup */ 1705 tnl = TNL_CONTEXT(mesaCtx); 1706 tnl->Driver.RunPipeline = _tnl_run_pipeline; 1707 /* swrast setup */ 1708 xmesa_register_swrast_functions( mesaCtx ); 1709 _swsetup_Wakeup(mesaCtx); 1710 1711 return c; 1712} 1713 1714 1715 1716void XMesaDestroyContext( XMesaContext c ) 1717{ 1718 GLcontext *mesaCtx = &c->mesa; 1719#ifdef FX 1720 XMesaBuffer xmbuf = XMESA_BUFFER(mesaCtx->DrawBuffer); 1721 1722 if (xmbuf && xmbuf->FXctx) 1723 fxMesaDestroyContext(xmbuf->FXctx); 1724#endif 1725 _swsetup_DestroyContext( mesaCtx ); 1726 _swrast_DestroyContext( mesaCtx ); 1727 _tnl_DestroyContext( mesaCtx ); 1728 _ac_DestroyContext( mesaCtx ); 1729 _mesa_free_context_data( mesaCtx ); 1730 _mesa_free( c ); 1731} 1732 1733 1734 1735/* 1736 * XXX this isn't a public function! It's a hack for the 3Dfx driver. 1737 * Create a new XMesaBuffer from an X window. 1738 * Input: v - the XMesaVisual 1739 * w - the window 1740 * c - the context 1741 * Return: new XMesaBuffer or NULL if error 1742 */ 1743XMesaBuffer 1744XMesaCreateWindowBuffer2(XMesaVisual v, XMesaWindow w, XMesaContext c) 1745{ 1746#ifndef XFree86Server 1747 XWindowAttributes attr; 1748#endif 1749#ifdef FX 1750 char *fxEnvVar; 1751#endif 1752 int client = 0; 1753 XMesaBuffer b; 1754 XMesaColormap cmap; 1755 1756 assert(v); 1757 (void) c; 1758 1759 /* Check that window depth matches visual depth */ 1760#ifdef XFree86Server 1761 client = CLIENT_ID(((XMesaDrawable)w)->id); 1762 1763 if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) { 1764 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", 1765 GET_VISUAL_DEPTH(v), ((XMesaDrawable) w)->depth); 1766 return NULL; 1767 } 1768#else 1769 XGetWindowAttributes( v->display, w, &attr ); 1770 1771 if (GET_VISUAL_DEPTH(v) != attr.depth) { 1772 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", 1773 GET_VISUAL_DEPTH(v), attr.depth); 1774 return NULL; 1775 } 1776#endif 1777 1778 /* Find colormap */ 1779#ifdef XFree86Server 1780 cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); 1781#else 1782 if (attr.colormap) { 1783 cmap = attr.colormap; 1784 } 1785 else { 1786 _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); 1787 /* this is weird, a window w/out a colormap!? */ 1788 /* OK, let's just allocate a new one and hope for the best */ 1789 cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); 1790 } 1791#endif 1792 1793 b = alloc_xmesa_buffer(v, WINDOW, cmap); 1794 if (!b) { 1795 return NULL; 1796 } 1797 1798 if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode, 1799 (XMesaDrawable) w, cmap )) { 1800 free_xmesa_buffer(client, b); 1801 return NULL; 1802 } 1803 1804#ifdef FX 1805 fxEnvVar = _mesa_getenv("MESA_GLX_FX"); 1806 if (fxEnvVar) { 1807 if (fxEnvVar[0]!='d') { 1808 int attribs[100]; 1809 int numAttribs = 0; 1810 int hw; 1811 if (v->mesa_visual.depthBits > 0) { 1812 attribs[numAttribs++] = FXMESA_DEPTH_SIZE; 1813 attribs[numAttribs++] = v->mesa_visual.depthBits; 1814 } 1815 if (v->mesa_visual.doubleBufferMode) { 1816 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; 1817 } 1818 if (v->mesa_visual.accumRedBits > 0) { 1819 attribs[numAttribs++] = FXMESA_ACCUM_SIZE; 1820 attribs[numAttribs++] = v->mesa_visual.accumRedBits; 1821 } 1822 if (v->mesa_visual.stencilBits > 0) { 1823 attribs[numAttribs++] = FXMESA_STENCIL_SIZE; 1824 attribs[numAttribs++] = v->mesa_visual.stencilBits; 1825 } 1826 if (v->mesa_visual.alphaBits > 0) { 1827 attribs[numAttribs++] = FXMESA_ALPHA_SIZE; 1828 attribs[numAttribs++] = v->mesa_visual.alphaBits; 1829 } 1830 if (1) { 1831 attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; 1832 attribs[numAttribs++] = (int) &(c->mesa); 1833 } 1834 attribs[numAttribs++] = FXMESA_NONE; 1835 1836 /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */ 1837 hw = fxMesaSelectCurrentBoard(0); 1838 1839 /* if these fail, there's a new bug somewhere */ 1840 ASSERT(b->mesa_buffer.Width > 0); 1841 ASSERT(b->mesa_buffer.Height > 0); 1842 1843 if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) { 1844 b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width, 1845 b->mesa_buffer.Height, attribs); 1846 if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) { 1847 b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; 1848 if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) { 1849 b->FXwindowHack = GL_TRUE; 1850 FX_grSstControl(GR_CONTROL_DEACTIVATE); 1851 } 1852 else { 1853 b->FXwindowHack = GL_FALSE; 1854 } 1855 } 1856 } 1857 else { 1858 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') 1859 b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, 1860 GR_REFRESH_75Hz, attribs); 1861 else 1862 b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width, 1863 b->mesa_buffer.Height, attribs); 1864 b->FXisHackUsable = GL_FALSE; 1865 b->FXwindowHack = GL_FALSE; 1866 } 1867 /* 1868 fprintf(stderr, 1869 "voodoo %d, wid %d height %d hack: usable %d active %d\n", 1870 hw, b->mesa_buffer.Width, b->mesa_buffer.Height, 1871 b->FXisHackUsable, b->FXwindowHack); 1872 */ 1873 } 1874 } 1875 else { 1876 _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n"); 1877 _mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n"); 1878 _mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n"); 1879 _mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); 1880 } 1881#endif 1882 1883 return b; 1884} 1885 1886 1887XMesaBuffer 1888XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) 1889{ 1890 return XMesaCreateWindowBuffer2( v, w, NULL ); 1891} 1892 1893 1894/** 1895 * Create a new XMesaBuffer from an X pixmap. 1896 * 1897 * \param v the XMesaVisual 1898 * \param p the pixmap 1899 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or 1900 * \c GLX_DIRECT_COLOR visual for the pixmap 1901 * \returns new XMesaBuffer or NULL if error 1902 */ 1903XMesaBuffer 1904XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap) 1905{ 1906 int client = 0; 1907 XMesaBuffer b; 1908 1909 assert(v); 1910 1911 b = alloc_xmesa_buffer(v, PIXMAP, cmap); 1912 if (!b) { 1913 return NULL; 1914 } 1915 1916#ifdef XFree86Server 1917 client = CLIENT_ID(((XMesaDrawable)p)->id); 1918#endif 1919 1920 if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, 1921 (XMesaDrawable) p, cmap)) { 1922 free_xmesa_buffer(client, b); 1923 return NULL; 1924 } 1925 1926 return b; 1927} 1928 1929 1930 1931XMesaBuffer 1932XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap, 1933 unsigned int width, unsigned int height) 1934{ 1935#ifdef XFree86Server 1936 return 0; 1937#else 1938 int client = 0; 1939 XMesaWindow root; 1940 XMesaDrawable drawable; /* X Pixmap Drawable */ 1941 XMesaBuffer b; 1942 1943 b = alloc_xmesa_buffer(v, PBUFFER, cmap); 1944 if (!b) { 1945 return NULL; 1946 } 1947 1948 /* allocate pixmap for front buffer */ 1949 root = RootWindow( v->display, v->visinfo->screen ); 1950 drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth ); 1951 1952 if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, 1953 drawable, cmap)) { 1954 free_xmesa_buffer(client, b); 1955 return NULL; 1956 } 1957 1958 return b; 1959#endif 1960} 1961 1962 1963 1964/* 1965 * Deallocate an XMesaBuffer structure and all related info. 1966 */ 1967void XMesaDestroyBuffer( XMesaBuffer b ) 1968{ 1969 int client = 0; 1970 1971#ifdef XFree86Server 1972 if (b->frontxrb->drawable) 1973 client = CLIENT_ID(b->frontxrb->drawable->id); 1974#endif 1975 1976 if (b->gc) XMesaFreeGC( b->xm_visual->display, b->gc ); 1977 if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc ); 1978 if (b->swapgc) XMesaFreeGC( b->xm_visual->display, b->swapgc ); 1979 1980 if (b->xm_visual->mesa_visual.doubleBufferMode) 1981 { 1982 if (b->backxrb->ximage) { 1983#if defined(USE_XSHM) && !defined(XFree86Server) 1984 if (b->shm) { 1985 XShmDetach( b->xm_visual->display, &b->shminfo ); 1986 XDestroyImage( b->backxrb->ximage ); 1987 shmdt( b->shminfo.shmaddr ); 1988 } 1989 else 1990#endif 1991 XMesaDestroyImage( b->backxrb->ximage ); 1992 } 1993 if (b->backxrb->pixmap) { 1994 XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap ); 1995 if (b->xm_visual->hpcr_clear_flag) { 1996 XMesaFreePixmap( b->xm_visual->display, 1997 b->xm_visual->hpcr_clear_pixmap ); 1998 XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); 1999 } 2000 } 2001 } 2002 if (b->rowimage) { 2003 _mesa_free( b->rowimage->data ); 2004 b->rowimage->data = NULL; 2005 XMesaDestroyImage( b->rowimage ); 2006 } 2007 2008 free_xmesa_buffer(client, b); 2009} 2010 2011 2012 2013/* 2014 * Bind buffer b to context c and make c the current rendering context. 2015 */ 2016GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) 2017{ 2018 return XMesaMakeCurrent2( c, b, b ); 2019} 2020 2021 2022/* 2023 * Bind buffer b to context c and make c the current rendering context. 2024 */ 2025GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, 2026 XMesaBuffer readBuffer ) 2027{ 2028 if (c) { 2029 if (!drawBuffer || !readBuffer) 2030 return GL_FALSE; /* must specify buffers! */ 2031 2032#ifdef FX 2033 if (drawBuffer->FXctx) { 2034 fxMesaMakeCurrent(drawBuffer->FXctx); 2035 2036 c->xm_buffer = drawBuffer; 2037 2038 return GL_TRUE; 2039 } 2040#endif 2041 if (&(c->mesa) == _mesa_get_current_context() 2042 && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer 2043 && c->mesa.ReadBuffer == &readBuffer->mesa_buffer 2044 && ((XMesaBuffer) c->mesa.DrawBuffer)->wasCurrent) { 2045 /* same context and buffer, do nothing */ 2046 return GL_TRUE; 2047 } 2048 2049 c->xm_buffer = drawBuffer; 2050 2051 /* Call this periodically to detect when the user has begun using 2052 * GL rendering from multiple threads. 2053 */ 2054 _glapi_check_multithread(); 2055 2056 _mesa_make_current(&(c->mesa), 2057 &drawBuffer->mesa_buffer, 2058 &readBuffer->mesa_buffer); 2059 2060 if (c->xm_visual->mesa_visual.rgbMode) { 2061 /* 2062 * Must recompute and set these pixel values because colormap 2063 * can be different for different windows. 2064 */ 2065 c->clearpixel = xmesa_color_to_pixel( &c->mesa, 2066 c->clearcolor[0], 2067 c->clearcolor[1], 2068 c->clearcolor[2], 2069 c->clearcolor[3], 2070 c->xm_visual->undithered_pf); 2071 XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel); 2072 } 2073 2074 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 2075 drawBuffer->wasCurrent = GL_TRUE; 2076 } 2077 else { 2078 /* Detach */ 2079 _mesa_make_current( NULL, NULL, NULL ); 2080 } 2081 return GL_TRUE; 2082} 2083 2084 2085/* 2086 * Unbind the context c from its buffer. 2087 */ 2088GLboolean XMesaUnbindContext( XMesaContext c ) 2089{ 2090 /* A no-op for XFree86 integration purposes */ 2091 return GL_TRUE; 2092} 2093 2094 2095XMesaContext XMesaGetCurrentContext( void ) 2096{ 2097 GET_CURRENT_CONTEXT(ctx); 2098 if (ctx) { 2099 XMesaContext xmesa = XMESA_CONTEXT(ctx); 2100 return xmesa; 2101 } 2102 else { 2103 return 0; 2104 } 2105} 2106 2107 2108XMesaBuffer XMesaGetCurrentBuffer( void ) 2109{ 2110 GET_CURRENT_CONTEXT(ctx); 2111 if (ctx) { 2112 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); 2113 return xmbuf; 2114 } 2115 else { 2116 return 0; 2117 } 2118} 2119 2120 2121/* New in Mesa 3.1 */ 2122XMesaBuffer XMesaGetCurrentReadBuffer( void ) 2123{ 2124 GET_CURRENT_CONTEXT(ctx); 2125 if (ctx) { 2126 return (XMesaBuffer) (ctx->ReadBuffer); 2127 } 2128 else { 2129 return 0; 2130 } 2131} 2132 2133 2134GLboolean XMesaForceCurrent(XMesaContext c) 2135{ 2136 if (c) { 2137 if (&(c->mesa) != _mesa_get_current_context()) { 2138 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer); 2139 } 2140 } 2141 else { 2142 _mesa_make_current(NULL, NULL, NULL); 2143 } 2144 return GL_TRUE; 2145} 2146 2147 2148GLboolean XMesaLoseCurrent(XMesaContext c) 2149{ 2150 (void) c; 2151 _mesa_make_current(NULL, NULL, NULL); 2152 return GL_TRUE; 2153} 2154 2155 2156/* 2157 * Switch 3Dfx support hack between window and full-screen mode. 2158 */ 2159GLboolean XMesaSetFXmode( GLint mode ) 2160{ 2161#ifdef FX 2162 const char *fx = _mesa_getenv("MESA_GLX_FX"); 2163 if (fx && fx[0] != 'd') { 2164 GET_CURRENT_CONTEXT(ctx); 2165 GrHwConfiguration hw; 2166 if (!FX_grSstQueryHardware(&hw)) { 2167 /*fprintf(stderr, "!grSstQueryHardware\n");*/ 2168 return GL_FALSE; 2169 } 2170 if (hw.num_sst < 1) { 2171 /*fprintf(stderr, "hw.num_sst < 1\n");*/ 2172 return GL_FALSE; 2173 } 2174 if (ctx) { 2175 /* [dBorca] Hack alert: 2176 * oh, this is sooo wrong: ctx above is 2177 * really an fxMesaContext, not an XMesaContext 2178 */ 2179 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); 2180 if (mode == XMESA_FX_WINDOW) { 2181 if (xmbuf->FXisHackUsable) { 2182 FX_grSstControl(GR_CONTROL_DEACTIVATE); 2183 xmbuf->FXwindowHack = GL_TRUE; 2184 return GL_TRUE; 2185 } 2186 } 2187 else if (mode == XMESA_FX_FULLSCREEN) { 2188 FX_grSstControl(GR_CONTROL_ACTIVATE); 2189 xmbuf->FXwindowHack = GL_FALSE; 2190 return GL_TRUE; 2191 } 2192 else { 2193 /* Error: Bad mode value */ 2194 } 2195 } 2196 } 2197 /*fprintf(stderr, "fallthrough\n");*/ 2198#else 2199 (void) mode; 2200#endif 2201 return GL_FALSE; 2202} 2203 2204 2205 2206#ifdef FX 2207/* 2208 * Read image from VooDoo frame buffer into X/Mesa's back XImage. 2209 */ 2210static void FXgetImage( XMesaBuffer b ) 2211{ 2212 GET_CURRENT_CONTEXT(ctx); 2213 static unsigned short pixbuf[MAX_WIDTH]; 2214 GLuint x, y; 2215 int xpos, ypos; 2216 XMesaWindow root; 2217 unsigned int bw, depth, width, height; 2218 XMesaContext xmesa = XMESA_CONTEXT(ctx); 2219 2220#ifdef XFree86Server 2221 x = b->frontxrb->pixmap->x; 2222 y = b->frontxrb->pixmap->y; 2223 width = b->frontxrb->pixmap->width; 2224 height = b->frontxrb->pixmap->height; 2225 depth = b->frontxrb->pixmap->depth; 2226#else 2227 XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap, 2228 &root, &xpos, &ypos, &width, &height, &bw, &depth); 2229#endif 2230 if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) { 2231 b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width); 2232 b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height); 2233 if (b->mesa_buffer.Width & 1) 2234 b->mesa_buffer.Width--; /* prevent odd width */ 2235 xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height); 2236 } 2237 2238 /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */ 2239 /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */ 2240 if (b->xm_visual->undithered_pf==PF_5R6G5B) { 2241 /* Special case: 16bpp RGB */ 2242 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ 2243 0, b->FXctx->height - b->mesa_buffer.Height, /*pos*/ 2244 b->mesa_buffer.Width, b->mesa_buffer.Height, /* size */ 2245 b->mesa_buffer.Width * sizeof(GLushort), /* stride */ 2246 b->backxrb->ximage->data); /* dest buffer */ 2247 } 2248 else if (b->xm_visual->dithered_pf==PF_Dither 2249 && GET_VISUAL_DEPTH(b->xm_visual)==8) { 2250 /* Special case: 8bpp RGB */ 2251 for (y=0;y<b->mesa_buffer.Height;y++) { 2252 GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data 2253 + b->backxrb->ximage->bytes_per_line * y; 2254 XDITHER_SETUP(y); 2255 2256 /* read row from 3Dfx frame buffer */ 2257 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2258 0, b->FXctx->height-(b->mesa_buffer.Height-y), 2259 b->mesa_buffer.Width, 1, 2260 0, 2261 pixbuf ); 2262 2263 /* write to XImage back buffer */ 2264 for (x=0;x<b->mesa_buffer.Width;x++) { 2265 GLubyte r = (pixbuf[x] & 0xf800) >> 8; 2266 GLubyte g = (pixbuf[x] & 0x07e0) >> 3; 2267 GLubyte b = (pixbuf[x] & 0x001f) << 3; 2268 *ptr++ = XDITHER( x, r, g, b); 2269 } 2270 } 2271 } 2272 else { 2273 /* General case: slow! */ 2274 for (y=0;y<b->mesa_buffer.Height;y++) { 2275 /* read row from 3Dfx frame buffer */ 2276 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2277 0, b->FXctx->height-(b->mesa_buffer.Height-y), 2278 b->mesa_buffer.Width, 1, 2279 0, 2280 pixbuf ); 2281 2282 /* write to XImage back buffer */ 2283 for (x=0;x<b->mesa_buffer.Width;x++) { 2284 XMesaPutPixel(b->backxrb->ximage,x,y, 2285 xmesa_color_to_pixel(ctx, 2286 (pixbuf[x] & 0xf800) >> 8, 2287 (pixbuf[x] & 0x07e0) >> 3, 2288 (pixbuf[x] & 0x001f) << 3, 2289 0xff, 2290 b->xm_visual->undithered_pf)); 2291 } 2292 } 2293 } 2294 /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */ 2295} 2296#endif 2297 2298 2299/* 2300 * Copy the back buffer to the front buffer. If there's no back buffer 2301 * this is a no-op. 2302 */ 2303void XMesaSwapBuffers( XMesaBuffer b ) 2304{ 2305 GET_CURRENT_CONTEXT(ctx); 2306 2307 if (!b->backxrb) { 2308 /* single buffered */ 2309 return; 2310 } 2311 2312 /* If we're swapping the buffer associated with the current context 2313 * we have to flush any pending rendering commands first. 2314 */ 2315 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2316 _mesa_notifySwapBuffers(ctx); 2317 2318 if (b->db_mode) { 2319#ifdef FX 2320 if (b->FXctx) { 2321 fxMesaSwapBuffers(); 2322 2323 if (b->FXwindowHack) 2324 FXgetImage(b); 2325 else 2326 return; 2327 } 2328#endif 2329 if (b->backxrb->ximage) { 2330 /* Copy Ximage from host's memory to server's window */ 2331#if defined(USE_XSHM) && !defined(XFree86Server) 2332 if (b->shm) { 2333 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2334 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 2335 b->swapgc, 2336 b->backxrb->ximage, 0, 0, 2337 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 2338 False ); 2339 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2340 } 2341 else 2342#endif 2343 { 2344 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2345 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 2346 b->swapgc, 2347 b->backxrb->ximage, 0, 0, 2348 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height ); 2349 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2350 } 2351 } 2352 else { 2353 /* Copy pixmap to window on server */ 2354 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2355 XMesaCopyArea( b->xm_visual->display, 2356 b->backxrb->pixmap, /* source drawable */ 2357 b->frontxrb->drawable, /* dest. drawable */ 2358 b->swapgc, 2359 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 2360 0, 0 /* dest region */ 2361 ); 2362 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2363 } 2364 } 2365#if !defined(XFree86Server) 2366 XSync( b->xm_visual->display, False ); 2367#endif 2368} 2369 2370 2371 2372/* 2373 * Copy sub-region of back buffer to front buffer 2374 */ 2375void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 2376{ 2377 GET_CURRENT_CONTEXT(ctx); 2378 2379 /* If we're swapping the buffer associated with the current context 2380 * we have to flush any pending rendering commands first. 2381 */ 2382 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2383 _mesa_notifySwapBuffers(ctx); 2384 2385 if (!b->backxrb) { 2386 /* single buffered */ 2387 return; 2388 } 2389 2390 if (b->db_mode) { 2391 int yTop = b->mesa_buffer.Height - y - height; 2392#ifdef FX 2393 if (b->FXctx) { 2394 fxMesaSwapBuffers(); 2395 if (b->FXwindowHack) 2396 FXgetImage(b); 2397 else 2398 return; 2399 } 2400#endif 2401 if (b->backxrb->ximage) { 2402 /* Copy Ximage from host's memory to server's window */ 2403#if defined(USE_XSHM) && !defined(XFree86Server) 2404 if (b->shm) { 2405 /* XXX assuming width and height aren't too large! */ 2406 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 2407 b->swapgc, 2408 b->backxrb->ximage, x, yTop, 2409 x, yTop, width, height, False ); 2410 /* wait for finished event??? */ 2411 } 2412 else 2413#endif 2414 { 2415 /* XXX assuming width and height aren't too large! */ 2416 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 2417 b->swapgc, 2418 b->backxrb->ximage, x, yTop, 2419 x, yTop, width, height ); 2420 } 2421 } 2422 else { 2423 /* Copy pixmap to window on server */ 2424 XMesaCopyArea( b->xm_visual->display, 2425 b->backxrb->pixmap, /* source drawable */ 2426 b->frontxrb->drawable, /* dest. drawable */ 2427 b->swapgc, 2428 x, yTop, width, height, /* source region */ 2429 x, yTop /* dest region */ 2430 ); 2431 } 2432 } 2433} 2434 2435 2436/* 2437 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function 2438 * is a way to get "under the hood" of X/Mesa so one can manipulate the 2439 * back buffer directly. 2440 * Output: pixmap - pointer to back buffer's Pixmap, or 0 2441 * ximage - pointer to back buffer's XImage, or NULL 2442 * Return: GL_TRUE = context is double buffered 2443 * GL_FALSE = context is single buffered 2444 */ 2445#ifndef XFree86Server 2446GLboolean XMesaGetBackBuffer( XMesaBuffer b, 2447 XMesaPixmap *pixmap, 2448 XMesaImage **ximage ) 2449{ 2450 if (b->db_mode) { 2451 if (pixmap) 2452 *pixmap = b->backxrb->pixmap; 2453 if (ximage) 2454 *ximage = b->backxrb->ximage; 2455 return GL_TRUE; 2456 } 2457 else { 2458 *pixmap = 0; 2459 *ximage = NULL; 2460 return GL_FALSE; 2461 } 2462} 2463#endif /* XFree86Server */ 2464 2465 2466/* 2467 * Return the depth buffer associated with an XMesaBuffer. 2468 * Input: b - the XMesa buffer handle 2469 * Output: width, height - size of buffer in pixels 2470 * bytesPerValue - bytes per depth value (2 or 4) 2471 * buffer - pointer to depth buffer values 2472 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 2473 */ 2474GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, 2475 GLint *bytesPerValue, void **buffer ) 2476{ 2477 struct gl_renderbuffer *rb 2478 = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer; 2479 if (!rb || !rb->Data) { 2480 *width = 0; 2481 *height = 0; 2482 *bytesPerValue = 0; 2483 *buffer = 0; 2484 return GL_FALSE; 2485 } 2486 else { 2487 *width = b->mesa_buffer.Width; 2488 *height = b->mesa_buffer.Height; 2489 *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 2490 ? sizeof(GLushort) : sizeof(GLuint); 2491 *buffer = rb->Data; 2492 return GL_TRUE; 2493 } 2494} 2495 2496 2497void XMesaFlush( XMesaContext c ) 2498{ 2499 if (c && c->xm_visual) { 2500#ifdef XFree86Server 2501 /* NOT_NEEDED */ 2502#else 2503 XSync( c->xm_visual->display, False ); 2504#endif 2505 } 2506} 2507 2508 2509 2510const char *XMesaGetString( XMesaContext c, int name ) 2511{ 2512 (void) c; 2513 if (name==XMESA_VERSION) { 2514 return "5.0"; 2515 } 2516 else if (name==XMESA_EXTENSIONS) { 2517 return ""; 2518 } 2519 else { 2520 return NULL; 2521 } 2522} 2523 2524 2525 2526XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) 2527{ 2528 XMesaBuffer b; 2529 for (b=XMesaBufferList; b; b=b->Next) { 2530 if (b->frontxrb->drawable == d && b->display == dpy) { 2531 return b; 2532 } 2533 } 2534 return NULL; 2535} 2536 2537 2538/** 2539 * Free/destroy all XMesaBuffers associated with given display. 2540 */ 2541void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) 2542{ 2543 XMesaBuffer b, next; 2544 for (b = XMesaBufferList; b; b = next) { 2545 next = b->Next; 2546 if (b->display == dpy) { 2547 free_xmesa_buffer(0, b); 2548 } 2549 } 2550} 2551 2552 2553/* 2554 * Look for XMesaBuffers whose X window has been destroyed. 2555 * Deallocate any such XMesaBuffers. 2556 */ 2557void XMesaGarbageCollect( void ) 2558{ 2559 XMesaBuffer b, next; 2560 for (b=XMesaBufferList; b; b=next) { 2561 next = b->Next; 2562 if (b->display && b->frontxrb->drawable && b->type == WINDOW) { 2563#ifdef XFree86Server 2564 /* NOT_NEEDED */ 2565#else 2566 XSync(b->display, False); 2567 if (!window_exists( b->display, b->frontxrb->drawable )) { 2568 /* found a dead window, free the ancillary info */ 2569 XMesaDestroyBuffer( b ); 2570 } 2571#endif 2572 } 2573 } 2574} 2575 2576 2577void XMesaReset( void ) 2578{ 2579 while (XMesaBufferList) 2580 XMesaDestroyBuffer(XMesaBufferList); 2581 2582 XMesaBufferList = NULL; 2583} 2584 2585 2586unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, 2587 GLfloat red, GLfloat green, 2588 GLfloat blue, GLfloat alpha ) 2589{ 2590 GLcontext *ctx = &xmesa->mesa; 2591 GLint r = (GLint) (red * 255.0F); 2592 GLint g = (GLint) (green * 255.0F); 2593 GLint b = (GLint) (blue * 255.0F); 2594 GLint a = (GLint) (alpha * 255.0F); 2595 2596 switch (xmesa->pixelformat) { 2597 case PF_Index: 2598 return 0; 2599 case PF_Truecolor: 2600 { 2601 unsigned long p; 2602 PACK_TRUECOLOR( p, r, g, b ); 2603 return p; 2604 } 2605 case PF_8A8B8G8R: 2606 return PACK_8A8B8G8R( r, g, b, a ); 2607 case PF_8A8R8G8B: 2608 return PACK_8A8R8G8B( r, g, b, a ); 2609 case PF_8R8G8B: 2610 return PACK_8R8G8B( r, g, b ); 2611 case PF_5R6G5B: 2612 return PACK_5R6G5B( r, g, b ); 2613 case PF_Dither: 2614 { 2615 DITHER_SETUP; 2616 return DITHER( x, y, r, g, b ); 2617 } 2618 case PF_1Bit: 2619 /* 382 = (3*255)/2 */ 2620 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 2621 case PF_HPCR: 2622 return DITHER_HPCR(x, y, r, g, b); 2623 case PF_Lookup: 2624 { 2625 LOOKUP_SETUP; 2626 return LOOKUP( r, g, b ); 2627 } 2628 case PF_Grayscale: 2629 return GRAY_RGB( r, g, b ); 2630 case PF_Dither_5R6G5B: 2631 /* fall through */ 2632 case PF_Dither_True: 2633 { 2634 unsigned long p; 2635 PACK_TRUEDITHER(p, x, y, r, g, b); 2636 return p; 2637 } 2638 default: 2639 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); 2640 } 2641 return 0; 2642} 2643 2644 2645/* 2646 * This is typically called when the window size changes and we need 2647 * to reallocate the buffer's back/depth/stencil/accum buffers. 2648 */ 2649void XMesaResizeBuffers( XMesaBuffer b ) 2650{ 2651#ifdef XFree86Server 2652 GLuint winwidth, winheight; 2653 GET_CURRENT_CONTEXT(ctx); 2654 2655 winwidth = MIN2(b->frontxrb->drawable->width, MAX_WIDTH); 2656 winheight = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT); 2657 2658 xmesa_resize_buffers(ctx, &(b->mesa_buffer), winwidth, winheight); 2659#else 2660 Window root; 2661 int xpos, ypos; 2662 unsigned int width, height, bw, depth; 2663 GET_CURRENT_CONTEXT(ctx); 2664 XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap, 2665 &root, &xpos, &ypos, &width, &height, &bw, &depth); 2666 xmesa_resize_buffers(ctx, &(b->mesa_buffer), width, height); 2667#endif 2668} 2669 2670