xm_api.c revision 3049946fa742b654afa9b24f8bc79f387f01aea9
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 */ 1846void 1847xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) 1848{ 1849 GLuint width, height; 1850 xmesa_get_window_size(xmctx->display, drawBuffer, &width, &height); 1851 if (drawBuffer->mesa_buffer.Width != width || 1852 drawBuffer->mesa_buffer.Height != height) { 1853 _mesa_resize_framebuffer(&(xmctx->mesa), 1854 &(drawBuffer->mesa_buffer), width, height); 1855 } 1856 drawBuffer->mesa_buffer.Initialized = GL_TRUE; /* XXX TEMPORARY? */ 1857} 1858 1859 1860/* 1861 * Bind buffer b to context c and make c the current rendering context. 1862 */ 1863GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) 1864{ 1865 return XMesaMakeCurrent2( c, b, b ); 1866} 1867 1868 1869/* 1870 * Bind buffer b to context c and make c the current rendering context. 1871 */ 1872GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, 1873 XMesaBuffer readBuffer ) 1874{ 1875 if (c) { 1876 if (!drawBuffer || !readBuffer) 1877 return GL_FALSE; /* must specify buffers! */ 1878 1879#ifdef FX 1880 if (drawBuffer->FXctx) { 1881 fxMesaMakeCurrent(drawBuffer->FXctx); 1882 1883 c->xm_buffer = drawBuffer; 1884 1885 return GL_TRUE; 1886 } 1887#endif 1888 if (&(c->mesa) == _mesa_get_current_context() 1889 && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer 1890 && c->mesa.ReadBuffer == &readBuffer->mesa_buffer 1891 && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) { 1892 /* same context and buffer, do nothing */ 1893 return GL_TRUE; 1894 } 1895 1896 c->xm_buffer = drawBuffer; 1897 1898 /* Call this periodically to detect when the user has begun using 1899 * GL rendering from multiple threads. 1900 */ 1901 _glapi_check_multithread(); 1902 1903 xmesa_check_and_update_buffer_size(c, drawBuffer); 1904 if (readBuffer != drawBuffer) 1905 xmesa_check_and_update_buffer_size(c, readBuffer); 1906 1907 _mesa_make_current(&(c->mesa), 1908 &drawBuffer->mesa_buffer, 1909 &readBuffer->mesa_buffer); 1910 1911 if (c->xm_visual->mesa_visual.rgbMode) { 1912 /* 1913 * Must recompute and set these pixel values because colormap 1914 * can be different for different windows. 1915 */ 1916 c->clearpixel = xmesa_color_to_pixel( &c->mesa, 1917 c->clearcolor[0], 1918 c->clearcolor[1], 1919 c->clearcolor[2], 1920 c->clearcolor[3], 1921 c->xm_visual->undithered_pf); 1922 XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel); 1923 } 1924 1925 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 1926 drawBuffer->wasCurrent = GL_TRUE; 1927 } 1928 else { 1929 /* Detach */ 1930 _mesa_make_current( NULL, NULL, NULL ); 1931 } 1932 return GL_TRUE; 1933} 1934 1935 1936/* 1937 * Unbind the context c from its buffer. 1938 */ 1939GLboolean XMesaUnbindContext( XMesaContext c ) 1940{ 1941 /* A no-op for XFree86 integration purposes */ 1942 return GL_TRUE; 1943} 1944 1945 1946XMesaContext XMesaGetCurrentContext( void ) 1947{ 1948 GET_CURRENT_CONTEXT(ctx); 1949 if (ctx) { 1950 XMesaContext xmesa = XMESA_CONTEXT(ctx); 1951 return xmesa; 1952 } 1953 else { 1954 return 0; 1955 } 1956} 1957 1958 1959XMesaBuffer XMesaGetCurrentBuffer( void ) 1960{ 1961 GET_CURRENT_CONTEXT(ctx); 1962 if (ctx) { 1963 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); 1964 return xmbuf; 1965 } 1966 else { 1967 return 0; 1968 } 1969} 1970 1971 1972/* New in Mesa 3.1 */ 1973XMesaBuffer XMesaGetCurrentReadBuffer( void ) 1974{ 1975 GET_CURRENT_CONTEXT(ctx); 1976 if (ctx) { 1977 return XMESA_BUFFER(ctx->ReadBuffer); 1978 } 1979 else { 1980 return 0; 1981 } 1982} 1983 1984 1985GLboolean XMesaForceCurrent(XMesaContext c) 1986{ 1987 if (c) { 1988 if (&(c->mesa) != _mesa_get_current_context()) { 1989 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer); 1990 } 1991 } 1992 else { 1993 _mesa_make_current(NULL, NULL, NULL); 1994 } 1995 return GL_TRUE; 1996} 1997 1998 1999GLboolean XMesaLoseCurrent(XMesaContext c) 2000{ 2001 (void) c; 2002 _mesa_make_current(NULL, NULL, NULL); 2003 return GL_TRUE; 2004} 2005 2006 2007/* 2008 * Switch 3Dfx support hack between window and full-screen mode. 2009 */ 2010GLboolean XMesaSetFXmode( GLint mode ) 2011{ 2012#ifdef FX 2013 const char *fx = _mesa_getenv("MESA_GLX_FX"); 2014 if (fx && fx[0] != 'd') { 2015 GET_CURRENT_CONTEXT(ctx); 2016 GrHwConfiguration hw; 2017 if (!FX_grSstQueryHardware(&hw)) { 2018 /*fprintf(stderr, "!grSstQueryHardware\n");*/ 2019 return GL_FALSE; 2020 } 2021 if (hw.num_sst < 1) { 2022 /*fprintf(stderr, "hw.num_sst < 1\n");*/ 2023 return GL_FALSE; 2024 } 2025 if (ctx) { 2026 /* [dBorca] Hack alert: 2027 * oh, this is sooo wrong: ctx above is 2028 * really an fxMesaContext, not an XMesaContext 2029 */ 2030 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); 2031 if (mode == XMESA_FX_WINDOW) { 2032 if (xmbuf->FXisHackUsable) { 2033 FX_grSstControl(GR_CONTROL_DEACTIVATE); 2034 xmbuf->FXwindowHack = GL_TRUE; 2035 return GL_TRUE; 2036 } 2037 } 2038 else if (mode == XMESA_FX_FULLSCREEN) { 2039 FX_grSstControl(GR_CONTROL_ACTIVATE); 2040 xmbuf->FXwindowHack = GL_FALSE; 2041 return GL_TRUE; 2042 } 2043 else { 2044 /* Error: Bad mode value */ 2045 } 2046 } 2047 } 2048 /*fprintf(stderr, "fallthrough\n");*/ 2049#else 2050 (void) mode; 2051#endif 2052 return GL_FALSE; 2053} 2054 2055 2056 2057#ifdef FX 2058/* 2059 * Read image from VooDoo frame buffer into X/Mesa's back XImage. 2060 */ 2061static void FXgetImage( XMesaBuffer b ) 2062{ 2063 GET_CURRENT_CONTEXT(ctx); 2064 static unsigned short pixbuf[MAX_WIDTH]; 2065 GLuint x, y; 2066 GLuint width, height; 2067 XMesaContext xmesa = XMESA_CONTEXT(ctx); 2068 2069#ifdef XFree86Server 2070 x = b->frontxrb->pixmap->x; 2071 y = b->frontxrb->pixmap->y; 2072 width = b->frontxrb->pixmap->width; 2073 height = b->frontxrb->pixmap->height; 2074 depth = b->frontxrb->pixmap->depth; 2075#else 2076 xmesa_get_window_size(b->display, b, &width, &height); 2077 x = y = 0; 2078#endif 2079 if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) { 2080 b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width); 2081 b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height); 2082 if (b->mesa_buffer.Width & 1) 2083 b->mesa_buffer.Width--; /* prevent odd width */ 2084 } 2085 2086 /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */ 2087 /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */ 2088 if (b->xm_visual->undithered_pf==PF_5R6G5B) { 2089 /* Special case: 16bpp RGB */ 2090 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ 2091 0, b->FXctx->height - b->mesa_buffer.Height, /*pos*/ 2092 b->mesa_buffer.Width, b->mesa_buffer.Height, /* size */ 2093 b->mesa_buffer.Width * sizeof(GLushort), /* stride */ 2094 b->backxrb->ximage->data); /* dest buffer */ 2095 } 2096 else if (b->xm_visual->dithered_pf==PF_Dither 2097 && GET_VISUAL_DEPTH(b->xm_visual)==8) { 2098 /* Special case: 8bpp RGB */ 2099 for (y=0;y<b->mesa_buffer.Height;y++) { 2100 GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data 2101 + b->backxrb->ximage->bytes_per_line * y; 2102 XDITHER_SETUP(y); 2103 2104 /* read row from 3Dfx frame buffer */ 2105 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2106 0, b->FXctx->height-(b->mesa_buffer.Height-y), 2107 b->mesa_buffer.Width, 1, 2108 0, 2109 pixbuf ); 2110 2111 /* write to XImage back buffer */ 2112 for (x=0;x<b->mesa_buffer.Width;x++) { 2113 GLubyte r = (pixbuf[x] & 0xf800) >> 8; 2114 GLubyte g = (pixbuf[x] & 0x07e0) >> 3; 2115 GLubyte b = (pixbuf[x] & 0x001f) << 3; 2116 *ptr++ = XDITHER( x, r, g, b); 2117 } 2118 } 2119 } 2120 else { 2121 /* General case: slow! */ 2122 for (y=0;y<b->mesa_buffer.Height;y++) { 2123 /* read row from 3Dfx frame buffer */ 2124 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 2125 0, b->FXctx->height-(b->mesa_buffer.Height-y), 2126 b->mesa_buffer.Width, 1, 2127 0, 2128 pixbuf ); 2129 2130 /* write to XImage back buffer */ 2131 for (x=0;x<b->mesa_buffer.Width;x++) { 2132 XMesaPutPixel(b->backxrb->ximage,x,y, 2133 xmesa_color_to_pixel(ctx, 2134 (pixbuf[x] & 0xf800) >> 8, 2135 (pixbuf[x] & 0x07e0) >> 3, 2136 (pixbuf[x] & 0x001f) << 3, 2137 0xff, 2138 b->xm_visual->undithered_pf)); 2139 } 2140 } 2141 } 2142 /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */ 2143} 2144#endif 2145 2146 2147/* 2148 * Copy the back buffer to the front buffer. If there's no back buffer 2149 * this is a no-op. 2150 */ 2151void XMesaSwapBuffers( XMesaBuffer b ) 2152{ 2153 GET_CURRENT_CONTEXT(ctx); 2154 2155 if (!b->backxrb) { 2156 /* single buffered */ 2157 return; 2158 } 2159 2160 /* If we're swapping the buffer associated with the current context 2161 * we have to flush any pending rendering commands first. 2162 */ 2163 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2164 _mesa_notifySwapBuffers(ctx); 2165 2166 if (b->db_mode) { 2167#ifdef FX 2168 if (b->FXctx) { 2169 fxMesaSwapBuffers(); 2170 2171 if (b->FXwindowHack) 2172 FXgetImage(b); 2173 else 2174 return; 2175 } 2176#endif 2177 if (b->backxrb->ximage) { 2178 /* Copy Ximage from host's memory to server's window */ 2179#if defined(USE_XSHM) && !defined(XFree86Server) 2180 if (b->shm) { 2181 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2182 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 2183 b->swapgc, 2184 b->backxrb->ximage, 0, 0, 2185 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 2186 False ); 2187 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2188 } 2189 else 2190#endif 2191 { 2192 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2193 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 2194 b->swapgc, 2195 b->backxrb->ximage, 0, 0, 2196 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height ); 2197 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2198 } 2199 } 2200 else { 2201 /* Copy pixmap to window on server */ 2202 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ 2203 XMesaCopyArea( b->xm_visual->display, 2204 b->backxrb->pixmap, /* source drawable */ 2205 b->frontxrb->drawable, /* dest. drawable */ 2206 b->swapgc, 2207 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 2208 0, 0 /* dest region */ 2209 ); 2210 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ 2211 } 2212 } 2213#if !defined(XFree86Server) 2214 XSync( b->xm_visual->display, False ); 2215#endif 2216} 2217 2218 2219 2220/* 2221 * Copy sub-region of back buffer to front buffer 2222 */ 2223void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 2224{ 2225 GET_CURRENT_CONTEXT(ctx); 2226 2227 /* If we're swapping the buffer associated with the current context 2228 * we have to flush any pending rendering commands first. 2229 */ 2230 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 2231 _mesa_notifySwapBuffers(ctx); 2232 2233 if (!b->backxrb) { 2234 /* single buffered */ 2235 return; 2236 } 2237 2238 if (b->db_mode) { 2239 int yTop = b->mesa_buffer.Height - y - height; 2240#ifdef FX 2241 if (b->FXctx) { 2242 fxMesaSwapBuffers(); 2243 if (b->FXwindowHack) 2244 FXgetImage(b); 2245 else 2246 return; 2247 } 2248#endif 2249 if (b->backxrb->ximage) { 2250 /* Copy Ximage from host's memory to server's window */ 2251#if defined(USE_XSHM) && !defined(XFree86Server) 2252 if (b->shm) { 2253 /* XXX assuming width and height aren't too large! */ 2254 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 2255 b->swapgc, 2256 b->backxrb->ximage, x, yTop, 2257 x, yTop, width, height, False ); 2258 /* wait for finished event??? */ 2259 } 2260 else 2261#endif 2262 { 2263 /* XXX assuming width and height aren't too large! */ 2264 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 2265 b->swapgc, 2266 b->backxrb->ximage, x, yTop, 2267 x, yTop, width, height ); 2268 } 2269 } 2270 else { 2271 /* Copy pixmap to window on server */ 2272 XMesaCopyArea( b->xm_visual->display, 2273 b->backxrb->pixmap, /* source drawable */ 2274 b->frontxrb->drawable, /* dest. drawable */ 2275 b->swapgc, 2276 x, yTop, width, height, /* source region */ 2277 x, yTop /* dest region */ 2278 ); 2279 } 2280 } 2281} 2282 2283 2284/* 2285 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function 2286 * is a way to get "under the hood" of X/Mesa so one can manipulate the 2287 * back buffer directly. 2288 * Output: pixmap - pointer to back buffer's Pixmap, or 0 2289 * ximage - pointer to back buffer's XImage, or NULL 2290 * Return: GL_TRUE = context is double buffered 2291 * GL_FALSE = context is single buffered 2292 */ 2293#ifndef XFree86Server 2294GLboolean XMesaGetBackBuffer( XMesaBuffer b, 2295 XMesaPixmap *pixmap, 2296 XMesaImage **ximage ) 2297{ 2298 if (b->db_mode) { 2299 if (pixmap) 2300 *pixmap = b->backxrb->pixmap; 2301 if (ximage) 2302 *ximage = b->backxrb->ximage; 2303 return GL_TRUE; 2304 } 2305 else { 2306 *pixmap = 0; 2307 *ximage = NULL; 2308 return GL_FALSE; 2309 } 2310} 2311#endif /* XFree86Server */ 2312 2313 2314/* 2315 * Return the depth buffer associated with an XMesaBuffer. 2316 * Input: b - the XMesa buffer handle 2317 * Output: width, height - size of buffer in pixels 2318 * bytesPerValue - bytes per depth value (2 or 4) 2319 * buffer - pointer to depth buffer values 2320 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 2321 */ 2322GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, 2323 GLint *bytesPerValue, void **buffer ) 2324{ 2325 struct gl_renderbuffer *rb 2326 = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer; 2327 if (!rb || !rb->Data) { 2328 *width = 0; 2329 *height = 0; 2330 *bytesPerValue = 0; 2331 *buffer = 0; 2332 return GL_FALSE; 2333 } 2334 else { 2335 *width = b->mesa_buffer.Width; 2336 *height = b->mesa_buffer.Height; 2337 *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 2338 ? sizeof(GLushort) : sizeof(GLuint); 2339 *buffer = rb->Data; 2340 return GL_TRUE; 2341 } 2342} 2343 2344 2345void XMesaFlush( XMesaContext c ) 2346{ 2347 if (c && c->xm_visual) { 2348#ifdef XFree86Server 2349 /* NOT_NEEDED */ 2350#else 2351 XSync( c->xm_visual->display, False ); 2352#endif 2353 } 2354} 2355 2356 2357 2358const char *XMesaGetString( XMesaContext c, int name ) 2359{ 2360 (void) c; 2361 if (name==XMESA_VERSION) { 2362 return "5.0"; 2363 } 2364 else if (name==XMESA_EXTENSIONS) { 2365 return ""; 2366 } 2367 else { 2368 return NULL; 2369 } 2370} 2371 2372 2373 2374XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) 2375{ 2376 XMesaBuffer b; 2377 for (b=XMesaBufferList; b; b=b->Next) { 2378 if (b->frontxrb->drawable == d && b->display == dpy) { 2379 return b; 2380 } 2381 } 2382 return NULL; 2383} 2384 2385 2386/** 2387 * Free/destroy all XMesaBuffers associated with given display. 2388 */ 2389void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) 2390{ 2391 XMesaBuffer b, next; 2392 for (b = XMesaBufferList; b; b = next) { 2393 next = b->Next; 2394 if (b->display == dpy) { 2395 xmesa_free_buffer(b); 2396 } 2397 } 2398} 2399 2400 2401/* 2402 * Look for XMesaBuffers whose X window has been destroyed. 2403 * Deallocate any such XMesaBuffers. 2404 */ 2405void XMesaGarbageCollect( void ) 2406{ 2407 XMesaBuffer b, next; 2408 for (b=XMesaBufferList; b; b=next) { 2409 next = b->Next; 2410 if (b->display && b->frontxrb->drawable && b->type == WINDOW) { 2411#ifdef XFree86Server 2412 /* NOT_NEEDED */ 2413#else 2414 XSync(b->display, False); 2415 if (!window_exists( b->display, b->frontxrb->drawable )) { 2416 /* found a dead window, free the ancillary info */ 2417 XMesaDestroyBuffer( b ); 2418 } 2419#endif 2420 } 2421 } 2422} 2423 2424 2425void XMesaReset( void ) 2426{ 2427 while (XMesaBufferList) 2428 XMesaDestroyBuffer(XMesaBufferList); 2429 2430 XMesaBufferList = NULL; 2431} 2432 2433 2434unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, 2435 GLfloat red, GLfloat green, 2436 GLfloat blue, GLfloat alpha ) 2437{ 2438 GLcontext *ctx = &xmesa->mesa; 2439 GLint r = (GLint) (red * 255.0F); 2440 GLint g = (GLint) (green * 255.0F); 2441 GLint b = (GLint) (blue * 255.0F); 2442 GLint a = (GLint) (alpha * 255.0F); 2443 2444 switch (xmesa->pixelformat) { 2445 case PF_Index: 2446 return 0; 2447 case PF_Truecolor: 2448 { 2449 unsigned long p; 2450 PACK_TRUECOLOR( p, r, g, b ); 2451 return p; 2452 } 2453 case PF_8A8B8G8R: 2454 return PACK_8A8B8G8R( r, g, b, a ); 2455 case PF_8A8R8G8B: 2456 return PACK_8A8R8G8B( r, g, b, a ); 2457 case PF_8R8G8B: 2458 return PACK_8R8G8B( r, g, b ); 2459 case PF_5R6G5B: 2460 return PACK_5R6G5B( r, g, b ); 2461 case PF_Dither: 2462 { 2463 DITHER_SETUP; 2464 return DITHER( x, y, r, g, b ); 2465 } 2466 case PF_1Bit: 2467 /* 382 = (3*255)/2 */ 2468 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; 2469 case PF_HPCR: 2470 return DITHER_HPCR(x, y, r, g, b); 2471 case PF_Lookup: 2472 { 2473 LOOKUP_SETUP; 2474 return LOOKUP( r, g, b ); 2475 } 2476 case PF_Grayscale: 2477 return GRAY_RGB( r, g, b ); 2478 case PF_Dither_5R6G5B: 2479 /* fall through */ 2480 case PF_Dither_True: 2481 { 2482 unsigned long p; 2483 PACK_TRUEDITHER(p, x, y, r, g, b); 2484 return p; 2485 } 2486 default: 2487 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); 2488 } 2489 return 0; 2490} 2491 2492 2493/* 2494 * This is typically called when the window size changes and we need 2495 * to reallocate the buffer's back/depth/stencil/accum buffers. 2496 */ 2497void 2498XMesaResizeBuffers( XMesaBuffer b ) 2499{ 2500 GET_CURRENT_CONTEXT(ctx); 2501 XMesaContext xmctx = XMESA_CONTEXT(ctx); 2502 xmesa_check_and_update_buffer_size(xmctx, b); 2503} 2504 2505