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