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