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