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