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