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