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