xm_api.c revision 18a285a5e244b7405b85feb7315a30d99920ec5d
1/* $Id: xm_api.c,v 1.35 2002/03/16 00:53:15 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  4.0.2
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   FREE( c );
1704}
1705
1706
1707
1708/*
1709 * XXX this isn't a public function!  It's a hack for the 3Dfx driver.
1710 * Create a new XMesaBuffer from an X window.
1711 * Input:  v - the XMesaVisual
1712 *         w - the window
1713 *         c - the context
1714 * Return:  new XMesaBuffer or NULL if error
1715 */
1716XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w,
1717                                      XMesaContext c )
1718{
1719#ifndef XFree86Server
1720   XWindowAttributes attr;
1721#endif
1722#ifdef FX
1723   char *fxEnvVar;
1724#endif
1725   int client = 0;
1726
1727   XMesaBuffer b = alloc_xmesa_buffer();
1728   if (!b) {
1729      return NULL;
1730   }
1731
1732   (void) c;
1733
1734#ifdef XFree86Server
1735   client = CLIENT_ID(((XMesaDrawable)w)->id);
1736#endif
1737
1738   assert(v);
1739
1740#ifdef XFree86Server
1741   if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
1742#else
1743   XGetWindowAttributes( v->display, w, &attr );
1744
1745   if (GET_VISUAL_DEPTH(v) != attr.depth) {
1746#endif
1747      if (getenv("MESA_DEBUG")) {
1748         fprintf(stderr, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n");
1749      }
1750      return NULL;
1751   }
1752
1753   b->xm_visual = v;
1754   b->pixmap_flag = GL_FALSE;
1755   b->display = v->display;
1756#ifdef XFree86Server
1757   b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1758#else
1759   if (attr.colormap) {
1760      b->cmap = attr.colormap;
1761   }
1762   else {
1763      if (getenv("MESA_DEBUG")) {
1764         fprintf(stderr, "Window %u has no colormap!\n", (unsigned int) w);
1765      }
1766      /* this is weird, a window w/out a colormap!? */
1767      /* OK, let's just allocate a new one and hope for the best */
1768      b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1769   }
1770#endif
1771
1772   /* determine back buffer implementation */
1773   if (v->mesa_visual.doubleBufferMode) {
1774      if (v->ximage_flag) {
1775	 b->db_state = BACK_XIMAGE;
1776      }
1777      else {
1778	 b->db_state = BACK_PIXMAP;
1779      }
1780   }
1781   else {
1782      b->db_state = 0;
1783   }
1784
1785   _mesa_initialize_framebuffer(&b->mesa_buffer,
1786                                &v->mesa_visual,
1787                                v->mesa_visual.depthBits > 0,
1788                                v->mesa_visual.stencilBits > 0,
1789                                v->mesa_visual.accumRedBits > 0,
1790                                v->mesa_visual.alphaBits > 0 );
1791
1792   if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
1793                                      (XMesaDrawable)w, b->cmap )) {
1794      free_xmesa_buffer(client, b);
1795      return NULL;
1796   }
1797
1798#ifdef FX
1799   fxEnvVar = getenv("MESA_GLX_FX");
1800   if (fxEnvVar) {
1801     if (fxEnvVar[0]!='d') {
1802       int attribs[100];
1803       int numAttribs = 0;
1804       int hw;
1805       if (v->mesa_visual.depthBits > 0) {
1806	 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
1807	 attribs[numAttribs++] = 1;
1808       }
1809       if (v->mesa_visual.doubleBufferMode) {
1810	 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
1811       }
1812       if (v->mesa_visual.accumRedBits > 0) {
1813	 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
1814	 attribs[numAttribs++] = v->mesa_visual.accumRedBits;
1815       }
1816       if (v->mesa_visual.stencilBits > 0) {
1817         attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
1818         attribs[numAttribs++] = v->mesa_visual.stencilBits;
1819       }
1820       if (v->mesa_visual.alphaBits > 0) {
1821         attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
1822         attribs[numAttribs++] = 1;
1823       }
1824       if (c->gl_ctx) {
1825#define FXMESA_SHARE_CONTEXT 990099  /* keep in sync with fxapi.c! */
1826         attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
1827         attribs[numAttribs++] = (int) c->gl_ctx;
1828       }
1829       attribs[numAttribs++] = FXMESA_NONE;
1830
1831       if ((hw = fxQueryHardware())==GR_SSTTYPE_VOODOO) {
1832         b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
1833         if ((v->undithered_pf!=PF_INDEX) && (b->backimage)) {
1834	   b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
1835	   if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1836	     b->FXwindowHack = b->FXctx ? GL_TRUE : GL_FALSE;
1837	   else
1838	     b->FXwindowHack = GL_FALSE;
1839         }
1840       }
1841       else {
1842         if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1843	   b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
1844					  GR_REFRESH_75Hz, attribs);
1845         else
1846	   b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
1847         b->FXisHackUsable = GL_FALSE;
1848         b->FXwindowHack = GL_FALSE;
1849       }
1850       /*
1851       fprintf(stderr,
1852               "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1853               hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
1854       */
1855     }
1856   }
1857   else {
1858      fprintf(stderr,"WARNING: This Mesa Library includes the Glide driver but\n");
1859      fprintf(stderr,"         you have not defined the MESA_GLX_FX env. var.\n");
1860      fprintf(stderr,"         (check the README.3DFX file for more information).\n\n");
1861      fprintf(stderr,"         you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1862   }
1863#endif
1864
1865   return b;
1866}
1867
1868
1869XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w )
1870{
1871   return XMesaCreateWindowBuffer2( v, w, NULL );
1872}
1873
1874
1875/*
1876 * Create a new XMesaBuffer from an X pixmap.
1877 * Input:  v - the XMesaVisual
1878 *         p - the pixmap
1879 *         cmap - the colormap, may be 0 if using a TrueColor or DirectColor
1880 *                visual for the pixmap
1881 * Return:  new XMesaBuffer or NULL if error
1882 */
1883XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v,
1884				     XMesaPixmap p, XMesaColormap cmap )
1885{
1886   int client = 0;
1887   XMesaBuffer b = alloc_xmesa_buffer();
1888   if (!b) {
1889      return NULL;
1890   }
1891
1892
1893#ifdef XFree86Server
1894   client = CLIENT_ID(((XMesaDrawable)p)->id);
1895#endif
1896
1897   assert(v);
1898
1899   b->xm_visual = v;
1900   b->pixmap_flag = GL_TRUE;
1901   b->display = v->display;
1902   b->cmap = cmap;
1903
1904   /* determine back buffer implementation */
1905   if (v->mesa_visual.doubleBufferMode) {
1906      if (v->ximage_flag) {
1907	 b->db_state = BACK_XIMAGE;
1908      }
1909      else {
1910	 b->db_state = BACK_PIXMAP;
1911      }
1912   }
1913   else {
1914      b->db_state = 0;
1915   }
1916
1917   _mesa_initialize_framebuffer(&b->mesa_buffer,
1918                                &v->mesa_visual,
1919                                v->mesa_visual.depthBits > 0,
1920                                v->mesa_visual.stencilBits > 0,
1921                                v->mesa_visual.accumRedBits +
1922                                v->mesa_visual.accumGreenBits +
1923                                v->mesa_visual.accumBlueBits > 0,
1924                                v->mesa_visual.alphaBits > 0 );
1925
1926   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1927				     (XMesaDrawable)p, cmap)) {
1928      free_xmesa_buffer(client, b);
1929      return NULL;
1930   }
1931
1932   return b;
1933}
1934
1935
1936
1937#if 0 /* not done */
1938XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap,
1939                                unsigned int width, unsigned int height )
1940{
1941   int client = 0;
1942   XMesaBuffer b = alloc_xmesa_buffer();
1943   if (!b) {
1944      return NULL;
1945   }
1946
1947   b->xm_visual = v;
1948   b->pbuffer_flag = GL_TRUE;
1949   b->display = v->display;
1950   b->cmap = cmap;
1951
1952   /* determine back buffer implementation */
1953   if (v->mesa_visual.doubleBufferMode) {
1954      if (v->ximage_flag) {
1955	 b->db_state = BACK_XIMAGE;
1956      }
1957      else {
1958	 b->db_state = BACK_PIXMAP;
1959      }
1960   }
1961   else {
1962      b->db_state = 0;
1963   }
1964
1965   _mesa_initialize_framebuffer(&b->mesa_buffer,
1966                                &v->mesa_visual,
1967                                v->mesa_visual.depthBits > 0,
1968                                v->mesa_visual.stencilBits > 0,
1969                                v->mesa_visual.accumRedBits +
1970                                v->mesa_visual.accumGreenBits +
1971                                v->mesa_visual.accumBlueBits > 0,
1972                                v->mesa_visual.alphaBits > 0 );
1973
1974   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1975				     0, cmap)) {
1976      free_xmesa_buffer(client, b);
1977      return NULL;
1978   }
1979
1980   return b;
1981}
1982#endif
1983
1984
1985
1986/*
1987 * Deallocate an XMesaBuffer structure and all related info.
1988 */
1989void XMesaDestroyBuffer( XMesaBuffer b )
1990{
1991   int client = 0;
1992
1993#ifdef XFree86Server
1994   if (b->frontbuffer)
1995       client = CLIENT_ID(b->frontbuffer->id);
1996#endif
1997
1998   if (b->gc)  XMesaFreeGC( b->xm_visual->display, b->gc );
1999   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
2000   if (b->swapgc)  XMesaFreeGC( b->xm_visual->display, b->swapgc );
2001
2002   if (b->backimage) {
2003#if defined(USE_XSHM) && !defined(XFree86Server)
2004       if (b->shm) {
2005	   XShmDetach( b->xm_visual->display, &b->shminfo );
2006	   XDestroyImage( b->backimage );
2007	   shmdt( b->shminfo.shmaddr );
2008       }
2009       else
2010#endif
2011	   XMesaDestroyImage( b->backimage );
2012   }
2013   if (b->backpixmap) {
2014      XMesaFreePixmap( b->xm_visual->display, b->backpixmap );
2015      if (b->xm_visual->hpcr_clear_flag) {
2016	XMesaFreePixmap( b->xm_visual->display,
2017			 b->xm_visual->hpcr_clear_pixmap );
2018	XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
2019      }
2020   }
2021   if (b->rowimage) {
2022      FREE( b->rowimage->data );
2023      b->rowimage->data = NULL;
2024      XMesaDestroyImage( b->rowimage );
2025   }
2026
2027   free_xmesa_buffer(client, b);
2028}
2029
2030
2031
2032/*
2033 * Bind buffer b to context c and make c the current rendering context.
2034 */
2035GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
2036{
2037   return XMesaMakeCurrent2( c, b, b );
2038}
2039
2040
2041/*
2042 * Bind buffer b to context c and make c the current rendering context.
2043 */
2044GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
2045                             XMesaBuffer readBuffer )
2046{
2047   if (c) {
2048      if (!drawBuffer || !readBuffer)
2049         return GL_FALSE;  /* must specify buffers! */
2050
2051#ifdef FX
2052      if (drawBuffer->FXctx) {
2053         fxMesaMakeCurrent(drawBuffer->FXctx);
2054
2055         c->xm_buffer = drawBuffer;
2056         c->xm_read_buffer = readBuffer;
2057         c->use_read_buffer = (drawBuffer != readBuffer);
2058
2059         return GL_TRUE;
2060      }
2061#endif
2062      if (c->gl_ctx == _mesa_get_current_context()
2063          && c->xm_buffer == drawBuffer
2064          && c->xm_read_buffer == readBuffer
2065          && c->xm_buffer->wasCurrent) {
2066         /* same context and buffer, do nothing */
2067         return GL_TRUE;
2068      }
2069
2070      c->xm_buffer = drawBuffer;
2071      c->xm_read_buffer = readBuffer;
2072      c->use_read_buffer = (drawBuffer != readBuffer);
2073
2074      _mesa_make_current2(c->gl_ctx,
2075                          &drawBuffer->mesa_buffer,
2076                          &readBuffer->mesa_buffer);
2077
2078      if (c->gl_ctx->Viewport.Width == 0) {
2079	 /* initialize viewport to window size */
2080	 _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height );
2081	 c->gl_ctx->Scissor.Width = drawBuffer->width;
2082	 c->gl_ctx->Scissor.Height = drawBuffer->height;
2083      }
2084
2085      if (c->xm_visual->mesa_visual.rgbMode) {
2086         /*
2087          * Must recompute and set these pixel values because colormap
2088          * can be different for different windows.
2089          */
2090         c->clearpixel = xmesa_color_to_pixel( c,
2091                                               c->clearcolor[0],
2092                                               c->clearcolor[1],
2093                                               c->clearcolor[2],
2094                                               c->clearcolor[3],
2095                                               c->xm_visual->undithered_pf);
2096         XMesaSetForeground(c->display, c->xm_buffer->cleargc, c->clearpixel);
2097      }
2098
2099      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2100      c->xm_buffer->wasCurrent = GL_TRUE;
2101   }
2102   else {
2103      /* Detach */
2104      _mesa_make_current2( NULL, NULL, NULL );
2105   }
2106   return GL_TRUE;
2107}
2108
2109
2110/*
2111 * Unbind the context c from its buffer.
2112 */
2113GLboolean XMesaUnbindContext( XMesaContext c )
2114{
2115   /* A no-op for XFree86 integration purposes */
2116   return GL_TRUE;
2117}
2118
2119
2120XMesaContext XMesaGetCurrentContext( void )
2121{
2122   GET_CURRENT_CONTEXT(ctx);
2123   if (ctx) {
2124      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2125      return xmesa;
2126   }
2127   else {
2128      return 0;
2129   }
2130}
2131
2132
2133XMesaBuffer XMesaGetCurrentBuffer( void )
2134{
2135   GET_CURRENT_CONTEXT(ctx);
2136   if (ctx) {
2137      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2138      return xmesa->xm_buffer;
2139   }
2140   else {
2141      return 0;
2142   }
2143}
2144
2145
2146/* New in Mesa 3.1 */
2147XMesaBuffer XMesaGetCurrentReadBuffer( void )
2148{
2149   GET_CURRENT_CONTEXT(ctx);
2150   if (ctx) {
2151      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2152      return xmesa->xm_buffer;
2153   }
2154   else {
2155      return 0;
2156   }
2157}
2158
2159
2160GLboolean XMesaForceCurrent(XMesaContext c)
2161{
2162   if (c) {
2163      if (c->gl_ctx != _mesa_get_current_context()) {
2164	 _mesa_make_current(c->gl_ctx, &c->xm_buffer->mesa_buffer);
2165      }
2166   }
2167   else {
2168      _mesa_make_current(NULL, NULL);
2169   }
2170   return GL_TRUE;
2171}
2172
2173
2174GLboolean XMesaLoseCurrent(XMesaContext c)
2175{
2176   (void) c;
2177   _mesa_make_current(NULL, NULL);
2178   return GL_TRUE;
2179}
2180
2181
2182/*
2183 * Switch 3Dfx support hack between window and full-screen mode.
2184 */
2185GLboolean XMesaSetFXmode( GLint mode )
2186{
2187#ifdef FX
2188   const char *fx = getenv("MESA_GLX_FX");
2189   if (fx && fx[0] != 'd') {
2190      GET_CURRENT_CONTEXT(ctx);
2191      GrHwConfiguration hw;
2192      if (!FX_grSstQueryHardware(&hw)) {
2193         /*fprintf(stderr, "!grSstQueryHardware\n");*/
2194         return GL_FALSE;
2195      }
2196      if (hw.num_sst < 1) {
2197         /*fprintf(stderr, "hw.num_sst < 1\n");*/
2198         return GL_FALSE;
2199      }
2200      if (ctx) {
2201         XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2202         if (mode == XMESA_FX_WINDOW) {
2203	    if (xmesa->xm_buffer->FXisHackUsable) {
2204	       FX_grSstControl(GR_CONTROL_DEACTIVATE);
2205	       xmesa->xm_buffer->FXwindowHack = GL_TRUE;
2206	       return GL_TRUE;
2207	    }
2208	 }
2209	 else if (mode == XMESA_FX_FULLSCREEN) {
2210	    FX_grSstControl(GR_CONTROL_ACTIVATE);
2211	    xmesa->xm_buffer->FXwindowHack = GL_FALSE;
2212	    return GL_TRUE;
2213	 }
2214	 else {
2215	    /* Error: Bad mode value */
2216	 }
2217      }
2218   }
2219   /*fprintf(stderr, "fallthrough\n");*/
2220#else
2221   (void) mode;
2222#endif
2223   return GL_FALSE;
2224}
2225
2226
2227
2228#ifdef FX
2229/*
2230 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2231 */
2232static void FXgetImage( XMesaBuffer b )
2233{
2234   GET_CURRENT_CONTEXT(ctx);
2235   static unsigned short pixbuf[MAX_WIDTH];
2236   GLuint x, y;
2237   int xpos, ypos;
2238   XMesaWindow root;
2239   unsigned int bw, depth, width, height;
2240   XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2241
2242   assert(xmesa->xm_buffer->FXctx);
2243
2244#ifdef XFree86Server
2245   x = b->frontbuffer->x;
2246   y = b->frontbuffer->y;
2247   width = b->frontbuffer->width;
2248   height = b->frontbuffer->height;
2249   depth = b->frontbuffer->depth;
2250#else
2251   XGetGeometry( xmesa->xm_visual->display, b->frontbuffer,
2252                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2253#endif
2254   if (b->width != width || b->height != height) {
2255      b->width = MIN2((int)width, xmesa->xm_buffer->FXctx->width);
2256      b->height = MIN2((int)height, xmesa->xm_buffer->FXctx->height);
2257      if (b->width & 1)
2258         b->width--;  /* prevent odd width */
2259      xmesa_alloc_back_buffer( b );
2260   }
2261
2262   grLfbWriteColorFormat(GR_COLORFORMAT_ARGB);
2263   if (xmesa->xm_visual->undithered_pf==PF_5R6G5B) {
2264      /* Special case: 16bpp RGB */
2265      grLfbReadRegion( GR_BUFFER_FRONTBUFFER,       /* src buffer */
2266                       0, xmesa->xm_buffer->FXctx->height - b->height,  /*pos*/
2267                       b->width, b->height,         /* size */
2268                       b->width * sizeof(GLushort), /* stride */
2269                       b->backimage->data);         /* dest buffer */
2270   }
2271   else if (xmesa->xm_visual->dithered_pf==PF_DITHER
2272	    && GET_VISUAL_DEPTH(xmesa->xm_visual)==8) {
2273      /* Special case: 8bpp RGB */
2274      for (y=0;y<b->height;y++) {
2275         GLubyte *ptr = (GLubyte*) xmesa->xm_buffer->backimage->data
2276                        + xmesa->xm_buffer->backimage->bytes_per_line * y;
2277         XDITHER_SETUP(y);
2278
2279         /* read row from 3Dfx frame buffer */
2280         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2281                          0, xmesa->xm_buffer->FXctx->height-(b->height-y),
2282                          b->width, 1,
2283                          0,
2284                          pixbuf );
2285
2286         /* write to XImage back buffer */
2287         for (x=0;x<b->width;x++) {
2288            GLubyte r = (pixbuf[x] & 0xf800) >> 8;
2289            GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
2290            GLubyte b = (pixbuf[x] & 0x001f) << 3;
2291            *ptr++ = XDITHER( x, r, g, b);
2292         }
2293      }
2294   }
2295   else {
2296      /* General case: slow! */
2297      for (y=0;y<b->height;y++) {
2298         /* read row from 3Dfx frame buffer */
2299         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2300                          0, xmesa->xm_buffer->FXctx->height-(b->height-y),
2301                          b->width, 1,
2302                          0,
2303                          pixbuf );
2304
2305         /* write to XImage back buffer */
2306         for (x=0;x<b->width;x++) {
2307            XMesaPutPixel(b->backimage,x,y,
2308			  xmesa_color_to_pixel(xmesa,
2309					       (pixbuf[x] & 0xf800) >> 8,
2310					       (pixbuf[x] & 0x07e0) >> 3,
2311					       (pixbuf[x] & 0x001f) << 3,
2312					       0xff, xmesa->pixelformat));
2313         }
2314      }
2315   }
2316   grLfbWriteColorFormat(GR_COLORFORMAT_ABGR);
2317}
2318#endif
2319
2320
2321/*
2322 * Copy the back buffer to the front buffer.  If there's no back buffer
2323 * this is a no-op.
2324 */
2325void XMesaSwapBuffers( XMesaBuffer b )
2326{
2327   GET_CURRENT_CONTEXT(ctx);
2328
2329   /* If we're swapping the buffer associated with the current context
2330    * we have to flush any pending rendering commands first.
2331    */
2332   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2333      _mesa_swapbuffers(ctx);
2334
2335   if (b->db_state) {
2336#ifdef FX
2337      if (b->FXctx) {
2338         fxMesaSwapBuffers();
2339
2340         if (b->FXwindowHack)
2341            FXgetImage(b);
2342         else
2343            return;
2344      }
2345#endif
2346     if (b->backimage) {
2347	 /* Copy Ximage from host's memory to server's window */
2348#if defined(USE_XSHM) && !defined(XFree86Server)
2349	 if (b->shm) {
2350            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2351	    XShmPutImage( b->xm_visual->display, b->frontbuffer,
2352			  b->swapgc,
2353			  b->backimage, 0, 0,
2354			  0, 0, b->width, b->height, False );
2355            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2356	 }
2357	 else
2358#endif
2359         {
2360            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2361            XMesaPutImage( b->xm_visual->display, b->frontbuffer,
2362			   b->swapgc,
2363			   b->backimage, 0, 0,
2364			   0, 0, b->width, b->height );
2365            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2366         }
2367      }
2368      else {
2369	 /* Copy pixmap to window on server */
2370         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2371	 XMesaCopyArea( b->xm_visual->display,
2372			b->backpixmap,   /* source drawable */
2373			b->frontbuffer,  /* dest. drawable */
2374			b->swapgc,
2375			0, 0, b->width, b->height,  /* source region */
2376			0, 0                 /* dest region */
2377		      );
2378         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2379      }
2380   }
2381#if !defined(XFree86Server)
2382   XSync( b->xm_visual->display, False );
2383#endif
2384}
2385
2386
2387
2388/*
2389 * Copy sub-region of back buffer to front buffer
2390 */
2391void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2392{
2393   GET_CURRENT_CONTEXT(ctx);
2394
2395   /* If we're swapping the buffer associated with the current context
2396    * we have to flush any pending rendering commands first.
2397    */
2398   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2399      _mesa_swapbuffers(ctx);
2400
2401   if (b->db_state) {
2402      int yTop = b->height - y - height;
2403#ifdef FX
2404      if (b->FXctx) {
2405         fxMesaSwapBuffers();
2406         if (b->FXwindowHack)
2407            FXgetImage(b);
2408         else
2409            return;
2410      }
2411#endif
2412      if (b->backimage) {
2413         /* Copy Ximage from host's memory to server's window */
2414#if defined(USE_XSHM) && !defined(XFree86Server)
2415         if (b->shm) {
2416            /* XXX assuming width and height aren't too large! */
2417            XShmPutImage( b->xm_visual->display, b->frontbuffer,
2418                          b->swapgc,
2419                          b->backimage, x, yTop,
2420                          x, yTop, width, height, False );
2421            /* wait for finished event??? */
2422         }
2423         else
2424#endif
2425         {
2426            /* XXX assuming width and height aren't too large! */
2427            XMesaPutImage( b->xm_visual->display, b->frontbuffer,
2428			   b->swapgc,
2429			   b->backimage, x, yTop,
2430			   x, yTop, width, height );
2431         }
2432      }
2433      else {
2434         /* Copy pixmap to window on server */
2435         XMesaCopyArea( b->xm_visual->display,
2436			b->backpixmap,           /* source drawable */
2437			b->frontbuffer,          /* dest. drawable */
2438			b->swapgc,
2439			x, yTop, width, height,  /* source region */
2440			x, yTop                  /* dest region */
2441                      );
2442      }
2443   }
2444}
2445
2446
2447/*
2448 * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
2449 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2450 * back buffer directly.
2451 * Output:  pixmap - pointer to back buffer's Pixmap, or 0
2452 *          ximage - pointer to back buffer's XImage, or NULL
2453 * Return:  GL_TRUE = context is double buffered
2454 *          GL_FALSE = context is single buffered
2455 */
2456GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2457                              XMesaPixmap *pixmap,
2458                              XMesaImage **ximage )
2459{
2460   if (b->db_state) {
2461      if (pixmap)  *pixmap = b->backpixmap;
2462      if (ximage)  *ximage = b->backimage;
2463      return GL_TRUE;
2464   }
2465   else {
2466      *pixmap = 0;
2467      *ximage = NULL;
2468      return GL_FALSE;
2469   }
2470}
2471
2472
2473/*
2474 * Return the depth buffer associated with an XMesaBuffer.
2475 * Input:  b - the XMesa buffer handle
2476 * Output:  width, height - size of buffer in pixels
2477 *          bytesPerValue - bytes per depth value (2 or 4)
2478 *          buffer - pointer to depth buffer values
2479 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
2480 */
2481GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2482                               GLint *bytesPerValue, void **buffer )
2483{
2484   if (!b->mesa_buffer.DepthBuffer) {
2485      *width = 0;
2486      *height = 0;
2487      *bytesPerValue = 0;
2488      *buffer = 0;
2489      return GL_FALSE;
2490   }
2491   else {
2492      *width = b->mesa_buffer.Width;
2493      *height = b->mesa_buffer.Height;
2494      *bytesPerValue = sizeof(GLdepth);
2495      *buffer = b->mesa_buffer.DepthBuffer;
2496      return GL_TRUE;
2497   }
2498}
2499
2500
2501void XMesaFlush( XMesaContext c )
2502{
2503   if (c && c->xm_visual) {
2504#ifdef XFree86Server
2505      /* NOT_NEEDED */
2506#else
2507      XSync( c->xm_visual->display, False );
2508#endif
2509   }
2510}
2511
2512
2513
2514const char *XMesaGetString( XMesaContext c, int name )
2515{
2516   (void) c;
2517   if (name==XMESA_VERSION) {
2518      return "3.5";
2519   }
2520   else if (name==XMESA_EXTENSIONS) {
2521      return "";
2522   }
2523   else {
2524      return NULL;
2525   }
2526}
2527
2528
2529
2530XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2531{
2532   XMesaBuffer b;
2533   for (b=XMesaBufferList; b; b=b->Next) {
2534      if (b->frontbuffer==d && b->display==dpy) {
2535         return b;
2536      }
2537   }
2538   return NULL;
2539}
2540
2541
2542
2543/*
2544 * Look for XMesaBuffers whose X window has been destroyed.
2545 * Deallocate any such XMesaBuffers.
2546 */
2547void XMesaGarbageCollect( void )
2548{
2549   XMesaBuffer b, next;
2550   for (b=XMesaBufferList; b; b=next) {
2551      next = b->Next;
2552      if (b->display && b->frontbuffer && !b->pixmap_flag) {
2553#ifdef XFree86Server
2554	 /* NOT_NEEDED */
2555#else
2556         XSync(b->display, False);
2557         if (!window_exists( b->display, b->frontbuffer )) {
2558            /* found a dead window, free the ancillary info */
2559            XMesaDestroyBuffer( b );
2560         }
2561#endif
2562      }
2563   }
2564}
2565
2566
2567void XMesaReset( void )
2568{
2569    while (XMesaBufferList)
2570	XMesaDestroyBuffer(XMesaBufferList);
2571
2572    XMesaBufferList = NULL;
2573}
2574
2575
2576unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2577                                GLfloat red, GLfloat green,
2578                                GLfloat blue, GLfloat alpha )
2579{
2580   GLint r = (GLint) (red   * 255.0F);
2581   GLint g = (GLint) (green * 255.0F);
2582   GLint b = (GLint) (blue  * 255.0F);
2583   GLint a = (GLint) (alpha * 255.0F);
2584
2585   switch (xmesa->pixelformat) {
2586      case PF_INDEX:
2587         return 0;
2588      case PF_TRUECOLOR:
2589         {
2590            unsigned long p;
2591            PACK_TRUECOLOR( p, r, g, b );
2592            return p;
2593         }
2594      case PF_8A8B8G8R:
2595         return PACK_8A8B8G8R( r, g, b, a );
2596      case PF_8R8G8B:
2597         return PACK_8R8G8B( r, g, b );
2598      case PF_5R6G5B:
2599         return PACK_5R6G5B( r, g, b );
2600      case PF_DITHER:
2601         {
2602            DITHER_SETUP;
2603            return DITHER( x, y, r, g, b );
2604         }
2605      case PF_1BIT:
2606         /* 382 = (3*255)/2 */
2607         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2608      case PF_HPCR:
2609         return DITHER_HPCR(x, y, r, g, b);
2610      case PF_LOOKUP:
2611         {
2612            LOOKUP_SETUP;
2613            return LOOKUP( r, g, b );
2614         }
2615      case PF_GRAYSCALE:
2616         return GRAY_RGB( r, g, b );
2617      case PF_DITHER_5R6G5B:
2618         /* fall through */
2619      case PF_TRUEDITHER:
2620         {
2621            unsigned long p;
2622            PACK_TRUEDITHER(p, x, y, r, g, b);
2623            return p;
2624         }
2625      default:
2626         _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2627   }
2628   return 0;
2629}
2630
2631
2632/*
2633 * This is typically called when the window size changes and we need
2634 * to reallocate the buffer's back/depth/stencil/accum buffers.
2635 */
2636void XMesaResizeBuffers( XMesaBuffer b )
2637{
2638   xmesa_resize_buffers( &(b->mesa_buffer) );
2639
2640}
2641
2642