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