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