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