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