xm_api.c revision b1394fa92aaaf859ce9efc8b5fc194397921320c
1/* $Id: xm_api.c,v 1.2 2000/09/26 20:54:13 brianp 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
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#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1659   c->driContextPriv = driContextPriv;
1660#endif
1661
1662   /* Run the config file */
1663   _mesa_context_initialize( c->gl_ctx );
1664
1665   return c;
1666}
1667
1668
1669
1670
1671void XMesaDestroyContext( XMesaContext c )
1672{
1673#ifdef FX
1674   if (c->xm_buffer && c->xm_buffer->FXctx)
1675      fxMesaDestroyContext(c->xm_buffer->FXctx);
1676#endif
1677   if (c->gl_ctx)
1678      _mesa_destroy_context( c->gl_ctx );
1679
1680   /* Disassociate old buffer with this context */
1681   if (c->xm_buffer)
1682       c->xm_buffer->xm_context = NULL;
1683
1684   /* Destroy any buffers which are using this context.  If we don't
1685    * we may have dangling references.  Hmm, maybe we should just
1686    * set the buffer's context pointer to NULL instead of deleting it?
1687    * Let's see if we get any bug reports...
1688    * This contributed by Doug Rabson <dfr@calcaphon.com>
1689    */
1690   {
1691      XMesaBuffer b, next;
1692      for (b = XMesaBufferList; b; b = next) {
1693         next = b->Next;
1694         if (!b->pixmap_flag) {
1695#ifndef XFree86Server
1696            XSync(b->display, False);
1697#endif
1698            if (b->xm_context == c) {
1699               /* found a context created for this context */
1700               XMesaDestroyBuffer( b );
1701            }
1702         }
1703      }
1704   }
1705
1706   FREE( c );
1707}
1708
1709
1710
1711/*
1712 * XXX this isn't a public function!  It's a hack for the 3Dfx driver.
1713 * Create a new XMesaBuffer from an X window.
1714 * Input:  v - the XMesaVisual
1715 *         w - the window
1716 *         c - the context
1717 * Return:  new XMesaBuffer or NULL if error
1718 */
1719XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w,
1720                                      XMesaContext c )
1721{
1722#ifndef XFree86Server
1723   XWindowAttributes attr;
1724#endif
1725#ifdef FX
1726   char *fxEnvVar;
1727#endif
1728   int client = 0;
1729
1730   XMesaBuffer b = alloc_xmesa_buffer();
1731   if (!b) {
1732      return NULL;
1733   }
1734
1735   (void) c;
1736
1737#ifdef XFree86Server
1738   client = CLIENT_ID(((XMesaDrawable)w)->id);
1739#endif
1740
1741   assert(v);
1742
1743#ifdef XFree86Server
1744   if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
1745#else
1746   XGetWindowAttributes( v->display, w, &attr );
1747
1748   if (GET_VISUAL_DEPTH(v) != attr.depth) {
1749#endif
1750      if (getenv("MESA_DEBUG")) {
1751         fprintf(stderr, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n");
1752      }
1753      return NULL;
1754   }
1755
1756   b->xm_context = NULL; /* Associate no context with this buffer */
1757
1758   b->xm_visual = v;
1759   b->pixmap_flag = GL_FALSE;
1760   b->display = v->display;
1761#ifdef XFree86Server
1762   b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1763#else
1764   if (attr.colormap) {
1765      b->cmap = attr.colormap;
1766   }
1767   else {
1768      if (getenv("MESA_DEBUG")) {
1769         fprintf(stderr, "Window %u has no colormap!\n", (unsigned int) w);
1770      }
1771      /* this is weird, a window w/out a colormap!? */
1772      /* OK, let's just allocate a new one and hope for the best */
1773      b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1774   }
1775#endif
1776
1777   /* determine back buffer implementation */
1778   if (v->gl_visual->DBflag) {
1779      if (v->ximage_flag) {
1780	 b->db_state = BACK_XIMAGE;
1781      }
1782      else {
1783	 b->db_state = BACK_PIXMAP;
1784      }
1785   }
1786   else {
1787      b->db_state = 0;
1788   }
1789
1790   b->gl_buffer = _mesa_create_framebuffer( v->gl_visual,
1791                                            v->gl_visual->DepthBits > 0,
1792                                            v->gl_visual->StencilBits > 0,
1793                                            v->gl_visual->AccumRedBits > 0,
1794                                            v->gl_visual->AlphaBits > 0 );
1795   if (!b->gl_buffer) {
1796      free_xmesa_buffer(client, b);
1797      return NULL;
1798   }
1799
1800   if (!initialize_visual_and_buffer( client, v, b, v->gl_visual->RGBAflag,
1801                                      (XMesaDrawable)w, b->cmap )) {
1802      _mesa_destroy_framebuffer( b->gl_buffer );
1803      free_xmesa_buffer(client, b);
1804      return NULL;
1805   }
1806
1807#ifdef FX
1808   fxEnvVar = getenv("MESA_GLX_FX");
1809   if (fxEnvVar) {
1810     if (fxEnvVar[0]!='d') {
1811       int attribs[100];
1812       int numAttribs = 0;
1813       int hw;
1814       if (v->gl_visual->DepthBits > 0) {
1815	 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
1816	 attribs[numAttribs++] = 1;
1817       }
1818       if (v->gl_visual->DBflag) {
1819	 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
1820       }
1821       if (v->gl_visual->AccumRedBits > 0) {
1822	 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
1823	 attribs[numAttribs++] = v->gl_visual->AccumRedBits;
1824       }
1825       if (v->gl_visual->StencilBits > 0) {
1826         attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
1827         attribs[numAttribs++] = v->gl_visual->StencilBits;
1828       }
1829       if (v->gl_visual->AlphaBits > 0) {
1830         attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
1831         attribs[numAttribs++] = 1;
1832       }
1833       if (c->gl_ctx) {
1834#define FXMESA_SHARE_CONTEXT 990099  /* keep in sync with fxapi.c! */
1835         attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
1836         attribs[numAttribs++] = (int) c->gl_ctx;
1837       }
1838       attribs[numAttribs++] = FXMESA_NONE;
1839
1840       if ((hw = fxQueryHardware())==GR_SSTTYPE_VOODOO) {
1841         b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
1842         if ((v->undithered_pf!=PF_INDEX) && (b->backimage)) {
1843	   b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
1844	   if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1845	     b->FXwindowHack = b->FXctx ? GL_TRUE : GL_FALSE;
1846	   else
1847	     b->FXwindowHack = GL_FALSE;
1848         }
1849       }
1850       else {
1851         if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1852	   b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
1853					  GR_REFRESH_75Hz, attribs);
1854         else
1855	   b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
1856         b->FXisHackUsable = GL_FALSE;
1857         b->FXwindowHack = GL_FALSE;
1858       }
1859       /*
1860       fprintf(stderr,
1861               "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1862               hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
1863       */
1864     }
1865   }
1866   else {
1867      fprintf(stderr,"WARNING: This Mesa Library includes the Glide driver but\n");
1868      fprintf(stderr,"         you have not defined the MESA_GLX_FX env. var.\n");
1869      fprintf(stderr,"         (check the README.3DFX file for more information).\n\n");
1870      fprintf(stderr,"         you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1871   }
1872#endif
1873
1874#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1875   b->driDrawPriv = driDrawPriv;
1876#endif
1877
1878   return b;
1879}
1880
1881
1882XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w )
1883{
1884   return XMesaCreateWindowBuffer2( v, w, NULL );
1885}
1886
1887
1888/*
1889 * Create a new XMesaBuffer from an X pixmap.
1890 * Input:  v - the XMesaVisual
1891 *         p - the pixmap
1892 *         cmap - the colormap, may be 0 if using a TrueColor or DirectColor
1893 *                visual for the pixmap
1894 * Return:  new XMesaBuffer or NULL if error
1895 */
1896XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v,
1897				     XMesaPixmap p, XMesaColormap cmap )
1898{
1899   int client = 0;
1900   XMesaBuffer b = alloc_xmesa_buffer();
1901   if (!b) {
1902      return NULL;
1903   }
1904
1905
1906#ifdef XFree86Server
1907   client = CLIENT_ID(((XMesaDrawable)p)->id);
1908#endif
1909
1910   assert(v);
1911
1912   b->xm_context = NULL; /* Associate no context with this buffer */
1913
1914   b->xm_visual = v;
1915   b->pixmap_flag = GL_TRUE;
1916   b->display = v->display;
1917   b->cmap = cmap;
1918
1919   /* determine back buffer implementation */
1920   if (v->gl_visual->DBflag) {
1921      if (v->ximage_flag) {
1922	 b->db_state = BACK_XIMAGE;
1923      }
1924      else {
1925	 b->db_state = BACK_PIXMAP;
1926      }
1927   }
1928   else {
1929      b->db_state = 0;
1930   }
1931
1932   b->gl_buffer = _mesa_create_framebuffer( v->gl_visual,
1933                                            v->gl_visual->DepthBits > 0,
1934                                            v->gl_visual->StencilBits > 0,
1935                                            v->gl_visual->AccumRedBits +
1936                                            v->gl_visual->AccumGreenBits +
1937                                            v->gl_visual->AccumBlueBits > 0,
1938                                            v->gl_visual->AlphaBits > 0 );
1939   if (!b->gl_buffer) {
1940      free_xmesa_buffer(client, b);
1941      return NULL;
1942   }
1943
1944   if (!initialize_visual_and_buffer(client, v, b, v->gl_visual->RGBAflag,
1945				     (XMesaDrawable)p, cmap)) {
1946      _mesa_destroy_framebuffer( b->gl_buffer );
1947      free_xmesa_buffer(client, b);
1948      return NULL;
1949   }
1950
1951#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1952   b->driDrawPriv = driDrawPriv;
1953#endif
1954
1955   return b;
1956}
1957
1958
1959
1960/*
1961 * Deallocate an XMesaBuffer structure and all related info.
1962 */
1963void XMesaDestroyBuffer( XMesaBuffer b )
1964{
1965   int client = 0;
1966
1967#ifdef XFree86Server
1968   if (b->frontbuffer)
1969       client = CLIENT_ID(b->frontbuffer->id);
1970#endif
1971
1972   if (b->gc1)  XMesaFreeGC( b->xm_visual->display, b->gc1 );
1973   if (b->gc2)  XMesaFreeGC( b->xm_visual->display, b->gc2 );
1974   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
1975
1976   if (b->backimage) {
1977#if defined(USE_XSHM) && !defined(XFree86Server)
1978       if (b->shm) {
1979	   XShmDetach( b->xm_visual->display, &b->shminfo );
1980	   XDestroyImage( b->backimage );
1981	   shmdt( b->shminfo.shmaddr );
1982       }
1983       else
1984#endif
1985	   XMesaDestroyImage( b->backimage );
1986   }
1987   if (b->backpixmap) {
1988      XMesaFreePixmap( b->xm_visual->display, b->backpixmap );
1989      if (b->xm_visual->hpcr_clear_flag) {
1990	XMesaFreePixmap( b->xm_visual->display,
1991			 b->xm_visual->hpcr_clear_pixmap );
1992	XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
1993      }
1994   }
1995   if (b->rowimage) {
1996      FREE( b->rowimage->data );
1997      b->rowimage->data = NULL;
1998      XMesaDestroyImage( b->rowimage );
1999   }
2000
2001   if (b->xm_context)
2002       b->xm_context->xm_buffer = NULL;
2003
2004   _mesa_destroy_framebuffer( b->gl_buffer );
2005   free_xmesa_buffer(client, b);
2006}
2007
2008
2009
2010/*
2011 * Bind buffer b to context c and make c the current rendering context.
2012 */
2013GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
2014{
2015   return XMesaMakeCurrent2( c, b, b );
2016}
2017
2018
2019/*
2020 * Bind buffer b to context c and make c the current rendering context.
2021 */
2022GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
2023                             XMesaBuffer readBuffer )
2024{
2025   if (c) {
2026      if (!drawBuffer || !readBuffer)
2027         return GL_FALSE;  /* must specify buffers! */
2028
2029#ifdef FX
2030      if (drawBuffer->FXctx) {
2031         fxMesaMakeCurrent(drawBuffer->FXctx);
2032
2033         /* Disassociate old buffer from this context */
2034         if (c->xm_buffer)
2035            c->xm_buffer->xm_context = NULL;
2036
2037         /* Associate the context with this buffer */
2038         drawBuffer->xm_context = c;
2039
2040         c->xm_buffer = drawBuffer;
2041         c->xm_read_buffer = readBuffer;
2042         c->use_read_buffer = (drawBuffer != readBuffer);
2043
2044         return GL_TRUE;
2045      }
2046#endif
2047      if (c->gl_ctx == _mesa_get_current_context()
2048          && c->xm_buffer == drawBuffer
2049          && c->xm_read_buffer == readBuffer
2050          && c->xm_buffer->wasCurrent) {
2051         /* same context and buffer, do nothing */
2052         return GL_TRUE;
2053      }
2054
2055      /* Disassociate old buffer with this context */
2056      if (c->xm_buffer)
2057	  c->xm_buffer->xm_context = NULL;
2058      drawBuffer->xm_context = c; /* Associate the context with this buffer */
2059
2060      c->xm_buffer = drawBuffer;
2061      c->xm_read_buffer = readBuffer;
2062      c->use_read_buffer = (drawBuffer != readBuffer);
2063
2064      _mesa_make_current2(c->gl_ctx, drawBuffer->gl_buffer, readBuffer->gl_buffer);
2065
2066      if (c->gl_ctx->Viewport.Width == 0) {
2067	 /* initialize viewport to window size */
2068	 _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height );
2069	 c->gl_ctx->Scissor.Width = drawBuffer->width;
2070	 c->gl_ctx->Scissor.Height = drawBuffer->height;
2071      }
2072
2073      if (c->xm_visual->gl_visual->RGBAflag) {
2074         /*
2075          * Must recompute and set these pixel values because colormap
2076          * can be different for different windows.
2077          */
2078         c->pixel = xmesa_color_to_pixel( c, c->red, c->green,
2079                                          c->blue, c->alpha, c->pixelformat );
2080         XMesaSetForeground( c->display, c->xm_buffer->gc1, c->pixel );
2081         c->clearpixel = xmesa_color_to_pixel( c,
2082                                               c->clearcolor[0],
2083                                               c->clearcolor[1],
2084                                               c->clearcolor[2],
2085                                               c->clearcolor[3],
2086                                               c->xm_visual->undithered_pf);
2087         XMesaSetForeground(c->display, c->xm_buffer->cleargc, c->clearpixel);
2088      }
2089
2090      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2091      c->xm_buffer->wasCurrent = GL_TRUE;
2092   }
2093   else {
2094      /* Detach */
2095      _mesa_make_current2( NULL, NULL, NULL );
2096   }
2097   return GL_TRUE;
2098}
2099
2100
2101/*
2102 * Unbind the context c from its buffer.
2103 */
2104GLboolean XMesaUnbindContext( XMesaContext c )
2105{
2106   /* A no-op for XFree86 integration purposes */
2107   return GL_TRUE;
2108}
2109
2110
2111XMesaContext XMesaGetCurrentContext( void )
2112{
2113   GET_CURRENT_CONTEXT(ctx);
2114   if (ctx) {
2115      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2116      return xmesa;
2117   }
2118   else {
2119      return 0;
2120   }
2121}
2122
2123
2124XMesaBuffer XMesaGetCurrentBuffer( void )
2125{
2126   GET_CURRENT_CONTEXT(ctx);
2127   if (ctx) {
2128      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2129      return xmesa->xm_buffer;
2130   }
2131   else {
2132      return 0;
2133   }
2134}
2135
2136
2137/* New in Mesa 3.1 */
2138XMesaBuffer XMesaGetCurrentReadBuffer( void )
2139{
2140   GET_CURRENT_CONTEXT(ctx);
2141   if (ctx) {
2142      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2143      return xmesa->xm_buffer;
2144   }
2145   else {
2146      return 0;
2147   }
2148}
2149
2150
2151GLboolean XMesaForceCurrent(XMesaContext c)
2152{
2153   if (c) {
2154      if (c->gl_ctx != _mesa_get_current_context()) {
2155	 _mesa_make_current(c->gl_ctx, c->xm_buffer->gl_buffer);
2156      }
2157   }
2158   else {
2159      _mesa_make_current(NULL, NULL);
2160   }
2161   return GL_TRUE;
2162}
2163
2164
2165GLboolean XMesaLoseCurrent(XMesaContext c)
2166{
2167   (void) c;
2168   _mesa_make_current(NULL, NULL);
2169   return GL_TRUE;
2170}
2171
2172
2173/*
2174 * Switch 3Dfx support hack between window and full-screen mode.
2175 */
2176GLboolean XMesaSetFXmode( GLint mode )
2177{
2178#ifdef FX
2179   const char *fx = getenv("MESA_GLX_FX");
2180   if (fx && fx[0] != 'd') {
2181      GET_CURRENT_CONTEXT(ctx);
2182      GrHwConfiguration hw;
2183      if (!FX_grSstQueryHardware(&hw)) {
2184         /*fprintf(stderr, "!grSstQueryHardware\n");*/
2185         return GL_FALSE;
2186      }
2187      if (hw.num_sst < 1) {
2188         /*fprintf(stderr, "hw.num_sst < 1\n");*/
2189         return GL_FALSE;
2190      }
2191      if (ctx) {
2192         XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2193         if (mode == XMESA_FX_WINDOW) {
2194	    if (xmesa->xm_buffer->FXisHackUsable) {
2195	       FX_grSstControl(GR_CONTROL_DEACTIVATE);
2196	       xmesa->xm_buffer->FXwindowHack = GL_TRUE;
2197	       return GL_TRUE;
2198	    }
2199	 }
2200	 else if (mode == XMESA_FX_FULLSCREEN) {
2201	    FX_grSstControl(GR_CONTROL_ACTIVATE);
2202	    xmesa->xm_buffer->FXwindowHack = GL_FALSE;
2203	    return GL_TRUE;
2204	 }
2205	 else {
2206	    /* Error: Bad mode value */
2207	 }
2208      }
2209   }
2210   /*fprintf(stderr, "fallthrough\n");*/
2211#else
2212   (void) mode;
2213#endif
2214   return GL_FALSE;
2215}
2216
2217
2218
2219#ifdef FX
2220/*
2221 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2222 */
2223static void FXgetImage( XMesaBuffer b )
2224{
2225   static unsigned short pixbuf[MAX_WIDTH];
2226   int x, y;
2227   XMesaWindow root;
2228   unsigned int bw, depth, width, height;
2229   XMesaContext xmesa = (XMesaContext) b->xm_context->gl_ctx->DriverCtx;
2230
2231   assert(xmesa->xm_buffer->FXctx);
2232
2233#ifdef XFree86Server
2234   x = b->frontbuffer->x;
2235   y = b->frontbuffer->y;
2236   width = b->frontbuffer->width;
2237   height = b->frontbuffer->height;
2238   depth = b->frontbuffer->depth;
2239#else
2240   XGetGeometry( xmesa->xm_visual->display, b->frontbuffer,
2241                 &root, &x, &y, &width, &height, &bw, &depth);
2242#endif
2243   if (b->width != width || b->height != height) {
2244      b->width = MIN2((int)width, xmesa->xm_buffer->FXctx->width);
2245      b->height = MIN2((int)height, xmesa->xm_buffer->FXctx->height);
2246      if (b->width & 1)
2247         b->width--;  /* prevent odd width */
2248      xmesa_alloc_back_buffer( b );
2249   }
2250
2251   grLfbWriteColorFormat(GR_COLORFORMAT_ARGB);
2252   if (xmesa->xm_visual->undithered_pf==PF_5R6G5B) {
2253      /* Special case: 16bpp RGB */
2254      grLfbReadRegion( GR_BUFFER_FRONTBUFFER,       /* src buffer */
2255                       0, xmesa->xm_buffer->FXctx->height - b->height,  /*pos*/
2256                       b->width, b->height,         /* size */
2257                       b->width * sizeof(GLushort), /* stride */
2258                       b->backimage->data);         /* dest buffer */
2259   }
2260   else if (xmesa->xm_visual->dithered_pf==PF_DITHER
2261	    && GET_VISUAL_DEPTH(xmesa->xm_visual)==8) {
2262      /* Special case: 8bpp RGB */
2263      for (y=0;y<b->height;y++) {
2264         GLubyte *ptr = (GLubyte*) xmesa->xm_buffer->backimage->data
2265                        + xmesa->xm_buffer->backimage->bytes_per_line * y;
2266         XDITHER_SETUP(y);
2267
2268         /* read row from 3Dfx frame buffer */
2269         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2270                          0, xmesa->xm_buffer->FXctx->height-(b->height-y),
2271                          b->width, 1,
2272                          0,
2273                          pixbuf );
2274
2275         /* write to XImage back buffer */
2276         for (x=0;x<b->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->height;y++) {
2287         /* read row from 3Dfx frame buffer */
2288         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2289                          0, xmesa->xm_buffer->FXctx->height-(b->height-y),
2290                          b->width, 1,
2291                          0,
2292                          pixbuf );
2293
2294         /* write to XImage back buffer */
2295         for (x=0;x<b->width;x++) {
2296            XMesaPutPixel(b->backimage,x,y,
2297			  xmesa_color_to_pixel(xmesa,
2298					       (pixbuf[x] & 0xf800) >> 8,
2299					       (pixbuf[x] & 0x07e0) >> 3,
2300					       (pixbuf[x] & 0x001f) << 3,
2301					       0xff, xmesa->pixelformat));
2302         }
2303      }
2304   }
2305   grLfbWriteColorFormat(GR_COLORFORMAT_ABGR);
2306}
2307#endif
2308
2309
2310/*
2311 * Copy the back buffer to the front buffer.  If there's no back buffer
2312 * this is a no-op.
2313 */
2314void XMesaSwapBuffers( XMesaBuffer b )
2315{
2316   GET_CURRENT_CONTEXT(ctx);
2317
2318   /* If we're swapping the buffer associated with the current context
2319    * we have to flush any pending rendering commands first.
2320    */
2321   if (b->xm_context && b->xm_context->gl_ctx == ctx)
2322      _mesa_swapbuffers(ctx);
2323
2324   if (b->db_state) {
2325#ifdef FX
2326      if (b->FXctx) {
2327         fxMesaSwapBuffers();
2328
2329         if (b->FXwindowHack)
2330            FXgetImage(b);
2331         else
2332            return;
2333      }
2334#endif
2335     if (b->backimage) {
2336	 /* Copy Ximage from host's memory to server's window */
2337#if defined(USE_XSHM) && !defined(XFree86Server)
2338	 if (b->shm) {
2339            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2340	    XShmPutImage( b->xm_visual->display, b->frontbuffer,
2341			  b->cleargc,
2342			  b->backimage, 0, 0,
2343			  0, 0, b->width, b->height, False );
2344            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2345	 }
2346	 else
2347#endif
2348         {
2349#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
2350	    XMesaDriSwapBuffers( b );
2351#else
2352            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2353            XMesaPutImage( b->xm_visual->display, b->frontbuffer,
2354			   b->cleargc,
2355			   b->backimage, 0, 0,
2356			   0, 0, b->width, b->height );
2357            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2358#endif
2359         }
2360      }
2361      else {
2362	 /* Copy pixmap to window on server */
2363         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2364	 XMesaCopyArea( b->xm_visual->display,
2365			b->backpixmap,   /* source drawable */
2366			b->frontbuffer,  /* dest. drawable */
2367			b->cleargc,
2368			0, 0, b->width, b->height,  /* source region */
2369			0, 0                 /* dest region */
2370		      );
2371         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2372      }
2373   }
2374#if !defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
2375   XSync( b->xm_visual->display, False );
2376#endif
2377}
2378
2379
2380
2381/*
2382 * Copy sub-region of back buffer to front buffer
2383 */
2384void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2385{
2386   GET_CURRENT_CONTEXT(ctx);
2387
2388   /* If we're swapping the buffer associated with the current context
2389    * we have to flush any pending rendering commands first.
2390    */
2391   if (b->xm_context->gl_ctx == ctx)
2392      _mesa_swapbuffers(ctx);
2393
2394   if (b->db_state) {
2395      int yTop = b->bottom - y - height;
2396#ifdef FX
2397      if (b->FXctx) {
2398         fxMesaSwapBuffers();
2399         if (b->FXwindowHack)
2400            FXgetImage(b);
2401         else
2402            return;
2403      }
2404#endif
2405      if (b->backimage) {
2406         /* Copy Ximage from host's memory to server's window */
2407#if defined(USE_XSHM) && !defined(XFree86Server)
2408         if (b->shm) {
2409            /* XXX assuming width and height aren't too large! */
2410            XShmPutImage( b->xm_visual->display, b->frontbuffer,
2411                          b->cleargc,
2412                          b->backimage, x, yTop,
2413                          x, yTop, width, height, False );
2414            /* wait for finished event??? */
2415         }
2416         else
2417#endif
2418         {
2419            /* XXX assuming width and height aren't too large! */
2420            XMesaPutImage( b->xm_visual->display, b->frontbuffer,
2421			   b->cleargc,
2422			   b->backimage, x, yTop,
2423			   x, yTop, width, height );
2424         }
2425      }
2426      else {
2427         /* Copy pixmap to window on server */
2428         XMesaCopyArea( b->xm_visual->display,
2429			b->backpixmap,           /* source drawable */
2430			b->frontbuffer,          /* dest. drawable */
2431			b->cleargc,
2432			x, yTop, width, height,  /* source region */
2433			x, yTop                  /* dest region */
2434                      );
2435      }
2436   }
2437}
2438
2439
2440/*
2441 * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
2442 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2443 * back buffer directly.
2444 * Output:  pixmap - pointer to back buffer's Pixmap, or 0
2445 *          ximage - pointer to back buffer's XImage, or NULL
2446 * Return:  GL_TRUE = context is double buffered
2447 *          GL_FALSE = context is single buffered
2448 */
2449GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2450                              XMesaPixmap *pixmap,
2451                              XMesaImage **ximage )
2452{
2453   if (b->db_state) {
2454      if (pixmap)  *pixmap = b->backpixmap;
2455      if (ximage)  *ximage = b->backimage;
2456      return GL_TRUE;
2457   }
2458   else {
2459      *pixmap = 0;
2460      *ximage = NULL;
2461      return GL_FALSE;
2462   }
2463}
2464
2465
2466/*
2467 * Return the depth buffer associated with an XMesaBuffer.
2468 * Input:  b - the XMesa buffer handle
2469 * Output:  width, height - size of buffer in pixels
2470 *          bytesPerValue - bytes per depth value (2 or 4)
2471 *          buffer - pointer to depth buffer values
2472 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
2473 */
2474GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2475                               GLint *bytesPerValue, void **buffer )
2476{
2477   if ((!b->gl_buffer) || (!b->gl_buffer->DepthBuffer)) {
2478      *width = 0;
2479      *height = 0;
2480      *bytesPerValue = 0;
2481      *buffer = 0;
2482      return GL_FALSE;
2483   }
2484   else {
2485      *width = b->gl_buffer->Width;
2486      *height = b->gl_buffer->Height;
2487      *bytesPerValue = sizeof(GLdepth);
2488      *buffer = b->gl_buffer->DepthBuffer;
2489      return GL_TRUE;
2490   }
2491}
2492
2493
2494void XMesaFlush( XMesaContext c )
2495{
2496   if (c && c->xm_visual) {
2497#ifdef XFree86Server
2498      /* NOT_NEEDED */
2499#else
2500      XSync( c->xm_visual->display, False );
2501#endif
2502   }
2503}
2504
2505
2506
2507const char *XMesaGetString( XMesaContext c, int name )
2508{
2509   (void) c;
2510   if (name==XMESA_VERSION) {
2511      return "3.1";
2512   }
2513   else if (name==XMESA_EXTENSIONS) {
2514      return "";
2515   }
2516   else {
2517      return NULL;
2518   }
2519}
2520
2521
2522
2523XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2524{
2525   XMesaBuffer b;
2526   for (b=XMesaBufferList; b; b=b->Next) {
2527      if (b->frontbuffer==d && b->display==dpy) {
2528         return b;
2529      }
2530   }
2531   return NULL;
2532}
2533
2534
2535
2536/*
2537 * Look for XMesaBuffers whose X window has been destroyed.
2538 * Deallocate any such XMesaBuffers.
2539 */
2540void XMesaGarbageCollect( void )
2541{
2542   XMesaBuffer b, next;
2543   for (b=XMesaBufferList; b; b=next) {
2544      next = b->Next;
2545      if (!b->pixmap_flag) {
2546#ifdef XFree86Server
2547	 /* NOT_NEEDED */
2548#else
2549         XSync(b->display, False);
2550         if (!window_exists( b->display, b->frontbuffer )) {
2551            /* found a dead window, free the ancillary info */
2552            XMesaDestroyBuffer( b );
2553         }
2554#endif
2555      }
2556   }
2557}
2558
2559
2560void XMesaReset( void )
2561{
2562    while (XMesaBufferList)
2563	XMesaDestroyBuffer(XMesaBufferList);
2564
2565    XMesaBufferList = NULL;
2566}
2567
2568
2569unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2570                                GLfloat red, GLfloat green,
2571                                GLfloat blue, GLfloat alpha )
2572{
2573   GLint r = (GLint) (red   * 255.0F);
2574   GLint g = (GLint) (green * 255.0F);
2575   GLint b = (GLint) (blue  * 255.0F);
2576   GLint a = (GLint) (alpha * 255.0F);
2577
2578   switch (xmesa->pixelformat) {
2579      case PF_INDEX:
2580         return 0;
2581      case PF_TRUECOLOR:
2582         {
2583            unsigned long p;
2584            PACK_TRUECOLOR( p, r, g, b );
2585            return p;
2586         }
2587      case PF_8A8B8G8R:
2588         return PACK_8A8B8G8R( r, g, b, a );
2589      case PF_8R8G8B:
2590         return PACK_8R8G8B( r, g, b );
2591      case PF_5R6G5B:
2592         return PACK_5R6G5B( r, g, b );
2593      case PF_DITHER:
2594         {
2595            DITHER_SETUP;
2596            return DITHER( x, y, r, g, b );
2597         }
2598      case PF_1BIT:
2599         /* 382 = (3*255)/2 */
2600         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2601      case PF_HPCR:
2602         return DITHER_HPCR(x, y, r, g, b);
2603      case PF_LOOKUP:
2604         {
2605            LOOKUP_SETUP;
2606            return LOOKUP( r, g, b );
2607         }
2608      case PF_GRAYSCALE:
2609         return GRAY_RGB( r, g, b );
2610      case PF_DITHER_5R6G5B:
2611         /* fall through */
2612      case PF_TRUEDITHER:
2613         {
2614            unsigned long p;
2615            PACK_TRUEDITHER(p, x, y, r, g, b);
2616            return p;
2617         }
2618      default:
2619         gl_problem(NULL, "Bad pixel format in XMesaDitherColor");
2620   }
2621   return 0;
2622}
2623
2624
2625