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