1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 /** 26 * \file xm_api.c 27 * 28 * All the XMesa* API functions. 29 * 30 * 31 * NOTES: 32 * 33 * The window coordinate system origin (0,0) is in the lower-left corner 34 * of the window. X11's window coordinate origin is in the upper-left 35 * corner of the window. Therefore, most drawing functions in this 36 * file have to flip Y coordinates. 37 * 38 * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile 39 * in support for the MIT Shared Memory extension. If enabled, when you 40 * use an Ximage for the back buffer in double buffered mode, the "swap" 41 * operation will be faster. You must also link with -lXext. 42 * 43 * Byte swapping: If the Mesa host and the X display use a different 44 * byte order then there's some trickiness to be aware of when using 45 * XImages. The byte ordering used for the XImage is that of the X 46 * display, not the Mesa host. 47 * The color-to-pixel encoding for True/DirectColor must be done 48 * according to the display's visual red_mask, green_mask, and blue_mask. 49 * If XPutPixel is used to put a pixel into an XImage then XPutPixel will 50 * do byte swapping if needed. If one wants to directly "poke" the pixel 51 * into the XImage's buffer then the pixel must be byte swapped first. In 52 * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format 53 * and use XPutPixel everywhere except in the implementation of 54 * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so 55 * instead of using XPutPixel we "poke" our values after byte-swapping 56 * the clear pixel value if needed. 57 * 58 */ 59 60 #ifdef __CYGWIN__ 61 #undef WIN32 62 #undef __WIN32__ 63 #endif 64 65 #include <stdio.h> 66 #include "glxheader.h" 67 #include "xmesaP.h" 68 #include "main/api_exec.h" 69 #include "main/context.h" 70 #include "main/extensions.h" 71 #include "main/framebuffer.h" 72 #include "main/imports.h" 73 #include "main/macros.h" 74 #include "main/renderbuffer.h" 75 #include "main/teximage.h" 76 #include "main/version.h" 77 #include "main/vtxfmt.h" 78 #include "swrast/swrast.h" 79 #include "swrast/s_renderbuffer.h" 80 #include "swrast_setup/swrast_setup.h" 81 #include "vbo/vbo.h" 82 #include "tnl/tnl.h" 83 #include "tnl/t_context.h" 84 #include "tnl/t_pipeline.h" 85 #include "drivers/common/driverfuncs.h" 86 #include "drivers/common/meta.h" 87 88 /** 89 * Global X driver lock 90 */ 91 mtx_t _xmesa_lock; 92 93 94 95 /**********************************************************************/ 96 /***** X Utility Functions *****/ 97 /**********************************************************************/ 98 99 100 /** 101 * Return the host's byte order as LSBFirst or MSBFirst ala X. 102 */ 103 static int host_byte_order( void ) 104 { 105 int i = 1; 106 char *cptr = (char *) &i; 107 return (*cptr==1) ? LSBFirst : MSBFirst; 108 } 109 110 111 /** 112 * Check if the X Shared Memory extension is available. 113 * Return: 0 = not available 114 * 1 = shared XImage support available 115 * 2 = shared Pixmap support available also 116 */ 117 static int check_for_xshm( XMesaDisplay *display ) 118 { 119 #if defined(USE_XSHM) 120 int ignore; 121 122 if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { 123 /* Note: we're no longer calling XShmQueryVersion() here. It seems 124 * to be flakey (triggers a spurious X protocol error when we close 125 * one display connection and start using a new one. XShm has been 126 * around a long time and hasn't changed so if MIT_SHM is supported 127 * we assume we're good to go. 128 */ 129 return 2; 130 } 131 else { 132 return 0; 133 } 134 #else 135 /* No XSHM support */ 136 return 0; 137 #endif 138 } 139 140 141 /** 142 * Apply gamma correction to an intensity value in [0..max]. Return the 143 * new intensity value. 144 */ 145 static GLint 146 gamma_adjust( GLfloat gamma, GLint value, GLint max ) 147 { 148 if (gamma == 1.0) { 149 return value; 150 } 151 else { 152 double x = (double) value / (double) max; 153 return IROUND_POS((GLfloat) max * pow(x, 1.0F/gamma)); 154 } 155 } 156 157 158 159 /** 160 * Return the true number of bits per pixel for XImages. 161 * For example, if we request a 24-bit deep visual we may actually need/get 162 * 32bpp XImages. This function returns the appropriate bpp. 163 * Input: dpy - the X display 164 * visinfo - desribes the visual to be used for XImages 165 * Return: true number of bits per pixel for XImages 166 */ 167 static int 168 bits_per_pixel( XMesaVisual xmv ) 169 { 170 XMesaDisplay *dpy = xmv->display; 171 XMesaVisualInfo visinfo = xmv->visinfo; 172 XMesaImage *img; 173 int bitsPerPixel; 174 /* Create a temporary XImage */ 175 img = XCreateImage( dpy, visinfo->visual, visinfo->depth, 176 ZPixmap, 0, /*format, offset*/ 177 malloc(8), /*data*/ 178 1, 1, /*width, height*/ 179 32, /*bitmap_pad*/ 180 0 /*bytes_per_line*/ 181 ); 182 assert(img); 183 /* grab the bits/pixel value */ 184 bitsPerPixel = img->bits_per_pixel; 185 /* free the XImage */ 186 free( img->data ); 187 img->data = NULL; 188 XMesaDestroyImage( img ); 189 return bitsPerPixel; 190 } 191 192 193 194 /* 195 * Determine if a given X window ID is valid (window exists). 196 * Do this by calling XGetWindowAttributes() for the window and 197 * checking if we catch an X error. 198 * Input: dpy - the display 199 * win - the window to check for existence 200 * Return: GL_TRUE - window exists 201 * GL_FALSE - window doesn't exist 202 */ 203 static GLboolean WindowExistsFlag; 204 205 static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr ) 206 { 207 (void) dpy; 208 if (xerr->error_code == BadWindow) { 209 WindowExistsFlag = GL_FALSE; 210 } 211 return 0; 212 } 213 214 static GLboolean window_exists( XMesaDisplay *dpy, Window win ) 215 { 216 XWindowAttributes wa; 217 int (*old_handler)( XMesaDisplay*, XErrorEvent* ); 218 WindowExistsFlag = GL_TRUE; 219 old_handler = XSetErrorHandler(window_exists_err_handler); 220 XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ 221 XSetErrorHandler(old_handler); 222 return WindowExistsFlag; 223 } 224 225 static Status 226 get_drawable_size( XMesaDisplay *dpy, Drawable d, GLuint *width, GLuint *height ) 227 { 228 Window root; 229 Status stat; 230 int xpos, ypos; 231 unsigned int w, h, bw, depth; 232 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); 233 *width = w; 234 *height = h; 235 return stat; 236 } 237 238 239 /** 240 * Return the size of the window (or pixmap) that corresponds to the 241 * given XMesaBuffer. 242 * \param width returns width in pixels 243 * \param height returns height in pixels 244 */ 245 void 246 xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b, 247 GLuint *width, GLuint *height) 248 { 249 Status stat; 250 251 mtx_lock(&_xmesa_lock); 252 XSync(b->xm_visual->display, 0); /* added for Chromium */ 253 stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height); 254 mtx_unlock(&_xmesa_lock); 255 256 if (!stat) { 257 /* probably querying a window that's recently been destroyed */ 258 _mesa_warning(NULL, "XGetGeometry failed!\n"); 259 *width = *height = 1; 260 } 261 } 262 263 264 265 /**********************************************************************/ 266 /***** Linked list of XMesaBuffers *****/ 267 /**********************************************************************/ 268 269 XMesaBuffer XMesaBufferList = NULL; 270 271 272 /** 273 * Allocate a new XMesaBuffer object which corresponds to the given drawable. 274 * Note that XMesaBuffer is derived from struct gl_framebuffer. 275 * The new XMesaBuffer will not have any size (Width=Height=0). 276 * 277 * \param d the corresponding X drawable (window or pixmap) 278 * \param type either WINDOW, PIXMAP or PBUFFER, describing d 279 * \param vis the buffer's visual 280 * \param cmap the window's colormap, if known. 281 * \return new XMesaBuffer or NULL if any problem 282 */ 283 static XMesaBuffer 284 create_xmesa_buffer(XMesaDrawable d, BufferType type, 285 XMesaVisual vis, XMesaColormap cmap) 286 { 287 XMesaBuffer b; 288 289 assert(type == WINDOW || type == PIXMAP || type == PBUFFER); 290 291 b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); 292 if (!b) 293 return NULL; 294 295 b->display = vis->display; 296 b->xm_visual = vis; 297 b->type = type; 298 b->cmap = cmap; 299 300 _mesa_initialize_window_framebuffer(&b->mesa_buffer, &vis->mesa_visual); 301 b->mesa_buffer.Delete = xmesa_delete_framebuffer; 302 303 /* 304 * Front renderbuffer 305 */ 306 b->frontxrb = xmesa_new_renderbuffer(NULL, 0, vis, GL_FALSE); 307 if (!b->frontxrb) { 308 free(b); 309 return NULL; 310 } 311 b->frontxrb->Parent = b; 312 b->frontxrb->drawable = d; 313 b->frontxrb->pixmap = (XMesaPixmap) d; 314 _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_FRONT_LEFT, 315 &b->frontxrb->Base.Base); 316 317 /* 318 * Back renderbuffer 319 */ 320 if (vis->mesa_visual.doubleBufferMode) { 321 b->backxrb = xmesa_new_renderbuffer(NULL, 0, vis, GL_TRUE); 322 if (!b->backxrb) { 323 /* XXX free front xrb too */ 324 free(b); 325 return NULL; 326 } 327 b->backxrb->Parent = b; 328 /* determine back buffer implementation */ 329 b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP; 330 331 _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_BACK_LEFT, 332 &b->backxrb->Base.Base); 333 } 334 335 /* 336 * Other renderbuffer (depth, stencil, etc) 337 */ 338 _swrast_add_soft_renderbuffers(&b->mesa_buffer, 339 GL_FALSE, /* color */ 340 vis->mesa_visual.haveDepthBuffer, 341 vis->mesa_visual.haveStencilBuffer, 342 vis->mesa_visual.haveAccumBuffer, 343 GL_FALSE, /* software alpha buffer */ 344 vis->mesa_visual.numAuxBuffers > 0 ); 345 346 /* GLX_EXT_texture_from_pixmap */ 347 b->TextureTarget = 0; 348 b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; 349 b->TextureMipmap = 0; 350 351 /* insert buffer into linked list */ 352 b->Next = XMesaBufferList; 353 XMesaBufferList = b; 354 355 return b; 356 } 357 358 359 /** 360 * Find an XMesaBuffer by matching X display and colormap but NOT matching 361 * the notThis buffer. 362 */ 363 XMesaBuffer 364 xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis) 365 { 366 XMesaBuffer b; 367 for (b=XMesaBufferList; b; b=b->Next) { 368 if (b->display==dpy && b->cmap==cmap && b!=notThis) { 369 return b; 370 } 371 } 372 return NULL; 373 } 374 375 376 /** 377 * Remove buffer from linked list, delete if no longer referenced. 378 */ 379 static void 380 xmesa_free_buffer(XMesaBuffer buffer) 381 { 382 XMesaBuffer prev = NULL, b; 383 384 for (b = XMesaBufferList; b; b = b->Next) { 385 if (b == buffer) { 386 struct gl_framebuffer *fb = &buffer->mesa_buffer; 387 388 /* unlink buffer from list */ 389 if (prev) 390 prev->Next = buffer->Next; 391 else 392 XMesaBufferList = buffer->Next; 393 394 /* mark as delete pending */ 395 fb->DeletePending = GL_TRUE; 396 397 /* Since the X window for the XMesaBuffer is going away, we don't 398 * want to dereference this pointer in the future. 399 */ 400 b->frontxrb->drawable = 0; 401 402 /* Unreference. If count = zero we'll really delete the buffer */ 403 _mesa_reference_framebuffer(&fb, NULL); 404 405 return; 406 } 407 /* continue search */ 408 prev = b; 409 } 410 /* buffer not found in XMesaBufferList */ 411 _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); 412 } 413 414 415 416 417 /**********************************************************************/ 418 /***** Misc Private Functions *****/ 419 /**********************************************************************/ 420 421 422 /** 423 * Setup RGB rendering for a window with a True/DirectColor visual. 424 */ 425 static void 426 setup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap) 427 { 428 unsigned long rmask, gmask, bmask; 429 (void) buffer; 430 (void) cmap; 431 432 /* Compute red multiplier (mask) and bit shift */ 433 v->rshift = 0; 434 rmask = GET_REDMASK(v); 435 while ((rmask & 1)==0) { 436 v->rshift++; 437 rmask = rmask >> 1; 438 } 439 440 /* Compute green multiplier (mask) and bit shift */ 441 v->gshift = 0; 442 gmask = GET_GREENMASK(v); 443 while ((gmask & 1)==0) { 444 v->gshift++; 445 gmask = gmask >> 1; 446 } 447 448 /* Compute blue multiplier (mask) and bit shift */ 449 v->bshift = 0; 450 bmask = GET_BLUEMASK(v); 451 while ((bmask & 1)==0) { 452 v->bshift++; 453 bmask = bmask >> 1; 454 } 455 456 /* 457 * Compute component-to-pixel lookup tables and dithering kernel 458 */ 459 { 460 static GLubyte kernel[16] = { 461 0*16, 8*16, 2*16, 10*16, 462 12*16, 4*16, 14*16, 6*16, 463 3*16, 11*16, 1*16, 9*16, 464 15*16, 7*16, 13*16, 5*16, 465 }; 466 GLint rBits = _mesa_bitcount(rmask); 467 GLint gBits = _mesa_bitcount(gmask); 468 GLint bBits = _mesa_bitcount(bmask); 469 GLint maxBits; 470 GLuint i; 471 472 /* convert pixel components in [0,_mask] to RGB values in [0,255] */ 473 for (i=0; i<=rmask; i++) 474 v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); 475 for (i=0; i<=gmask; i++) 476 v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); 477 for (i=0; i<=bmask; i++) 478 v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); 479 480 /* convert RGB values from [0,255] to pixel components */ 481 482 for (i=0;i<256;i++) { 483 GLint r = gamma_adjust(v->RedGamma, i, 255); 484 GLint g = gamma_adjust(v->GreenGamma, i, 255); 485 GLint b = gamma_adjust(v->BlueGamma, i, 255); 486 v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; 487 v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; 488 v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; 489 } 490 /* overflow protection */ 491 for (i=256;i<512;i++) { 492 v->RtoPixel[i] = v->RtoPixel[255]; 493 v->GtoPixel[i] = v->GtoPixel[255]; 494 v->BtoPixel[i] = v->BtoPixel[255]; 495 } 496 497 /* setup dithering kernel */ 498 maxBits = rBits; 499 if (gBits > maxBits) maxBits = gBits; 500 if (bBits > maxBits) maxBits = bBits; 501 for (i=0;i<16;i++) { 502 v->Kernel[i] = kernel[i] >> maxBits; 503 } 504 505 v->undithered_pf = PF_Truecolor; 506 v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor; 507 } 508 509 /* 510 * Now check for TrueColor visuals which we can optimize. 511 */ 512 if ( GET_REDMASK(v) ==0x0000ff 513 && GET_GREENMASK(v)==0x00ff00 514 && GET_BLUEMASK(v) ==0xff0000 515 && CHECK_BYTE_ORDER(v) 516 && v->BitsPerPixel==32 517 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 518 /* common 32 bpp config used on SGI, Sun */ 519 v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */ 520 } 521 else if (GET_REDMASK(v) == 0xff0000 522 && GET_GREENMASK(v)== 0x00ff00 523 && GET_BLUEMASK(v) == 0x0000ff 524 && CHECK_BYTE_ORDER(v) 525 && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){ 526 if (v->BitsPerPixel==32) { 527 /* if 32 bpp, and visual indicates 8 bpp alpha channel */ 528 if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8) 529 v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */ 530 else 531 v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */ 532 } 533 else if (v->BitsPerPixel == 24) { 534 v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */ 535 } 536 } 537 else if (GET_REDMASK(v) ==0xf800 538 && GET_GREENMASK(v)==0x07e0 539 && GET_BLUEMASK(v) ==0x001f 540 && CHECK_BYTE_ORDER(v) 541 && v->BitsPerPixel==16 542 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 543 /* 5-6-5 RGB */ 544 v->undithered_pf = PF_5R6G5B; 545 v->dithered_pf = PF_Dither_5R6G5B; 546 } 547 } 548 549 550 /** 551 * When a context is bound for the first time, we can finally finish 552 * initializing the context's visual and buffer information. 553 * \param v the XMesaVisual to initialize 554 * \param b the XMesaBuffer to initialize (may be NULL) 555 * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode 556 * \param window the window/pixmap we're rendering into 557 * \param cmap the colormap associated with the window/pixmap 558 * \return GL_TRUE=success, GL_FALSE=failure 559 */ 560 static GLboolean 561 initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, 562 XMesaDrawable window, 563 XMesaColormap cmap) 564 { 565 const int xclass = v->visualType; 566 567 568 assert(!b || b->xm_visual == v); 569 570 /* Save true bits/pixel */ 571 v->BitsPerPixel = bits_per_pixel(v); 572 assert(v->BitsPerPixel > 0); 573 574 /* RGB WINDOW: 575 * We support RGB rendering into almost any kind of visual. 576 */ 577 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { 578 setup_truecolor( v, b, cmap ); 579 } 580 else { 581 _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n"); 582 return GL_FALSE; 583 } 584 v->mesa_visual.indexBits = 0; 585 586 if (getenv("MESA_NO_DITHER")) { 587 v->dithered_pf = v->undithered_pf; 588 } 589 590 591 /* 592 * If MESA_INFO env var is set print out some debugging info 593 * which can help Brian figure out what's going on when a user 594 * reports bugs. 595 */ 596 if (getenv("MESA_INFO")) { 597 printf("X/Mesa visual = %p\n", (void *) v); 598 printf("X/Mesa dithered pf = %u\n", v->dithered_pf); 599 printf("X/Mesa undithered pf = %u\n", v->undithered_pf); 600 printf("X/Mesa level = %d\n", v->mesa_visual.level); 601 printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); 602 printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); 603 } 604 605 if (b && window) { 606 /* Do window-specific initializations */ 607 608 /* these should have been set in create_xmesa_buffer */ 609 assert(b->frontxrb->drawable == window); 610 assert(b->frontxrb->pixmap == (XMesaPixmap) window); 611 612 /* Setup for single/double buffering */ 613 if (v->mesa_visual.doubleBufferMode) { 614 /* Double buffered */ 615 b->shm = check_for_xshm( v->display ); 616 } 617 618 /* X11 graphics contexts */ 619 b->gc = XCreateGC( v->display, window, 0, NULL ); 620 XMesaSetFunction( v->display, b->gc, GXcopy ); 621 622 /* cleargc - for glClear() */ 623 b->cleargc = XCreateGC( v->display, window, 0, NULL ); 624 XMesaSetFunction( v->display, b->cleargc, GXcopy ); 625 626 /* 627 * Don't generate Graphics Expose/NoExpose events in swapbuffers(). 628 * Patch contributed by Michael Pichler May 15, 1995. 629 */ 630 { 631 XGCValues gcvalues; 632 gcvalues.graphics_exposures = False; 633 b->swapgc = XCreateGC(v->display, window, 634 GCGraphicsExposures, &gcvalues); 635 } 636 XMesaSetFunction( v->display, b->swapgc, GXcopy ); 637 } 638 639 return GL_TRUE; 640 } 641 642 643 644 /* 645 * Convert an RGBA color to a pixel value. 646 */ 647 unsigned long 648 xmesa_color_to_pixel(struct gl_context *ctx, 649 GLubyte r, GLubyte g, GLubyte b, GLubyte a, 650 GLuint pixelFormat) 651 { 652 XMesaContext xmesa = XMESA_CONTEXT(ctx); 653 switch (pixelFormat) { 654 case PF_Truecolor: 655 { 656 unsigned long p; 657 PACK_TRUECOLOR( p, r, g, b ); 658 return p; 659 } 660 case PF_8A8B8G8R: 661 return PACK_8A8B8G8R( r, g, b, a ); 662 case PF_8A8R8G8B: 663 return PACK_8A8R8G8B( r, g, b, a ); 664 case PF_8R8G8B: 665 /* fall through */ 666 case PF_8R8G8B24: 667 return PACK_8R8G8B( r, g, b ); 668 case PF_5R6G5B: 669 return PACK_5R6G5B( r, g, b ); 670 case PF_Dither_True: 671 /* fall through */ 672 case PF_Dither_5R6G5B: 673 { 674 unsigned long p; 675 PACK_TRUEDITHER(p, 1, 0, r, g, b); 676 return p; 677 } 678 default: 679 _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel"); 680 } 681 return 0; 682 } 683 684 685 #define NUM_VISUAL_TYPES 6 686 687 /** 688 * Convert an X visual type to a GLX visual type. 689 * 690 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) 691 * to be converted. 692 * \return If \c visualType is a valid X visual type, a GLX visual type will 693 * be returned. Otherwise \c GLX_NONE will be returned. 694 * 695 * \note 696 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the 697 * DRI CVS tree. 698 */ 699 static GLint 700 xmesa_convert_from_x_visual_type( int visualType ) 701 { 702 static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { 703 GLX_STATIC_GRAY, GLX_GRAY_SCALE, 704 GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, 705 GLX_TRUE_COLOR, GLX_DIRECT_COLOR 706 }; 707 708 return ( (unsigned) visualType < NUM_VISUAL_TYPES ) 709 ? glx_visual_types[ visualType ] : GLX_NONE; 710 } 711 712 713 /**********************************************************************/ 714 /***** Public Functions *****/ 715 /**********************************************************************/ 716 717 718 /* 719 * Create a new X/Mesa visual. 720 * Input: display - X11 display 721 * visinfo - an XVisualInfo pointer 722 * rgb_flag - GL_TRUE = RGB mode, 723 * GL_FALSE = color index mode 724 * alpha_flag - alpha buffer requested? 725 * db_flag - GL_TRUE = double-buffered, 726 * GL_FALSE = single buffered 727 * stereo_flag - stereo visual? 728 * ximage_flag - GL_TRUE = use an XImage for back buffer, 729 * GL_FALSE = use an off-screen pixmap for back buffer 730 * depth_size - requested bits/depth values, or zero 731 * stencil_size - requested bits/stencil values, or zero 732 * accum_red_size - requested bits/red accum values, or zero 733 * accum_green_size - requested bits/green accum values, or zero 734 * accum_blue_size - requested bits/blue accum values, or zero 735 * accum_alpha_size - requested bits/alpha accum values, or zero 736 * num_samples - number of samples/pixel if multisampling, or zero 737 * level - visual level, usually 0 738 * visualCaveat - ala the GLX extension, usually GLX_NONE 739 * Return; a new XMesaVisual or 0 if error. 740 */ 741 PUBLIC 742 XMesaVisual XMesaCreateVisual( XMesaDisplay *display, 743 XMesaVisualInfo visinfo, 744 GLboolean rgb_flag, 745 GLboolean alpha_flag, 746 GLboolean db_flag, 747 GLboolean stereo_flag, 748 GLboolean ximage_flag, 749 GLint depth_size, 750 GLint stencil_size, 751 GLint accum_red_size, 752 GLint accum_green_size, 753 GLint accum_blue_size, 754 GLint accum_alpha_size, 755 GLint num_samples, 756 GLint level, 757 GLint visualCaveat ) 758 { 759 char *gamma; 760 XMesaVisual v; 761 GLint red_bits, green_bits, blue_bits, alpha_bits; 762 763 /* For debugging only */ 764 if (getenv("MESA_XSYNC")) { 765 /* This makes debugging X easier. 766 * In your debugger, set a breakpoint on _XError to stop when an 767 * X protocol error is generated. 768 */ 769 XSynchronize( display, 1 ); 770 } 771 772 /* Color-index rendering not supported. */ 773 if (!rgb_flag) 774 return NULL; 775 776 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); 777 if (!v) { 778 return NULL; 779 } 780 781 v->display = display; 782 783 /* Save a copy of the XVisualInfo struct because the user may Xfree() 784 * the struct but we may need some of the information contained in it 785 * at a later time. 786 */ 787 v->visinfo = malloc(sizeof(*visinfo)); 788 if(!v->visinfo) { 789 free(v); 790 return NULL; 791 } 792 memcpy(v->visinfo, visinfo, sizeof(*visinfo)); 793 794 /* check for MESA_GAMMA environment variable */ 795 gamma = getenv("MESA_GAMMA"); 796 if (gamma) { 797 v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; 798 sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); 799 if (v->RedGamma<=0.0) v->RedGamma = 1.0; 800 if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; 801 if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; 802 } 803 else { 804 v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; 805 } 806 807 v->ximage_flag = ximage_flag; 808 809 v->mesa_visual.redMask = visinfo->red_mask; 810 v->mesa_visual.greenMask = visinfo->green_mask; 811 v->mesa_visual.blueMask = visinfo->blue_mask; 812 v->visualID = visinfo->visualid; 813 v->screen = visinfo->screen; 814 815 #if !(defined(__cplusplus) || defined(c_plusplus)) 816 v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); 817 #else 818 v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); 819 #endif 820 821 v->mesa_visual.visualRating = visualCaveat; 822 823 if (alpha_flag) 824 v->mesa_visual.alphaBits = 8; 825 826 (void) initialize_visual_and_buffer( v, NULL, 0, 0 ); 827 828 { 829 const int xclass = v->visualType; 830 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { 831 red_bits = _mesa_bitcount(GET_REDMASK(v)); 832 green_bits = _mesa_bitcount(GET_GREENMASK(v)); 833 blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); 834 } 835 else { 836 /* this is an approximation */ 837 int depth; 838 depth = GET_VISUAL_DEPTH(v); 839 red_bits = depth / 3; 840 depth -= red_bits; 841 green_bits = depth / 2; 842 depth -= green_bits; 843 blue_bits = depth; 844 alpha_bits = 0; 845 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); 846 } 847 alpha_bits = v->mesa_visual.alphaBits; 848 } 849 850 if (!_mesa_initialize_visual(&v->mesa_visual, 851 db_flag, stereo_flag, 852 red_bits, green_bits, 853 blue_bits, alpha_bits, 854 depth_size, 855 stencil_size, 856 accum_red_size, accum_green_size, 857 accum_blue_size, accum_alpha_size, 858 0)) { 859 free(v->visinfo); 860 free(v); 861 return NULL; 862 } 863 864 /* XXX minor hack */ 865 v->mesa_visual.level = level; 866 return v; 867 } 868 869 870 PUBLIC 871 void XMesaDestroyVisual( XMesaVisual v ) 872 { 873 free(v->visinfo); 874 free(v); 875 } 876 877 878 879 /** 880 * Create a new XMesaContext. 881 * \param v the XMesaVisual 882 * \param share_list another XMesaContext with which to share display 883 * lists or NULL if no sharing is wanted. 884 * \return an XMesaContext or NULL if error. 885 */ 886 PUBLIC 887 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 888 { 889 static GLboolean firstTime = GL_TRUE; 890 XMesaContext c; 891 struct gl_context *mesaCtx; 892 struct dd_function_table functions; 893 TNLcontext *tnl; 894 895 if (firstTime) { 896 mtx_init(&_xmesa_lock, mtx_plain); 897 firstTime = GL_FALSE; 898 } 899 900 /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */ 901 c = (XMesaContext) CALLOC_STRUCT(xmesa_context); 902 if (!c) 903 return NULL; 904 905 mesaCtx = &(c->mesa); 906 907 /* initialize with default driver functions, then plug in XMesa funcs */ 908 _mesa_init_driver_functions(&functions); 909 xmesa_init_driver_functions(v, &functions); 910 if (!_mesa_initialize_context(mesaCtx, API_OPENGL_COMPAT, &v->mesa_visual, 911 share_list ? &(share_list->mesa) : (struct gl_context *) NULL, 912 &functions)) { 913 free(c); 914 return NULL; 915 } 916 917 /* Enable this to exercise fixed function -> shader translation 918 * with software rendering. 919 */ 920 if (0) { 921 mesaCtx->VertexProgram._MaintainTnlProgram = GL_TRUE; 922 mesaCtx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; 923 } 924 925 _mesa_enable_sw_extensions(mesaCtx); 926 927 #if ENABLE_EXT_timer_query 928 mesaCtx->Extensions.EXT_timer_query = GL_TRUE; 929 #endif 930 931 932 /* finish up xmesa context initializations */ 933 c->direct = GL_TRUE; 934 c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE; 935 c->xm_visual = v; 936 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ 937 c->display = v->display; 938 c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ 939 940 /* Initialize the software rasterizer and helper modules. 941 */ 942 if (!_swrast_CreateContext( mesaCtx ) || 943 !_vbo_CreateContext( mesaCtx ) || 944 !_tnl_CreateContext( mesaCtx ) || 945 !_swsetup_CreateContext( mesaCtx )) { 946 _mesa_free_context_data(&c->mesa); 947 free(c); 948 return NULL; 949 } 950 951 /* tnl setup */ 952 tnl = TNL_CONTEXT(mesaCtx); 953 tnl->Driver.RunPipeline = _tnl_run_pipeline; 954 /* swrast setup */ 955 xmesa_register_swrast_functions( mesaCtx ); 956 _swsetup_Wakeup(mesaCtx); 957 958 _mesa_meta_init(mesaCtx); 959 960 _mesa_compute_version(mesaCtx); 961 962 /* Exec table initialization requires the version to be computed */ 963 _mesa_initialize_dispatch_tables(mesaCtx); 964 _mesa_initialize_vbo_vtxfmt(mesaCtx); 965 966 return c; 967 } 968 969 970 971 PUBLIC 972 void XMesaDestroyContext( XMesaContext c ) 973 { 974 struct gl_context *mesaCtx = &c->mesa; 975 976 _mesa_meta_free( mesaCtx ); 977 978 _swsetup_DestroyContext( mesaCtx ); 979 _swrast_DestroyContext( mesaCtx ); 980 _tnl_DestroyContext( mesaCtx ); 981 _vbo_DestroyContext( mesaCtx ); 982 _mesa_free_context_data( mesaCtx ); 983 free( c ); 984 } 985 986 987 988 /** 989 * Private function for creating an XMesaBuffer which corresponds to an 990 * X window or pixmap. 991 * \param v the window's XMesaVisual 992 * \param w the window we're wrapping 993 * \return new XMesaBuffer or NULL if error 994 */ 995 PUBLIC XMesaBuffer 996 XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) 997 { 998 XWindowAttributes attr; 999 XMesaBuffer b; 1000 XMesaColormap cmap; 1001 int depth; 1002 1003 assert(v); 1004 assert(w); 1005 1006 /* Check that window depth matches visual depth */ 1007 XGetWindowAttributes( v->display, w, &attr ); 1008 depth = attr.depth; 1009 if (GET_VISUAL_DEPTH(v) != depth) { 1010 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", 1011 GET_VISUAL_DEPTH(v), depth); 1012 return NULL; 1013 } 1014 1015 /* Find colormap */ 1016 if (attr.colormap) { 1017 cmap = attr.colormap; 1018 } 1019 else { 1020 _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); 1021 /* this is weird, a window w/out a colormap!? */ 1022 /* OK, let's just allocate a new one and hope for the best */ 1023 cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); 1024 } 1025 1026 b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap); 1027 if (!b) 1028 return NULL; 1029 1030 if (!initialize_visual_and_buffer( v, b, (XMesaDrawable) w, cmap )) { 1031 xmesa_free_buffer(b); 1032 return NULL; 1033 } 1034 1035 return b; 1036 } 1037 1038 1039 1040 /** 1041 * Create a new XMesaBuffer from an X pixmap. 1042 * 1043 * \param v the XMesaVisual 1044 * \param p the pixmap 1045 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or 1046 * \c GLX_DIRECT_COLOR visual for the pixmap 1047 * \returns new XMesaBuffer or NULL if error 1048 */ 1049 PUBLIC XMesaBuffer 1050 XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap) 1051 { 1052 XMesaBuffer b; 1053 1054 assert(v); 1055 1056 b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); 1057 if (!b) 1058 return NULL; 1059 1060 if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) { 1061 xmesa_free_buffer(b); 1062 return NULL; 1063 } 1064 1065 return b; 1066 } 1067 1068 1069 /** 1070 * For GLX_EXT_texture_from_pixmap 1071 */ 1072 XMesaBuffer 1073 XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p, 1074 XMesaColormap cmap, 1075 int format, int target, int mipmap) 1076 { 1077 GET_CURRENT_CONTEXT(ctx); 1078 XMesaBuffer b; 1079 GLuint width, height; 1080 1081 assert(v); 1082 1083 b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); 1084 if (!b) 1085 return NULL; 1086 1087 /* get pixmap size, update framebuffer/renderbuffer dims */ 1088 xmesa_get_window_size(v->display, b, &width, &height); 1089 _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height); 1090 1091 if (target == 0) { 1092 /* examine dims */ 1093 if (ctx->Extensions.ARB_texture_non_power_of_two) { 1094 target = GLX_TEXTURE_2D_EXT; 1095 } 1096 else if ( _mesa_bitcount(width) == 1 1097 && _mesa_bitcount(height) == 1) { 1098 /* power of two size */ 1099 if (height == 1) { 1100 target = GLX_TEXTURE_1D_EXT; 1101 } 1102 else { 1103 target = GLX_TEXTURE_2D_EXT; 1104 } 1105 } 1106 else if (ctx->Extensions.NV_texture_rectangle) { 1107 target = GLX_TEXTURE_RECTANGLE_EXT; 1108 } 1109 else { 1110 /* non power of two textures not supported */ 1111 XMesaDestroyBuffer(b); 1112 return 0; 1113 } 1114 } 1115 1116 b->TextureTarget = target; 1117 b->TextureFormat = format; 1118 b->TextureMipmap = mipmap; 1119 1120 if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) { 1121 xmesa_free_buffer(b); 1122 return NULL; 1123 } 1124 1125 return b; 1126 } 1127 1128 1129 1130 XMesaBuffer 1131 XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap, 1132 unsigned int width, unsigned int height) 1133 { 1134 XMesaWindow root; 1135 XMesaDrawable drawable; /* X Pixmap Drawable */ 1136 XMesaBuffer b; 1137 1138 /* allocate pixmap for front buffer */ 1139 root = RootWindow( v->display, v->visinfo->screen ); 1140 drawable = XCreatePixmap(v->display, root, width, height, 1141 v->visinfo->depth); 1142 if (!drawable) 1143 return NULL; 1144 1145 b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); 1146 if (!b) 1147 return NULL; 1148 1149 if (!initialize_visual_and_buffer(v, b, drawable, cmap)) { 1150 xmesa_free_buffer(b); 1151 return NULL; 1152 } 1153 1154 return b; 1155 } 1156 1157 1158 1159 /* 1160 * Deallocate an XMesaBuffer structure and all related info. 1161 */ 1162 PUBLIC void 1163 XMesaDestroyBuffer(XMesaBuffer b) 1164 { 1165 xmesa_free_buffer(b); 1166 } 1167 1168 1169 /** 1170 * Query the current window size and update the corresponding struct gl_framebuffer 1171 * and all attached renderbuffers. 1172 * Called when: 1173 * 1. the first time a buffer is bound to a context. 1174 * 2. from glViewport to poll for window size changes 1175 * 3. from the XMesaResizeBuffers() API function. 1176 * Note: it's possible (and legal) for xmctx to be NULL. That can happen 1177 * when resizing a buffer when no rendering context is bound. 1178 */ 1179 void 1180 xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) 1181 { 1182 GLuint width, height; 1183 xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height); 1184 if (drawBuffer->mesa_buffer.Width != width || 1185 drawBuffer->mesa_buffer.Height != height) { 1186 struct gl_context *ctx = xmctx ? &xmctx->mesa : NULL; 1187 _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height); 1188 } 1189 } 1190 1191 1192 /* 1193 * Bind buffer b to context c and make c the current rendering context. 1194 */ 1195 GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) 1196 { 1197 return XMesaMakeCurrent2( c, b, b ); 1198 } 1199 1200 1201 /* 1202 * Bind buffer b to context c and make c the current rendering context. 1203 */ 1204 PUBLIC 1205 GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, 1206 XMesaBuffer readBuffer ) 1207 { 1208 if (c) { 1209 if (!drawBuffer || !readBuffer) 1210 return GL_FALSE; /* must specify buffers! */ 1211 1212 if (&(c->mesa) == _mesa_get_current_context() 1213 && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer 1214 && c->mesa.ReadBuffer == &readBuffer->mesa_buffer 1215 && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) { 1216 /* same context and buffer, do nothing */ 1217 return GL_TRUE; 1218 } 1219 1220 c->xm_buffer = drawBuffer; 1221 1222 /* Call this periodically to detect when the user has begun using 1223 * GL rendering from multiple threads. 1224 */ 1225 _glapi_check_multithread(); 1226 1227 xmesa_check_and_update_buffer_size(c, drawBuffer); 1228 if (readBuffer != drawBuffer) 1229 xmesa_check_and_update_buffer_size(c, readBuffer); 1230 1231 _mesa_make_current(&(c->mesa), 1232 &drawBuffer->mesa_buffer, 1233 &readBuffer->mesa_buffer); 1234 1235 /* 1236 * Must recompute and set these pixel values because colormap 1237 * can be different for different windows. 1238 */ 1239 c->clearpixel = xmesa_color_to_pixel( &c->mesa, 1240 c->clearcolor[0], 1241 c->clearcolor[1], 1242 c->clearcolor[2], 1243 c->clearcolor[3], 1244 c->xm_visual->undithered_pf); 1245 XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel); 1246 1247 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 1248 drawBuffer->wasCurrent = GL_TRUE; 1249 } 1250 else { 1251 /* Detach */ 1252 _mesa_make_current( NULL, NULL, NULL ); 1253 } 1254 return GL_TRUE; 1255 } 1256 1257 1258 /* 1259 * Unbind the context c from its buffer. 1260 */ 1261 GLboolean XMesaUnbindContext( XMesaContext c ) 1262 { 1263 /* A no-op for XFree86 integration purposes */ 1264 return GL_TRUE; 1265 } 1266 1267 1268 XMesaContext XMesaGetCurrentContext( void ) 1269 { 1270 GET_CURRENT_CONTEXT(ctx); 1271 if (ctx) { 1272 XMesaContext xmesa = XMESA_CONTEXT(ctx); 1273 return xmesa; 1274 } 1275 else { 1276 return 0; 1277 } 1278 } 1279 1280 1281 XMesaBuffer XMesaGetCurrentBuffer( void ) 1282 { 1283 GET_CURRENT_CONTEXT(ctx); 1284 if (ctx) { 1285 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); 1286 return xmbuf; 1287 } 1288 else { 1289 return 0; 1290 } 1291 } 1292 1293 1294 /* New in Mesa 3.1 */ 1295 XMesaBuffer XMesaGetCurrentReadBuffer( void ) 1296 { 1297 GET_CURRENT_CONTEXT(ctx); 1298 if (ctx) { 1299 return XMESA_BUFFER(ctx->ReadBuffer); 1300 } 1301 else { 1302 return 0; 1303 } 1304 } 1305 1306 1307 1308 GLboolean XMesaSetFXmode( GLint mode ) 1309 { 1310 (void) mode; 1311 return GL_FALSE; 1312 } 1313 1314 1315 1316 /* 1317 * Copy the back buffer to the front buffer. If there's no back buffer 1318 * this is a no-op. 1319 */ 1320 PUBLIC 1321 void XMesaSwapBuffers( XMesaBuffer b ) 1322 { 1323 GET_CURRENT_CONTEXT(ctx); 1324 1325 if (!b->backxrb) { 1326 /* single buffered */ 1327 return; 1328 } 1329 1330 /* If we're swapping the buffer associated with the current context 1331 * we have to flush any pending rendering commands first. 1332 */ 1333 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 1334 _mesa_notifySwapBuffers(ctx); 1335 1336 if (b->db_mode) { 1337 if (b->backxrb->ximage) { 1338 /* Copy Ximage (back buf) from client memory to server window */ 1339 #if defined(USE_XSHM) 1340 if (b->shm) { 1341 /*mtx_lock(&_xmesa_lock);*/ 1342 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 1343 b->swapgc, 1344 b->backxrb->ximage, 0, 0, 1345 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 1346 False ); 1347 /*mtx_unlock(&_xmesa_lock);*/ 1348 } 1349 else 1350 #endif 1351 { 1352 /*mtx_lock(&_xmesa_lock);*/ 1353 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 1354 b->swapgc, 1355 b->backxrb->ximage, 0, 0, 1356 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height ); 1357 /*mtx_unlock(&_xmesa_lock);*/ 1358 } 1359 } 1360 else if (b->backxrb->pixmap) { 1361 /* Copy pixmap (back buf) to window (front buf) on server */ 1362 /*mtx_lock(&_xmesa_lock);*/ 1363 XMesaCopyArea( b->xm_visual->display, 1364 b->backxrb->pixmap, /* source drawable */ 1365 b->frontxrb->drawable, /* dest. drawable */ 1366 b->swapgc, 1367 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 1368 0, 0 /* dest region */ 1369 ); 1370 /*mtx_unlock(&_xmesa_lock);*/ 1371 } 1372 } 1373 XSync( b->xm_visual->display, False ); 1374 } 1375 1376 1377 1378 /* 1379 * Copy sub-region of back buffer to front buffer 1380 */ 1381 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 1382 { 1383 GET_CURRENT_CONTEXT(ctx); 1384 1385 /* If we're swapping the buffer associated with the current context 1386 * we have to flush any pending rendering commands first. 1387 */ 1388 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 1389 _mesa_notifySwapBuffers(ctx); 1390 1391 if (!b->backxrb) { 1392 /* single buffered */ 1393 return; 1394 } 1395 1396 if (b->db_mode) { 1397 int yTop = b->mesa_buffer.Height - y - height; 1398 if (b->backxrb->ximage) { 1399 /* Copy Ximage from host's memory to server's window */ 1400 #if defined(USE_XSHM) 1401 if (b->shm) { 1402 /* XXX assuming width and height aren't too large! */ 1403 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 1404 b->swapgc, 1405 b->backxrb->ximage, x, yTop, 1406 x, yTop, width, height, False ); 1407 /* wait for finished event??? */ 1408 } 1409 else 1410 #endif 1411 { 1412 /* XXX assuming width and height aren't too large! */ 1413 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 1414 b->swapgc, 1415 b->backxrb->ximage, x, yTop, 1416 x, yTop, width, height ); 1417 } 1418 } 1419 else { 1420 /* Copy pixmap to window on server */ 1421 XMesaCopyArea( b->xm_visual->display, 1422 b->backxrb->pixmap, /* source drawable */ 1423 b->frontxrb->drawable, /* dest. drawable */ 1424 b->swapgc, 1425 x, yTop, width, height, /* source region */ 1426 x, yTop /* dest region */ 1427 ); 1428 } 1429 } 1430 } 1431 1432 1433 /* 1434 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function 1435 * is a way to get "under the hood" of X/Mesa so one can manipulate the 1436 * back buffer directly. 1437 * Output: pixmap - pointer to back buffer's Pixmap, or 0 1438 * ximage - pointer to back buffer's XImage, or NULL 1439 * Return: GL_TRUE = context is double buffered 1440 * GL_FALSE = context is single buffered 1441 */ 1442 GLboolean XMesaGetBackBuffer( XMesaBuffer b, 1443 XMesaPixmap *pixmap, 1444 XMesaImage **ximage ) 1445 { 1446 if (b->db_mode) { 1447 if (pixmap) 1448 *pixmap = b->backxrb->pixmap; 1449 if (ximage) 1450 *ximage = b->backxrb->ximage; 1451 return GL_TRUE; 1452 } 1453 else { 1454 *pixmap = 0; 1455 *ximage = NULL; 1456 return GL_FALSE; 1457 } 1458 } 1459 1460 1461 /* 1462 * Return the depth buffer associated with an XMesaBuffer. 1463 * Input: b - the XMesa buffer handle 1464 * Output: width, height - size of buffer in pixels 1465 * bytesPerValue - bytes per depth value (2 or 4) 1466 * buffer - pointer to depth buffer values 1467 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1468 */ 1469 GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, 1470 GLint *bytesPerValue, void **buffer ) 1471 { 1472 struct gl_renderbuffer *rb 1473 = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer; 1474 struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); 1475 1476 if (!xrb || !xrb->Base.Buffer) { 1477 *width = 0; 1478 *height = 0; 1479 *bytesPerValue = 0; 1480 *buffer = 0; 1481 return GL_FALSE; 1482 } 1483 else { 1484 *width = b->mesa_buffer.Width; 1485 *height = b->mesa_buffer.Height; 1486 *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 1487 ? sizeof(GLushort) : sizeof(GLuint); 1488 *buffer = (void *) xrb->Base.Buffer; 1489 return GL_TRUE; 1490 } 1491 } 1492 1493 1494 void XMesaFlush( XMesaContext c ) 1495 { 1496 if (c && c->xm_visual) { 1497 XSync( c->xm_visual->display, False ); 1498 } 1499 } 1500 1501 1502 1503 const char *XMesaGetString( XMesaContext c, int name ) 1504 { 1505 (void) c; 1506 if (name==XMESA_VERSION) { 1507 return "5.0"; 1508 } 1509 else if (name==XMESA_EXTENSIONS) { 1510 return ""; 1511 } 1512 else { 1513 return NULL; 1514 } 1515 } 1516 1517 1518 1519 XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) 1520 { 1521 XMesaBuffer b; 1522 for (b=XMesaBufferList; b; b=b->Next) { 1523 if (b->frontxrb->drawable == d && b->display == dpy) { 1524 return b; 1525 } 1526 } 1527 return NULL; 1528 } 1529 1530 1531 /** 1532 * Free/destroy all XMesaBuffers associated with given display. 1533 */ 1534 void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) 1535 { 1536 XMesaBuffer b, next; 1537 for (b = XMesaBufferList; b; b = next) { 1538 next = b->Next; 1539 if (b->display == dpy) { 1540 xmesa_free_buffer(b); 1541 } 1542 } 1543 } 1544 1545 1546 /* 1547 * Look for XMesaBuffers whose X window has been destroyed. 1548 * Deallocate any such XMesaBuffers. 1549 */ 1550 void XMesaGarbageCollect( XMesaDisplay* dpy ) 1551 { 1552 XMesaBuffer b, next; 1553 for (b=XMesaBufferList; b; b=next) { 1554 next = b->Next; 1555 if (b->display && b->display == dpy && b->frontxrb->drawable && b->type == WINDOW) { 1556 XSync(b->display, False); 1557 if (!window_exists( b->display, b->frontxrb->drawable )) { 1558 /* found a dead window, free the ancillary info */ 1559 XMesaDestroyBuffer( b ); 1560 } 1561 } 1562 } 1563 } 1564 1565 1566 unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, 1567 GLfloat red, GLfloat green, 1568 GLfloat blue, GLfloat alpha ) 1569 { 1570 GLint r = (GLint) (red * 255.0F); 1571 GLint g = (GLint) (green * 255.0F); 1572 GLint b = (GLint) (blue * 255.0F); 1573 GLint a = (GLint) (alpha * 255.0F); 1574 1575 switch (xmesa->pixelformat) { 1576 case PF_Truecolor: 1577 { 1578 unsigned long p; 1579 PACK_TRUECOLOR( p, r, g, b ); 1580 return p; 1581 } 1582 case PF_8A8B8G8R: 1583 return PACK_8A8B8G8R( r, g, b, a ); 1584 case PF_8A8R8G8B: 1585 return PACK_8A8R8G8B( r, g, b, a ); 1586 case PF_8R8G8B: 1587 return PACK_8R8G8B( r, g, b ); 1588 case PF_5R6G5B: 1589 return PACK_5R6G5B( r, g, b ); 1590 case PF_Dither_5R6G5B: 1591 /* fall through */ 1592 case PF_Dither_True: 1593 { 1594 unsigned long p; 1595 PACK_TRUEDITHER(p, x, y, r, g, b); 1596 return p; 1597 } 1598 default: 1599 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); 1600 } 1601 return 0; 1602 } 1603 1604 1605 /* 1606 * This is typically called when the window size changes and we need 1607 * to reallocate the buffer's back/depth/stencil/accum buffers. 1608 */ 1609 PUBLIC void 1610 XMesaResizeBuffers( XMesaBuffer b ) 1611 { 1612 GET_CURRENT_CONTEXT(ctx); 1613 XMesaContext xmctx = XMESA_CONTEXT(ctx); 1614 if (!xmctx) 1615 return; 1616 xmesa_check_and_update_buffer_size(xmctx, b); 1617 } 1618 1619 1620 static GLint 1621 xbuffer_to_renderbuffer(int buffer) 1622 { 1623 assert(MAX_AUX_BUFFERS <= 4); 1624 1625 switch (buffer) { 1626 case GLX_FRONT_LEFT_EXT: 1627 return BUFFER_FRONT_LEFT; 1628 case GLX_FRONT_RIGHT_EXT: 1629 return BUFFER_FRONT_RIGHT; 1630 case GLX_BACK_LEFT_EXT: 1631 return BUFFER_BACK_LEFT; 1632 case GLX_BACK_RIGHT_EXT: 1633 return BUFFER_BACK_RIGHT; 1634 case GLX_AUX0_EXT: 1635 return BUFFER_AUX0; 1636 case GLX_AUX1_EXT: 1637 case GLX_AUX2_EXT: 1638 case GLX_AUX3_EXT: 1639 case GLX_AUX4_EXT: 1640 case GLX_AUX5_EXT: 1641 case GLX_AUX6_EXT: 1642 case GLX_AUX7_EXT: 1643 case GLX_AUX8_EXT: 1644 case GLX_AUX9_EXT: 1645 default: 1646 /* BadValue error */ 1647 return -1; 1648 } 1649 } 1650 1651 1652 PUBLIC void 1653 XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer, 1654 const int *attrib_list) 1655 { 1656 #if 0 1657 GET_CURRENT_CONTEXT(ctx); 1658 const GLuint unit = ctx->Texture.CurrentUnit; 1659 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 1660 struct gl_texture_object *texObj; 1661 #endif 1662 struct gl_renderbuffer *rb; 1663 struct xmesa_renderbuffer *xrb; 1664 GLint b; 1665 XMesaImage *img = NULL; 1666 GLboolean freeImg = GL_FALSE; 1667 1668 b = xbuffer_to_renderbuffer(buffer); 1669 if (b < 0) 1670 return; 1671 1672 if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT) 1673 return; /* BadMatch error */ 1674 1675 rb = drawable->mesa_buffer.Attachment[b].Renderbuffer; 1676 if (!rb) { 1677 /* invalid buffer */ 1678 return; 1679 } 1680 xrb = xmesa_renderbuffer(rb); 1681 1682 #if 0 1683 switch (drawable->TextureTarget) { 1684 case GLX_TEXTURE_1D_EXT: 1685 texObj = texUnit->CurrentTex[TEXTURE_1D_INDEX]; 1686 break; 1687 case GLX_TEXTURE_2D_EXT: 1688 texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX]; 1689 break; 1690 case GLX_TEXTURE_RECTANGLE_EXT: 1691 texObj = texUnit->CurrentTex[TEXTURE_RECT_INDEX]; 1692 break; 1693 default: 1694 return; /* BadMatch error */ 1695 } 1696 #endif 1697 1698 /* 1699 * The following is a quick and simple way to implement 1700 * BindTexImage. The better way is to write some new FetchTexel() 1701 * functions which would extract texels from XImages. We'd still 1702 * need to use GetImage when texturing from a Pixmap (front buffer) 1703 * but texturing from a back buffer (XImage) would avoid an image 1704 * copy. 1705 */ 1706 1707 /* get XImage */ 1708 if (xrb->pixmap) { 1709 img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L, 1710 ZPixmap); 1711 freeImg = GL_TRUE; 1712 } 1713 else if (xrb->ximage) { 1714 img = xrb->ximage; 1715 } 1716 1717 /* store the XImage as a new texture image */ 1718 if (img) { 1719 GLenum format, type, intFormat; 1720 if (img->bits_per_pixel == 32) { 1721 format = GL_BGRA; 1722 type = GL_UNSIGNED_BYTE; 1723 intFormat = GL_RGBA; 1724 } 1725 else if (img->bits_per_pixel == 24) { 1726 format = GL_BGR; 1727 type = GL_UNSIGNED_BYTE; 1728 intFormat = GL_RGB; 1729 } 1730 else if (img->bits_per_pixel == 16) { 1731 format = GL_BGR; 1732 type = GL_UNSIGNED_SHORT_5_6_5; 1733 intFormat = GL_RGB; 1734 } 1735 else { 1736 _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage"); 1737 return; 1738 } 1739 if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) { 1740 intFormat = GL_RGBA; 1741 } 1742 else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) { 1743 intFormat = GL_RGB; 1744 } 1745 1746 _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0, 1747 format, type, img->data); 1748 1749 if (freeImg) { 1750 XMesaDestroyImage(img); 1751 } 1752 } 1753 } 1754 1755 1756 1757 PUBLIC void 1758 XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer) 1759 { 1760 const GLint b = xbuffer_to_renderbuffer(buffer); 1761 if (b < 0) 1762 return; 1763 1764 /* no-op for now */ 1765 } 1766 1767