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