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