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