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