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