xm_api.c revision 6c06ce281aa7a7e20eab1934f573bc5c673d41cb
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.1 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 "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 assert(visinfo->nplanes > 0); 1567 v->nplanes = visinfo->nplanes; 1568 v->ColormapEntries = visinfo->ColormapEntries; 1569 1570 v->mesa_visual.redMask = visinfo->redMask; 1571 v->mesa_visual.greenMask = visinfo->greenMask; 1572 v->mesa_visual.blueMask = visinfo->blueMask; 1573 v->mesa_visual.visualID = visinfo->vid; 1574 v->mesa_visual.screen = 0; /* FIXME: What should be done here? */ 1575#else 1576 v->mesa_visual.redMask = visinfo->red_mask; 1577 v->mesa_visual.greenMask = visinfo->green_mask; 1578 v->mesa_visual.blueMask = visinfo->blue_mask; 1579 v->mesa_visual.visualID = visinfo->visualid; 1580 v->mesa_visual.screen = visinfo->screen; 1581#endif 1582 1583#if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus)) 1584 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class); 1585#else 1586 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); 1587#endif 1588 1589 v->mesa_visual.visualRating = visualCaveat; 1590 1591 (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 ); 1592 1593 { 1594 const int xclass = v->mesa_visual.visualType; 1595 if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) { 1596 red_bits = _mesa_bitcount(GET_REDMASK(v)); 1597 green_bits = _mesa_bitcount(GET_GREENMASK(v)); 1598 blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); 1599 alpha_bits = 0; 1600 } 1601 else { 1602 /* this is an approximation */ 1603 int depth; 1604 depth = GET_VISUAL_DEPTH(v); 1605 red_bits = depth / 3; 1606 depth -= red_bits; 1607 green_bits = depth / 2; 1608 depth -= green_bits; 1609 blue_bits = depth; 1610 alpha_bits = 0; 1611 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); 1612 } 1613 } 1614 1615 if (alpha_flag && alpha_bits == 0) 1616 alpha_bits = 8; 1617 1618 _mesa_initialize_visual( &v->mesa_visual, 1619 rgb_flag, db_flag, stereo_flag, 1620 red_bits, green_bits, 1621 blue_bits, alpha_bits, 1622 v->mesa_visual.indexBits, 1623 depth_size, 1624 stencil_size, 1625 accum_red_size, accum_green_size, 1626 accum_blue_size, accum_alpha_size, 1627 0 ); 1628 1629 /* XXX minor hack */ 1630 v->mesa_visual.level = level; 1631 return v; 1632} 1633 1634 1635void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ) 1636{ 1637 v->display = dpy; 1638} 1639 1640 1641void XMesaDestroyVisual( XMesaVisual v ) 1642{ 1643#ifndef XFree86Server 1644 _mesa_free(v->visinfo); 1645#endif 1646 _mesa_free(v); 1647} 1648 1649 1650 1651/** 1652 * Create a new XMesaContext. 1653 * \param v the XMesaVisual 1654 * \param share_list another XMesaContext with which to share display 1655 * lists or NULL if no sharing is wanted. 1656 * \return an XMesaContext or NULL if error. 1657 */ 1658XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 1659{ 1660 static GLboolean firstTime = GL_TRUE; 1661 XMesaContext c; 1662 GLcontext *mesaCtx; 1663 struct dd_function_table functions; 1664 TNLcontext *tnl; 1665 1666 if (firstTime) { 1667 _glthread_INIT_MUTEX(_xmesa_lock); 1668 firstTime = GL_FALSE; 1669 } 1670 1671 /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ 1672 c = (XMesaContext) CALLOC_STRUCT(xmesa_context); 1673 if (!c) 1674 return NULL; 1675 1676 mesaCtx = &(c->mesa); 1677 1678 /* initialize with default driver functions, then plug in XMesa funcs */ 1679 _mesa_init_driver_functions(&functions); 1680 xmesa_init_driver_functions(v, &functions); 1681 if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual, 1682 share_list ? &(share_list->mesa) : (GLcontext *) NULL, 1683 &functions, (void *) c)) { 1684 _mesa_free(c); 1685 return NULL; 1686 } 1687 1688 _mesa_enable_sw_extensions(mesaCtx); 1689 _mesa_enable_1_3_extensions(mesaCtx); 1690 _mesa_enable_1_4_extensions(mesaCtx); 1691 _mesa_enable_1_5_extensions(mesaCtx); 1692 _mesa_enable_2_0_extensions(mesaCtx); 1693#if ENABLE_EXT_texure_compression_s3tc 1694 if (c->Mesa_DXTn) { 1695 _mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc"); 1696 _mesa_enable_extension(mesaCtx, "GL_S3_s3tc"); 1697 } 1698 _mesa_enable_extension(mesaCtx, "GL_3DFX_texture_compression_FXT1"); 1699#endif 1700#if ENABLE_EXT_timer_query 1701 _mesa_enable_extension(mesaCtx, "GL_EXT_timer_query"); 1702#endif 1703 1704 /* finish up xmesa context initializations */ 1705 c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE; 1706 c->xm_visual = v; 1707 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ 1708 c->display = v->display; 1709 c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ 1710 1711 /* Initialize the software rasterizer and helper modules. 1712 */ 1713 if (!_swrast_CreateContext( mesaCtx ) || 1714 !_ac_CreateContext( mesaCtx ) || 1715 !_tnl_CreateContext( mesaCtx ) || 1716 !_swsetup_CreateContext( mesaCtx )) { 1717 _mesa_free_context_data(&c->mesa); 1718 _mesa_free(c); 1719 return NULL; 1720 } 1721 1722 /* tnl setup */ 1723 tnl = TNL_CONTEXT(mesaCtx); 1724 tnl->Driver.RunPipeline = _tnl_run_pipeline; 1725 /* swrast setup */ 1726 xmesa_register_swrast_functions( mesaCtx ); 1727 _swsetup_Wakeup(mesaCtx); 1728 1729 return c; 1730} 1731 1732 1733 1734void XMesaDestroyContext( XMesaContext c ) 1735{ 1736 GLcontext *mesaCtx = &c->mesa; 1737#ifdef FX 1738 XMesaBuffer xmbuf = XMESA_BUFFER(mesaCtx->DrawBuffer); 1739 1740 if (xmbuf && xmbuf->FXctx) 1741 fxMesaDestroyContext(xmbuf->FXctx); 1742#endif 1743 _swsetup_DestroyContext( mesaCtx ); 1744 _swrast_DestroyContext( mesaCtx ); 1745 _tnl_DestroyContext( mesaCtx ); 1746 _ac_DestroyContext( mesaCtx ); 1747 _mesa_free_context_data( mesaCtx ); 1748 _mesa_free( c ); 1749} 1750 1751 1752 1753/* 1754 * XXX this isn't a public function! It's a hack for the 3Dfx driver. 1755 * Create a new XMesaBuffer from an X window. 1756 * Input: v - the XMesaVisual 1757 * w - the window 1758 * c - the context 1759 * Return: new XMesaBuffer or NULL if error 1760 */ 1761XMesaBuffer 1762XMesaCreateWindowBuffer2(XMesaVisual v, XMesaWindow w, XMesaContext c) 1763{ 1764#ifndef XFree86Server 1765 XWindowAttributes attr; 1766#endif 1767#ifdef FX 1768 char *fxEnvVar; 1769#endif 1770 int client = 0; 1771 XMesaBuffer b; 1772 XMesaColormap cmap; 1773 1774 assert(v); 1775 (void) c; 1776 1777 /* Check that window depth matches visual depth */ 1778#ifdef XFree86Server 1779 client = CLIENT_ID(((XMesaDrawable)w)->id); 1780 1781 if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) { 1782 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", 1783 GET_VISUAL_DEPTH(v), ((XMesaDrawable) w)->depth); 1784 return NULL; 1785 } 1786#else 1787 XGetWindowAttributes( v->display, w, &attr ); 1788 1789 if (GET_VISUAL_DEPTH(v) != attr.depth) { 1790 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", 1791 GET_VISUAL_DEPTH(v), attr.depth); 1792 return NULL; 1793 } 1794#endif 1795 1796 /* Find colormap */ 1797#ifdef XFree86Server 1798 cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); 1799#else 1800 if (attr.colormap) { 1801 cmap = attr.colormap; 1802 } 1803 else { 1804 _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); 1805 /* this is weird, a window w/out a colormap!? */ 1806 /* OK, let's just allocate a new one and hope for the best */ 1807 cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); 1808 } 1809#endif 1810 1811 b = alloc_xmesa_buffer(v, WINDOW, cmap); 1812 if (!b) { 1813 return NULL; 1814 } 1815 1816 if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode, 1817 (XMesaDrawable) w, cmap )) { 1818 free_xmesa_buffer(client, b); 1819 return NULL; 1820 } 1821 1822#ifdef FX 1823 fxEnvVar = _mesa_getenv("MESA_GLX_FX"); 1824 if (fxEnvVar) { 1825 if (fxEnvVar[0]!='d') { 1826 int attribs[100]; 1827 int numAttribs = 0; 1828 int hw; 1829 if (v->mesa_visual.depthBits > 0) { 1830 attribs[numAttribs++] = FXMESA_DEPTH_SIZE; 1831 attribs[numAttribs++] = v->mesa_visual.depthBits; 1832 } 1833 if (v->mesa_visual.doubleBufferMode) { 1834 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; 1835 } 1836 if (v->mesa_visual.accumRedBits > 0) { 1837 attribs[numAttribs++] = FXMESA_ACCUM_SIZE; 1838 attribs[numAttribs++] = v->mesa_visual.accumRedBits; 1839 } 1840 if (v->mesa_visual.stencilBits > 0) { 1841 attribs[numAttribs++] = FXMESA_STENCIL_SIZE; 1842 attribs[numAttribs++] = v->mesa_visual.stencilBits; 1843 } 1844 if (v->mesa_visual.alphaBits > 0) { 1845 attribs[numAttribs++] = FXMESA_ALPHA_SIZE; 1846 attribs[numAttribs++] = v->mesa_visual.alphaBits; 1847 } 1848 if (1) { 1849 attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; 1850 attribs[numAttribs++] = (int) &(c->mesa); 1851 } 1852 attribs[numAttribs++] = FXMESA_NONE; 1853 1854 /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */ 1855 hw = fxMesaSelectCurrentBoard(0); 1856 1857 /* if these fail, there's a new bug somewhere */ 1858 ASSERT(b->mesa_buffer.Width > 0); 1859 ASSERT(b->mesa_buffer.Height > 0); 1860 1861 if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) { 1862 b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width, 1863 b->mesa_buffer.Height, attribs); 1864 if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) { 1865 b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; 1866 if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) { 1867 b->FXwindowHack = GL_TRUE; 1868 FX_grSstControl(GR_CONTROL_DEACTIVATE); 1869 } 1870 else { 1871 b->FXwindowHack = GL_FALSE; 1872 } 1873 } 1874 } 1875 else { 1876 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') 1877 b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, 1878 GR_REFRESH_75Hz, attribs); 1879 else 1880 b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width, 1881 b->mesa_buffer.Height, attribs); 1882 b->FXisHackUsable = GL_FALSE; 1883 b->FXwindowHack = GL_FALSE; 1884 } 1885 /* 1886 fprintf(stderr, 1887 "voodoo %d, wid %d height %d hack: usable %d active %d\n", 1888 hw, b->mesa_buffer.Width, b->mesa_buffer.Height, 1889 b->FXisHackUsable, b->FXwindowHack); 1890 */ 1891 } 1892 } 1893 else { 1894 _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n"); 1895 _mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n"); 1896 _mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n"); 1897 _mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); 1898 } 1899#endif 1900 1901 return b; 1902} 1903 1904 1905XMesaBuffer 1906XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) 1907{ 1908 return XMesaCreateWindowBuffer2( v, w, NULL ); 1909} 1910 1911 1912/** 1913 * Create a new XMesaBuffer from an X pixmap. 1914 * 1915 * \param v the XMesaVisual 1916 * \param p the pixmap 1917 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or 1918 * \c GLX_DIRECT_COLOR visual for the pixmap 1919 * \returns new XMesaBuffer or NULL if error 1920 */ 1921XMesaBuffer 1922XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap) 1923{ 1924 int client = 0; 1925 XMesaBuffer b; 1926 1927 assert(v); 1928 1929 b = alloc_xmesa_buffer(v, PIXMAP, cmap); 1930 if (!b) { 1931 return NULL; 1932 } 1933 1934#ifdef XFree86Server 1935 client = CLIENT_ID(((XMesaDrawable)p)->id); 1936#endif 1937 1938 if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, 1939 (XMesaDrawable) p, cmap)) { 1940 free_xmesa_buffer(client, b); 1941 return NULL; 1942 } 1943 1944 return b; 1945} 1946 1947 1948 1949XMesaBuffer 1950XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap, 1951 unsigned int width, unsigned int height) 1952{ 1953#ifdef XFree86Server 1954 return 0; 1955#else 1956 int client = 0; 1957 XMesaWindow root; 1958 XMesaDrawable drawable; /* X Pixmap Drawable */ 1959 XMesaBuffer b; 1960 1961 b = alloc_xmesa_buffer(v, PBUFFER, cmap); 1962 if (!b) { 1963 return NULL; 1964 } 1965 1966 /* allocate pixmap for front buffer */ 1967 root = RootWindow( v->display, v->visinfo->screen ); 1968 drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth ); 1969 1970 if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, 1971 drawable, cmap)) { 1972 free_xmesa_buffer(client, b); 1973 return NULL; 1974 } 1975 1976 return b; 1977#endif 1978} 1979 1980 1981 1982/* 1983 * Deallocate an XMesaBuffer structure and all related info. 1984 */ 1985void XMesaDestroyBuffer( XMesaBuffer b ) 1986{ 1987 int client = 0; 1988 1989#ifdef XFree86Server 1990 if (b->frontxrb->drawable) 1991 client = CLIENT_ID(b->frontxrb->drawable->id); 1992#endif 1993 1994 if (b->gc) XMesaFreeGC( b->xm_visual->display, b->gc ); 1995 if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc ); 1996 if (b->swapgc) XMesaFreeGC( b->xm_visual->display, b->swapgc ); 1997 1998 if (b->xm_visual->mesa_visual.doubleBufferMode) 1999 { 2000 if (b->backxrb->ximage) { 2001#if defined(USE_XSHM) && !defined(XFree86Server) 2002 if (b->shm) { 2003 XShmDetach( b->xm_visual->display, &b->shminfo ); 2004 XDestroyImage( b->backxrb->ximage ); 2005 shmdt( b->shminfo.shmaddr ); 2006 } 2007 else 2008#endif 2009 XMesaDestroyImage( b->backxrb->ximage ); 2010 } 2011 if (b->backxrb->pixmap) { 2012 XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap ); 2013 if (b->xm_visual->hpcr_clear_flag) { 2014 XMesaFreePixmap( b->xm_visual->display, 2015 b->xm_visual->hpcr_clear_pixmap ); 2016 XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); 2017 } 2018 } 2019 } 2020 if (b->rowimage) { 2021 _mesa_free( b->rowimage->data ); 2022 b->rowimage->data = NULL; 2023 XMesaDestroyImage( b->rowimage ); 2024 } 2025 2026 free_xmesa_buffer(client, b); 2027} 2028 2029 2030 2031/* 2032 * Bind buffer b to context c and make c the current rendering context. 2033 */ 2034GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) 2035{ 2036 return XMesaMakeCurrent2( c, b, b ); 2037} 2038 2039 2040/* 2041 * Bind buffer b to context c and make c the current rendering context. 2042 */ 2043GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, 2044 XMesaBuffer readBuffer ) 2045{ 2046 if (c) { 2047 if (!drawBuffer || !readBuffer) 2048 return GL_FALSE; /* must specify buffers! */ 2049 2050#ifdef FX 2051 if (drawBuffer->FXctx) { 2052 fxMesaMakeCurrent(drawBuffer->FXctx); 2053 2054 c->xm_buffer = drawBuffer; 2055 2056 return GL_TRUE; 2057 } 2058#endif 2059 if (&(c->mesa) == _mesa_get_current_context() 2060 && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer 2061 && c->mesa.ReadBuffer == &readBuffer->mesa_buffer 2062 && ((XMesaBuffer) c->mesa.DrawBuffer)->wasCurrent) { 2063 /* same context and buffer, do nothing */ 2064 return GL_TRUE; 2065 } 2066 2067 c->xm_buffer = drawBuffer; 2068 2069 /* Call this periodically to detect when the user has begun using 2070 * GL rendering from multiple threads. 2071 */ 2072 _glapi_check_multithread(); 2073 2074 _mesa_make_current(&(c->mesa), 2075 &drawBuffer->mesa_buffer, 2076 &readBuffer->mesa_buffer); 2077 2078 if (c->xm_visual->mesa_visual.rgbMode) { 2079 /* 2080 * Must recompute and set these pixel values because colormap 2081 * can be different for different windows. 2082 */ 2083 c->clearpixel = xmesa_color_to_pixel( &c->mesa, 2084 c->clearcolor[0], 2085 c->clearcolor[1], 2086 c->clearcolor[2], 2087 c->clearcolor[3], 2088 c->xm_visual->undithered_pf); 2089 XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel); 2090 } 2091 2092 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 2093 drawBuffer->wasCurrent = GL_TRUE; 2094 } 2095 else { 2096 /* Detach */ 2097 _mesa_make_current( NULL, NULL, NULL ); 2098 } 2099 return GL_TRUE; 2100} 2101 2102 2103/* 2104 * Unbind the context c from its buffer. 2105 */ 2106GLboolean XMesaUnbindContext( XMesaContext c ) 2107{ 2108 /* A no-op for XFree86 integration purposes */ 2109 return GL_TRUE; 2110} 2111 2112 2113XMesaContext XMesaGetCurrentContext( void ) 2114{ 2115 GET_CURRENT_CONTEXT(ctx); 2116 if (ctx) { 2117 XMesaContext xmesa = XMESA_CONTEXT(ctx); 2118 return xmesa; 2119 } 2120 else { 2121 return 0; 2122 } 2123} 2124 2125 2126XMesaBuffer XMesaGetCurrentBuffer( void ) 2127{ 2128 GET_CURRENT_CONTEXT(ctx); 2129 if (ctx) { 2130 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); 2131 return xmbuf; 2132 } 2133 else { 2134 return 0; 2135 } 2136} 2137 2138 2139/* New in Mesa 3.1 */ 2140XMesaBuffer XMesaGetCurrentReadBuffer( void ) 2141{ 2142 GET_CURRENT_CONTEXT(ctx); 2143 if (ctx) { 2144 return (XMesaBuffer) (ctx->ReadBuffer); 2145 } 2146 else { 2147 return 0; 2148 } 2149} 2150 2151 2152GLboolean XMesaForceCurrent(XMesaContext c) 2153{ 2154 if (c) { 2155 if (&(c->mesa) != _mesa_get_current_context()) { 2156 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer); 2157 } 2158 } 2159 else { 2160 _mesa_make_current(NULL, NULL, NULL); 2161 } 2162 return GL_TRUE; 2163} 2164 2165 2166GLboolean XMesaLoseCurrent(XMesaContext c) 2167{ 2168 (void) c; 2169 _mesa_make_current(NULL, NULL, NULL); 2170 return GL_TRUE; 2171} 2172 2173 2174/* 2175 * Switch 3Dfx support hack between window and full-screen mode. 2176 */ 2177GLboolean XMesaSetFXmode( GLint mode ) 2178{ 2179#ifdef FX 2180 const char *fx = _mesa_getenv("MESA_GLX_FX"); 2181 if (fx && fx[0] != 'd') { 2182 GET_CURRENT_CONTEXT(ctx); 2183 GrHwConfiguration hw; 2184 if (!FX_grSstQueryHardware(&hw)) { 2185 /*fprintf(stderr, "!grSstQueryHardware\n");*/ 2186 return GL_FALSE; 2187 } 2188 if (hw.num_sst < 1) { 2189 /*fprintf(stderr, "hw.num_sst < 1\n");*/ 2190 return GL_FALSE; 2191 } 2192 if (ctx) { 2193 /* [dBorca] Hack alert: 2194 * oh, this is sooo wrong: ctx above is 2195 * really an fxMesaContext, not an XMesaContext 2196 */ 2197 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); 2198 if (mode == XMESA_FX_WINDOW) { 2199 if (xmbuf->FXisHackUsable) { 2200 FX_grSstControl(GR_CONTROL_DEACTIVATE); 2201 xmbuf->FXwindowHack = GL_TRUE; 2202 return GL_TRUE; 2203 } 2204 } 2205 else if (mode == XMESA_FX_FULLSCREEN) { 2206 FX_grSstControl(GR_CONTROL_ACTIVATE); 2207 xmbuf->FXwindowHack = GL_FALSE; 2208 return GL_TRUE; 2209 } 2210 else { 2211 /* Error: Bad mode value */ 2212 } 2213 } 2214 } 2215 /*fprintf(stderr, "fallthrough\n");*/ 2216#else 2217 (void) mode; 2218#endif 2219 return GL_FALSE; 2220} 2221 2222 2223 2224#ifdef FX 2225/* 2226 * Read image from VooDoo frame buffer into X/Mesa's back XImage. 2227 */ 2228static void FXgetImage( XMesaBuffer b ) 2229{ 2230 GET_CURRENT_CONTEXT(ctx); 2231 static unsigned short pixbuf[MAX_WIDTH]; 2232 GLuint x, y; 2233 int xpos, ypos; 2234 XMesaWindow root; 2235 unsigned int bw, depth, width, height; 2236 XMesaContext xmesa = XMESA_CONTEXT(ctx); 2237 2238#ifdef XFree86Server 2239 x = b->frontxrb->pixmap->x; 2240 y = b->frontxrb->pixmap->y; 2241 width = b->frontxrb->pixmap->width; 2242 height = b->frontxrb->pixmap->height; 2243 depth = b->frontxrb->pixmap->depth; 2244#else 2245 XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap, 2246 &root, &xpos, &ypos, &width, &height, &bw, &depth); 2247#endif 2248 if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) { 2249 b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width); 2250 b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height); 2251 if (b->mesa_buffer.Width & 1) 2252 b->mesa_buffer.Width--; /* prevent odd width */ 2253 xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height); 2254 } 2255 2256 /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */ 2257 /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */ 2258 if (b->xm_visual->undithered_pf==PF_5R6G5B) { 2259 /* Special case: 16bpp RGB */ 2260 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ 2261 0, b->FXctx->height - b->mesa_buffer.Height, /*pos*/ 2262 b->mesa_buffer.Width, b->mesa_buffer.Height, /* size */ 2263 b->mesa_buffer.Width * sizeof(GLushort), /* stride */ 2264 b->backxrb->ximage->data); /* dest buffer */ 2265 } 2266 else if (b->xm_visual->dithered_pf==PF_Dither 2267 && GET_VISUAL_DEPTH(b->xm_visual)==8) { 2268 /* Special case: 8bpp RGB */ 2269 for (y=0;y<b->mesa_buffer.Height;y++) { 2270 GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data 2271 + b->backxrb->ximage->bytes_per_line * y; 2272 XDITHER_SETUP(y); 2273 2274 /* read row from 3Dfx frame buffer */ 2275 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2276 0, b->FXctx->height-(b->mesa_buffer.Height-y), 2277 b->mesa_buffer.Width, 1, 2278 0, 2279 pixbuf ); 2280 2281 /* write to XImage back buffer */ 2282 for (x=0;x<b->mesa_buffer.Width;x++) { 2283 GLubyte r = (pixbuf[x] & 0xf800) >> 8; 2284 GLubyte g = (pixbuf[x] & 0x07e0) >> 3; 2285 GLubyte b = (pixbuf[x] & 0x001f) << 3; 2286 *ptr++ = XDITHER( x, r, g, b); 2287 } 2288 } 2289 } 2290 else { 2291 /* General case: slow! */ 2292 for (y=0;y<b->mesa_buffer.Height;y++) { 2293 /* read row from 3Dfx frame buffer */ 2294 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2295 0, b->FXctx->height-(b->mesa_buffer.Height-y), 2296 b->mesa_buffer.Width, 1, 2297 0, 2298 pixbuf ); 2299 2300 /* write to XImage back buffer */ 2301 for (x=0;x<b->mesa_buffer.Width;x++) { 2302 XMesaPutPixel(b->backxrb->ximage,x,y, 2303 xmesa_color_to_pixel(ctx, 2304 (pixbuf[x] & 0xf800) >> 8, 2305 (pixbuf[x] & 0x07e0) >> 3, 2306 (pixbuf[x] & 0x001f) << 3, 2307 0xff, 2308 b->xm_visual->undithered_pf)); 2309 } 2310 } 2311 } 2312 /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */ 2313} 2314#endif 2315 2316 2317/* 2318 * Copy the back buffer to the front buffer. If there's no back buffer 2319 * this is a no-op. 2320 */ 2321void XMesaSwapBuffers( XMesaBuffer b ) 2322{ 2323 GET_CURRENT_CONTEXT(ctx); 2324 2325 if (!b->backxrb) { 2326 /* single buffered */ 2327 return; 2328 } 2329 2330 /* If we're swapping the buffer associated with the current context 2331 * we have to flush any pending rendering commands first. 2332 */ 2333 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2334 _mesa_notifySwapBuffers(ctx); 2335 2336 if (b->db_mode) { 2337#ifdef FX 2338 if (b->FXctx) { 2339 fxMesaSwapBuffers(); 2340 2341 if (b->FXwindowHack) 2342 FXgetImage(b); 2343 else 2344 return; 2345 } 2346#endif 2347 if (b->backxrb->ximage) { 2348 /* Copy Ximage from host's memory to server's window */ 2349#if defined(USE_XSHM) && !defined(XFree86Server) 2350 if (b->shm) { 2351 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2352 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 2353 b->swapgc, 2354 b->backxrb->ximage, 0, 0, 2355 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 2356 False ); 2357 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2358 } 2359 else 2360#endif 2361 { 2362 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2363 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 2364 b->swapgc, 2365 b->backxrb->ximage, 0, 0, 2366 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height ); 2367 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2368 } 2369 } 2370 else { 2371 /* Copy pixmap to window on server */ 2372 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2373 XMesaCopyArea( b->xm_visual->display, 2374 b->backxrb->pixmap, /* source drawable */ 2375 b->frontxrb->drawable, /* dest. drawable */ 2376 b->swapgc, 2377 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 2378 0, 0 /* dest region */ 2379 ); 2380 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2381 } 2382 } 2383#if !defined(XFree86Server) 2384 XSync( b->xm_visual->display, False ); 2385#endif 2386} 2387 2388 2389 2390/* 2391 * Copy sub-region of back buffer to front buffer 2392 */ 2393void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 2394{ 2395 GET_CURRENT_CONTEXT(ctx); 2396 2397 /* If we're swapping the buffer associated with the current context 2398 * we have to flush any pending rendering commands first. 2399 */ 2400 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2401 _mesa_notifySwapBuffers(ctx); 2402 2403 if (!b->backxrb) { 2404 /* single buffered */ 2405 return; 2406 } 2407 2408 if (b->db_mode) { 2409 int yTop = b->mesa_buffer.Height - y - height; 2410#ifdef FX 2411 if (b->FXctx) { 2412 fxMesaSwapBuffers(); 2413 if (b->FXwindowHack) 2414 FXgetImage(b); 2415 else 2416 return; 2417 } 2418#endif 2419 if (b->backxrb->ximage) { 2420 /* Copy Ximage from host's memory to server's window */ 2421#if defined(USE_XSHM) && !defined(XFree86Server) 2422 if (b->shm) { 2423 /* XXX assuming width and height aren't too large! */ 2424 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 2425 b->swapgc, 2426 b->backxrb->ximage, x, yTop, 2427 x, yTop, width, height, False ); 2428 /* wait for finished event??? */ 2429 } 2430 else 2431#endif 2432 { 2433 /* XXX assuming width and height aren't too large! */ 2434 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 2435 b->swapgc, 2436 b->backxrb->ximage, x, yTop, 2437 x, yTop, width, height ); 2438 } 2439 } 2440 else { 2441 /* Copy pixmap to window on server */ 2442 XMesaCopyArea( b->xm_visual->display, 2443 b->backxrb->pixmap, /* source drawable */ 2444 b->frontxrb->drawable, /* dest. drawable */ 2445 b->swapgc, 2446 x, yTop, width, height, /* source region */ 2447 x, yTop /* dest region */ 2448 ); 2449 } 2450 } 2451} 2452 2453 2454/* 2455 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function 2456 * is a way to get "under the hood" of X/Mesa so one can manipulate the 2457 * back buffer directly. 2458 * Output: pixmap - pointer to back buffer's Pixmap, or 0 2459 * ximage - pointer to back buffer's XImage, or NULL 2460 * Return: GL_TRUE = context is double buffered 2461 * GL_FALSE = context is single buffered 2462 */ 2463#ifndef XFree86Server 2464GLboolean XMesaGetBackBuffer( XMesaBuffer b, 2465 XMesaPixmap *pixmap, 2466 XMesaImage **ximage ) 2467{ 2468 if (b->db_mode) { 2469 if (pixmap) 2470 *pixmap = b->backxrb->pixmap; 2471 if (ximage) 2472 *ximage = b->backxrb->ximage; 2473 return GL_TRUE; 2474 } 2475 else { 2476 *pixmap = 0; 2477 *ximage = NULL; 2478 return GL_FALSE; 2479 } 2480} 2481#endif /* XFree86Server */ 2482 2483 2484/* 2485 * Return the depth buffer associated with an XMesaBuffer. 2486 * Input: b - the XMesa buffer handle 2487 * Output: width, height - size of buffer in pixels 2488 * bytesPerValue - bytes per depth value (2 or 4) 2489 * buffer - pointer to depth buffer values 2490 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 2491 */ 2492GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, 2493 GLint *bytesPerValue, void **buffer ) 2494{ 2495 struct gl_renderbuffer *rb 2496 = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer; 2497 if (!rb || !rb->Data) { 2498 *width = 0; 2499 *height = 0; 2500 *bytesPerValue = 0; 2501 *buffer = 0; 2502 return GL_FALSE; 2503 } 2504 else { 2505 *width = b->mesa_buffer.Width; 2506 *height = b->mesa_buffer.Height; 2507 *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 2508 ? sizeof(GLushort) : sizeof(GLuint); 2509 *buffer = rb->Data; 2510 return GL_TRUE; 2511 } 2512} 2513 2514 2515void XMesaFlush( XMesaContext c ) 2516{ 2517 if (c && c->xm_visual) { 2518#ifdef XFree86Server 2519 /* NOT_NEEDED */ 2520#else 2521 XSync( c->xm_visual->display, False ); 2522#endif 2523 } 2524} 2525 2526 2527 2528const char *XMesaGetString( XMesaContext c, int name ) 2529{ 2530 (void) c; 2531 if (name==XMESA_VERSION) { 2532 return "5.0"; 2533 } 2534 else if (name==XMESA_EXTENSIONS) { 2535 return ""; 2536 } 2537 else { 2538 return NULL; 2539 } 2540} 2541 2542 2543 2544XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) 2545{ 2546 XMesaBuffer b; 2547 for (b=XMesaBufferList; b; b=b->Next) { 2548 if (b->frontxrb->drawable == d && b->display == dpy) { 2549 return b; 2550 } 2551 } 2552 return NULL; 2553} 2554 2555 2556/** 2557 * Free/destroy all XMesaBuffers associated with given display. 2558 */ 2559void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) 2560{ 2561 XMesaBuffer b, next; 2562 for (b = XMesaBufferList; b; b = next) { 2563 next = b->Next; 2564 if (b->display == dpy) { 2565 free_xmesa_buffer(0, b); 2566 } 2567 } 2568} 2569 2570 2571/* 2572 * Look for XMesaBuffers whose X window has been destroyed. 2573 * Deallocate any such XMesaBuffers. 2574 */ 2575void XMesaGarbageCollect( void ) 2576{ 2577 XMesaBuffer b, next; 2578 for (b=XMesaBufferList; b; b=next) { 2579 next = b->Next; 2580 if (b->display && b->frontxrb->drawable && b->type == WINDOW) { 2581#ifdef XFree86Server 2582 /* NOT_NEEDED */ 2583#else 2584 XSync(b->display, False); 2585 if (!window_exists( b->display, b->frontxrb->drawable )) { 2586 /* found a dead window, free the ancillary info */ 2587 XMesaDestroyBuffer( b ); 2588 } 2589#endif 2590 } 2591 } 2592} 2593 2594 2595void XMesaReset( void ) 2596{ 2597 while (XMesaBufferList) 2598 XMesaDestroyBuffer(XMesaBufferList); 2599 2600 XMesaBufferList = NULL; 2601} 2602 2603 2604unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, 2605 GLfloat red, GLfloat green, 2606 GLfloat blue, GLfloat alpha ) 2607{ 2608 GLcontext *ctx = &xmesa->mesa; 2609 GLint r = (GLint) (red * 255.0F); 2610 GLint g = (GLint) (green * 255.0F); 2611 GLint b = (GLint) (blue * 255.0F); 2612 GLint a = (GLint) (alpha * 255.0F); 2613 2614 switch (xmesa->pixelformat) { 2615 case PF_Index: 2616 return 0; 2617 case PF_Truecolor: 2618 { 2619 unsigned long p; 2620 PACK_TRUECOLOR( p, r, g, b ); 2621 return p; 2622 } 2623 case PF_8A8B8G8R: 2624 return PACK_8A8B8G8R( r, g, b, a ); 2625 case PF_8A8R8G8B: 2626 return PACK_8A8R8G8B( r, g, b, a ); 2627 case PF_8R8G8B: 2628 return PACK_8R8G8B( r, g, b ); 2629 case PF_5R6G5B: 2630 return PACK_5R6G5B( r, g, b ); 2631 case PF_Dither: 2632 { 2633 DITHER_SETUP; 2634 return DITHER( x, y, r, g, b ); 2635 } 2636 case PF_1Bit: 2637 /* 382 = (3*255)/2 */ 2638 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 2639 case PF_HPCR: 2640 return DITHER_HPCR(x, y, r, g, b); 2641 case PF_Lookup: 2642 { 2643 LOOKUP_SETUP; 2644 return LOOKUP( r, g, b ); 2645 } 2646 case PF_Grayscale: 2647 return GRAY_RGB( r, g, b ); 2648 case PF_Dither_5R6G5B: 2649 /* fall through */ 2650 case PF_Dither_True: 2651 { 2652 unsigned long p; 2653 PACK_TRUEDITHER(p, x, y, r, g, b); 2654 return p; 2655 } 2656 default: 2657 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); 2658 } 2659 return 0; 2660} 2661 2662 2663/* 2664 * This is typically called when the window size changes and we need 2665 * to reallocate the buffer's back/depth/stencil/accum buffers. 2666 */ 2667void XMesaResizeBuffers( XMesaBuffer b ) 2668{ 2669#ifdef XFree86Server 2670 GLuint winwidth, winheight; 2671 GET_CURRENT_CONTEXT(ctx); 2672 2673 winwidth = MIN2(b->frontxrb->drawable->width, MAX_WIDTH); 2674 winheight = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT); 2675 2676 xmesa_resize_buffers(ctx, &(b->mesa_buffer), winwidth, winheight); 2677#else 2678 Window root; 2679 int xpos, ypos; 2680 unsigned int width, height, bw, depth; 2681 GET_CURRENT_CONTEXT(ctx); 2682 XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap, 2683 &root, &xpos, &ypos, &width, &height, &bw, &depth); 2684 xmesa_resize_buffers(ctx, &(b->mesa_buffer), width, height); 2685#endif 2686} 2687 2688