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