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