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