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