xm_api.c revision 42b26f688d82b2023ea882bfa1fd13bb6548d73a
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 "array_cache/acache.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   /* 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       !_ac_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   _ac_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      free_xmesa_buffer(client, 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      free_xmesa_buffer(client, 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      free_xmesa_buffer(client, 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 XMesaDestroyBuffer( XMesaBuffer b )
1831{
1832   int client = 0;
1833
1834#ifdef XFree86Server
1835   if (b->frontxrb->drawable)
1836       client = CLIENT_ID(b->frontxrb->drawable->id);
1837#endif
1838
1839   if (b->gc)  XMesaFreeGC( b->xm_visual->display, b->gc );
1840   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
1841   if (b->swapgc)  XMesaFreeGC( b->xm_visual->display, b->swapgc );
1842
1843   if (b->xm_visual->mesa_visual.doubleBufferMode)
1844   {
1845      if (b->backxrb->ximage) {
1846#if defined(USE_XSHM) && !defined(XFree86Server)
1847         if (b->shm) {
1848            XShmDetach( b->xm_visual->display, &b->shminfo );
1849            XDestroyImage( b->backxrb->ximage );
1850            shmdt( b->shminfo.shmaddr );
1851         }
1852         else
1853#endif
1854            XMesaDestroyImage( b->backxrb->ximage );
1855      }
1856      if (b->backxrb->pixmap) {
1857         XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
1858         if (b->xm_visual->hpcr_clear_flag) {
1859            XMesaFreePixmap( b->xm_visual->display,
1860                             b->xm_visual->hpcr_clear_pixmap );
1861            XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
1862         }
1863      }
1864   }
1865   if (b->rowimage) {
1866      _mesa_free( b->rowimage->data );
1867      b->rowimage->data = NULL;
1868      XMesaDestroyImage( b->rowimage );
1869   }
1870
1871   free_xmesa_buffer(client, b);
1872}
1873
1874
1875/**
1876 * Query the current window size and update the corresponding GLframebuffer
1877 * and all attached renderbuffers.
1878 * Called when:
1879 *  1. the first time a buffer is bound to a context.
1880 *  2. from glViewport to poll for window size changes
1881 *  3. from the XMesaResizeBuffers() API function.
1882 */
1883void
1884xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
1885{
1886   GLuint width, height;
1887   xmesa_get_window_size(xmctx->display, drawBuffer, &width, &height);
1888   if (drawBuffer->mesa_buffer.Width != width ||
1889       drawBuffer->mesa_buffer.Height != height) {
1890      _mesa_resize_framebuffer(&(xmctx->mesa),
1891                               &(drawBuffer->mesa_buffer), width, height);
1892   }
1893   drawBuffer->mesa_buffer.Initialized = GL_TRUE; /* XXX TEMPORARY? */
1894}
1895
1896
1897/*
1898 * Bind buffer b to context c and make c the current rendering context.
1899 */
1900GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
1901{
1902   return XMesaMakeCurrent2( c, b, b );
1903}
1904
1905
1906/*
1907 * Bind buffer b to context c and make c the current rendering context.
1908 */
1909GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1910                             XMesaBuffer readBuffer )
1911{
1912   if (c) {
1913      if (!drawBuffer || !readBuffer)
1914         return GL_FALSE;  /* must specify buffers! */
1915
1916#ifdef FX
1917      if (drawBuffer->FXctx) {
1918         fxMesaMakeCurrent(drawBuffer->FXctx);
1919
1920         c->xm_buffer = drawBuffer;
1921
1922         return GL_TRUE;
1923      }
1924#endif
1925      if (&(c->mesa) == _mesa_get_current_context()
1926          && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
1927          && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
1928          && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) {
1929         /* same context and buffer, do nothing */
1930         return GL_TRUE;
1931      }
1932
1933      c->xm_buffer = drawBuffer;
1934
1935      /* Call this periodically to detect when the user has begun using
1936       * GL rendering from multiple threads.
1937       */
1938      _glapi_check_multithread();
1939
1940      xmesa_check_and_update_buffer_size(c, drawBuffer);
1941      if (readBuffer != drawBuffer)
1942         xmesa_check_and_update_buffer_size(c, readBuffer);
1943
1944      _mesa_make_current(&(c->mesa),
1945                         &drawBuffer->mesa_buffer,
1946                         &readBuffer->mesa_buffer);
1947
1948      if (c->xm_visual->mesa_visual.rgbMode) {
1949         /*
1950          * Must recompute and set these pixel values because colormap
1951          * can be different for different windows.
1952          */
1953         c->clearpixel = xmesa_color_to_pixel( &c->mesa,
1954                                               c->clearcolor[0],
1955                                               c->clearcolor[1],
1956                                               c->clearcolor[2],
1957                                               c->clearcolor[3],
1958                                               c->xm_visual->undithered_pf);
1959         XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
1960      }
1961
1962      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1963      drawBuffer->wasCurrent = GL_TRUE;
1964   }
1965   else {
1966      /* Detach */
1967      _mesa_make_current( NULL, NULL, NULL );
1968   }
1969   return GL_TRUE;
1970}
1971
1972
1973/*
1974 * Unbind the context c from its buffer.
1975 */
1976GLboolean XMesaUnbindContext( XMesaContext c )
1977{
1978   /* A no-op for XFree86 integration purposes */
1979   return GL_TRUE;
1980}
1981
1982
1983XMesaContext XMesaGetCurrentContext( void )
1984{
1985   GET_CURRENT_CONTEXT(ctx);
1986   if (ctx) {
1987      XMesaContext xmesa = XMESA_CONTEXT(ctx);
1988      return xmesa;
1989   }
1990   else {
1991      return 0;
1992   }
1993}
1994
1995
1996XMesaBuffer XMesaGetCurrentBuffer( void )
1997{
1998   GET_CURRENT_CONTEXT(ctx);
1999   if (ctx) {
2000      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2001      return xmbuf;
2002   }
2003   else {
2004      return 0;
2005   }
2006}
2007
2008
2009/* New in Mesa 3.1 */
2010XMesaBuffer XMesaGetCurrentReadBuffer( void )
2011{
2012   GET_CURRENT_CONTEXT(ctx);
2013   if (ctx) {
2014      return XMESA_BUFFER(ctx->ReadBuffer);
2015   }
2016   else {
2017      return 0;
2018   }
2019}
2020
2021
2022GLboolean XMesaForceCurrent(XMesaContext c)
2023{
2024   if (c) {
2025      if (&(c->mesa) != _mesa_get_current_context()) {
2026	 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
2027      }
2028   }
2029   else {
2030      _mesa_make_current(NULL, NULL, NULL);
2031   }
2032   return GL_TRUE;
2033}
2034
2035
2036GLboolean XMesaLoseCurrent(XMesaContext c)
2037{
2038   (void) c;
2039   _mesa_make_current(NULL, NULL, NULL);
2040   return GL_TRUE;
2041}
2042
2043
2044/*
2045 * Switch 3Dfx support hack between window and full-screen mode.
2046 */
2047GLboolean XMesaSetFXmode( GLint mode )
2048{
2049#ifdef FX
2050   const char *fx = _mesa_getenv("MESA_GLX_FX");
2051   if (fx && fx[0] != 'd') {
2052      GET_CURRENT_CONTEXT(ctx);
2053      GrHwConfiguration hw;
2054      if (!FX_grSstQueryHardware(&hw)) {
2055         /*fprintf(stderr, "!grSstQueryHardware\n");*/
2056         return GL_FALSE;
2057      }
2058      if (hw.num_sst < 1) {
2059         /*fprintf(stderr, "hw.num_sst < 1\n");*/
2060         return GL_FALSE;
2061      }
2062      if (ctx) {
2063         /* [dBorca] Hack alert:
2064	  * oh, this is sooo wrong: ctx above is
2065	  * really an fxMesaContext, not an XMesaContext
2066	  */
2067         XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2068         if (mode == XMESA_FX_WINDOW) {
2069	    if (xmbuf->FXisHackUsable) {
2070	       FX_grSstControl(GR_CONTROL_DEACTIVATE);
2071	       xmbuf->FXwindowHack = GL_TRUE;
2072	       return GL_TRUE;
2073	    }
2074	 }
2075	 else if (mode == XMESA_FX_FULLSCREEN) {
2076	    FX_grSstControl(GR_CONTROL_ACTIVATE);
2077	    xmbuf->FXwindowHack = GL_FALSE;
2078	    return GL_TRUE;
2079	 }
2080	 else {
2081	    /* Error: Bad mode value */
2082	 }
2083      }
2084   }
2085   /*fprintf(stderr, "fallthrough\n");*/
2086#else
2087   (void) mode;
2088#endif
2089   return GL_FALSE;
2090}
2091
2092
2093
2094#ifdef FX
2095/*
2096 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2097 */
2098static void FXgetImage( XMesaBuffer b )
2099{
2100   GET_CURRENT_CONTEXT(ctx);
2101   static unsigned short pixbuf[MAX_WIDTH];
2102   GLuint x, y;
2103   GLuint width, height;
2104   XMesaContext xmesa = XMESA_CONTEXT(ctx);
2105
2106#ifdef XFree86Server
2107   x = b->frontxrb->pixmap->x;
2108   y = b->frontxrb->pixmap->y;
2109   width = b->frontxrb->pixmap->width;
2110   height = b->frontxrb->pixmap->height;
2111   depth = b->frontxrb->pixmap->depth;
2112#else
2113   xmesa_get_window_size(b->display, b, &width, &height);
2114   x = y = 0;
2115#endif
2116   if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) {
2117      b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width);
2118      b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height);
2119      if (b->mesa_buffer.Width & 1)
2120         b->mesa_buffer.Width--;  /* prevent odd width */
2121   }
2122
2123   /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
2124   /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
2125   if (b->xm_visual->undithered_pf==PF_5R6G5B) {
2126      /* Special case: 16bpp RGB */
2127      grLfbReadRegion( GR_BUFFER_FRONTBUFFER,       /* src buffer */
2128                       0, b->FXctx->height - b->mesa_buffer.Height,  /*pos*/
2129                       b->mesa_buffer.Width, b->mesa_buffer.Height,  /* size */
2130                       b->mesa_buffer.Width * sizeof(GLushort), /* stride */
2131                       b->backxrb->ximage->data);         /* dest buffer */
2132   }
2133   else if (b->xm_visual->dithered_pf==PF_Dither
2134	    && GET_VISUAL_DEPTH(b->xm_visual)==8) {
2135      /* Special case: 8bpp RGB */
2136      for (y=0;y<b->mesa_buffer.Height;y++) {
2137         GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data
2138                        + b->backxrb->ximage->bytes_per_line * y;
2139         XDITHER_SETUP(y);
2140
2141         /* read row from 3Dfx frame buffer */
2142         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2143                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2144                          b->mesa_buffer.Width, 1,
2145                          0,
2146                          pixbuf );
2147
2148         /* write to XImage back buffer */
2149         for (x=0;x<b->mesa_buffer.Width;x++) {
2150            GLubyte r = (pixbuf[x] & 0xf800) >> 8;
2151            GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
2152            GLubyte b = (pixbuf[x] & 0x001f) << 3;
2153            *ptr++ = XDITHER( x, r, g, b);
2154         }
2155      }
2156   }
2157   else {
2158      /* General case: slow! */
2159      for (y=0;y<b->mesa_buffer.Height;y++) {
2160         /* read row from 3Dfx frame buffer */
2161         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2162                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2163                          b->mesa_buffer.Width, 1,
2164                          0,
2165                          pixbuf );
2166
2167         /* write to XImage back buffer */
2168         for (x=0;x<b->mesa_buffer.Width;x++) {
2169            XMesaPutPixel(b->backxrb->ximage,x,y,
2170			  xmesa_color_to_pixel(ctx,
2171					       (pixbuf[x] & 0xf800) >> 8,
2172					       (pixbuf[x] & 0x07e0) >> 3,
2173					       (pixbuf[x] & 0x001f) << 3,
2174					       0xff,
2175                                               b->xm_visual->undithered_pf));
2176         }
2177      }
2178   }
2179   /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
2180}
2181#endif
2182
2183
2184/*
2185 * Copy the back buffer to the front buffer.  If there's no back buffer
2186 * this is a no-op.
2187 */
2188void XMesaSwapBuffers( XMesaBuffer b )
2189{
2190   GET_CURRENT_CONTEXT(ctx);
2191
2192   if (!b->backxrb) {
2193      /* single buffered */
2194      return;
2195   }
2196
2197   /* If we're swapping the buffer associated with the current context
2198    * we have to flush any pending rendering commands first.
2199    */
2200   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2201      _mesa_notifySwapBuffers(ctx);
2202
2203   if (b->db_mode) {
2204#ifdef FX
2205      if (b->FXctx) {
2206         fxMesaSwapBuffers();
2207
2208         if (b->FXwindowHack)
2209            FXgetImage(b);
2210         else
2211            return;
2212      }
2213#endif
2214     if (b->backxrb->ximage) {
2215	 /* Copy Ximage from host's memory to server's window */
2216#if defined(USE_XSHM) && !defined(XFree86Server)
2217	 if (b->shm) {
2218            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2219	    XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2220			  b->swapgc,
2221			  b->backxrb->ximage, 0, 0,
2222			  0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2223                          False );
2224            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2225	 }
2226	 else
2227#endif
2228         {
2229            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2230            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2231			   b->swapgc,
2232			   b->backxrb->ximage, 0, 0,
2233			   0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
2234            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2235         }
2236      }
2237      else {
2238	 /* Copy pixmap to window on server */
2239         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2240	 XMesaCopyArea( b->xm_visual->display,
2241			b->backxrb->pixmap,   /* source drawable */
2242			b->frontxrb->drawable,  /* dest. drawable */
2243			b->swapgc,
2244			0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2245			0, 0                 /* dest region */
2246		      );
2247         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2248      }
2249   }
2250#if !defined(XFree86Server)
2251   XSync( b->xm_visual->display, False );
2252#endif
2253}
2254
2255
2256
2257/*
2258 * Copy sub-region of back buffer to front buffer
2259 */
2260void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2261{
2262   GET_CURRENT_CONTEXT(ctx);
2263
2264   /* If we're swapping the buffer associated with the current context
2265    * we have to flush any pending rendering commands first.
2266    */
2267   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2268      _mesa_notifySwapBuffers(ctx);
2269
2270   if (!b->backxrb) {
2271      /* single buffered */
2272      return;
2273   }
2274
2275   if (b->db_mode) {
2276      int yTop = b->mesa_buffer.Height - y - height;
2277#ifdef FX
2278      if (b->FXctx) {
2279         fxMesaSwapBuffers();
2280         if (b->FXwindowHack)
2281            FXgetImage(b);
2282         else
2283            return;
2284      }
2285#endif
2286      if (b->backxrb->ximage) {
2287         /* Copy Ximage from host's memory to server's window */
2288#if defined(USE_XSHM) && !defined(XFree86Server)
2289         if (b->shm) {
2290            /* XXX assuming width and height aren't too large! */
2291            XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2292                          b->swapgc,
2293                          b->backxrb->ximage, x, yTop,
2294                          x, yTop, width, height, False );
2295            /* wait for finished event??? */
2296         }
2297         else
2298#endif
2299         {
2300            /* XXX assuming width and height aren't too large! */
2301            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2302			   b->swapgc,
2303			   b->backxrb->ximage, x, yTop,
2304			   x, yTop, width, height );
2305         }
2306      }
2307      else {
2308         /* Copy pixmap to window on server */
2309         XMesaCopyArea( b->xm_visual->display,
2310			b->backxrb->pixmap,           /* source drawable */
2311			b->frontxrb->drawable,        /* dest. drawable */
2312			b->swapgc,
2313			x, yTop, width, height,  /* source region */
2314			x, yTop                  /* dest region */
2315                      );
2316      }
2317   }
2318}
2319
2320
2321/*
2322 * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
2323 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2324 * back buffer directly.
2325 * Output:  pixmap - pointer to back buffer's Pixmap, or 0
2326 *          ximage - pointer to back buffer's XImage, or NULL
2327 * Return:  GL_TRUE = context is double buffered
2328 *          GL_FALSE = context is single buffered
2329 */
2330#ifndef XFree86Server
2331GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2332                              XMesaPixmap *pixmap,
2333                              XMesaImage **ximage )
2334{
2335   if (b->db_mode) {
2336      if (pixmap)
2337         *pixmap = b->backxrb->pixmap;
2338      if (ximage)
2339         *ximage = b->backxrb->ximage;
2340      return GL_TRUE;
2341   }
2342   else {
2343      *pixmap = 0;
2344      *ximage = NULL;
2345      return GL_FALSE;
2346   }
2347}
2348#endif /* XFree86Server */
2349
2350
2351/*
2352 * Return the depth buffer associated with an XMesaBuffer.
2353 * Input:  b - the XMesa buffer handle
2354 * Output:  width, height - size of buffer in pixels
2355 *          bytesPerValue - bytes per depth value (2 or 4)
2356 *          buffer - pointer to depth buffer values
2357 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
2358 */
2359GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2360                               GLint *bytesPerValue, void **buffer )
2361{
2362   struct gl_renderbuffer *rb
2363      = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
2364   if (!rb || !rb->Data) {
2365      *width = 0;
2366      *height = 0;
2367      *bytesPerValue = 0;
2368      *buffer = 0;
2369      return GL_FALSE;
2370   }
2371   else {
2372      *width = b->mesa_buffer.Width;
2373      *height = b->mesa_buffer.Height;
2374      *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
2375         ? sizeof(GLushort) : sizeof(GLuint);
2376      *buffer = rb->Data;
2377      return GL_TRUE;
2378   }
2379}
2380
2381
2382void XMesaFlush( XMesaContext c )
2383{
2384   if (c && c->xm_visual) {
2385#ifdef XFree86Server
2386      /* NOT_NEEDED */
2387#else
2388      XSync( c->xm_visual->display, False );
2389#endif
2390   }
2391}
2392
2393
2394
2395const char *XMesaGetString( XMesaContext c, int name )
2396{
2397   (void) c;
2398   if (name==XMESA_VERSION) {
2399      return "5.0";
2400   }
2401   else if (name==XMESA_EXTENSIONS) {
2402      return "";
2403   }
2404   else {
2405      return NULL;
2406   }
2407}
2408
2409
2410
2411XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2412{
2413   XMesaBuffer b;
2414   for (b=XMesaBufferList; b; b=b->Next) {
2415      if (b->frontxrb->drawable == d && b->display == dpy) {
2416         return b;
2417      }
2418   }
2419   return NULL;
2420}
2421
2422
2423/**
2424 * Free/destroy all XMesaBuffers associated with given display.
2425 */
2426void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
2427{
2428   XMesaBuffer b, next;
2429   for (b = XMesaBufferList; b; b = next) {
2430      next = b->Next;
2431      if (b->display == dpy) {
2432         free_xmesa_buffer(0, b);
2433      }
2434   }
2435}
2436
2437
2438/*
2439 * Look for XMesaBuffers whose X window has been destroyed.
2440 * Deallocate any such XMesaBuffers.
2441 */
2442void XMesaGarbageCollect( void )
2443{
2444   XMesaBuffer b, next;
2445   for (b=XMesaBufferList; b; b=next) {
2446      next = b->Next;
2447      if (b->display && b->frontxrb->drawable && b->type == WINDOW) {
2448#ifdef XFree86Server
2449	 /* NOT_NEEDED */
2450#else
2451         XSync(b->display, False);
2452         if (!window_exists( b->display, b->frontxrb->drawable )) {
2453            /* found a dead window, free the ancillary info */
2454            XMesaDestroyBuffer( b );
2455         }
2456#endif
2457      }
2458   }
2459}
2460
2461
2462void XMesaReset( void )
2463{
2464    while (XMesaBufferList)
2465	XMesaDestroyBuffer(XMesaBufferList);
2466
2467    XMesaBufferList = NULL;
2468}
2469
2470
2471unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2472                                GLfloat red, GLfloat green,
2473                                GLfloat blue, GLfloat alpha )
2474{
2475   GLcontext *ctx = &xmesa->mesa;
2476   GLint r = (GLint) (red   * 255.0F);
2477   GLint g = (GLint) (green * 255.0F);
2478   GLint b = (GLint) (blue  * 255.0F);
2479   GLint a = (GLint) (alpha * 255.0F);
2480
2481   switch (xmesa->pixelformat) {
2482      case PF_Index:
2483         return 0;
2484      case PF_Truecolor:
2485         {
2486            unsigned long p;
2487            PACK_TRUECOLOR( p, r, g, b );
2488            return p;
2489         }
2490      case PF_8A8B8G8R:
2491         return PACK_8A8B8G8R( r, g, b, a );
2492      case PF_8A8R8G8B:
2493         return PACK_8A8R8G8B( r, g, b, a );
2494      case PF_8R8G8B:
2495         return PACK_8R8G8B( r, g, b );
2496      case PF_5R6G5B:
2497         return PACK_5R6G5B( r, g, b );
2498      case PF_Dither:
2499         {
2500            DITHER_SETUP;
2501            return DITHER( x, y, r, g, b );
2502         }
2503      case PF_1Bit:
2504         /* 382 = (3*255)/2 */
2505         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2506      case PF_HPCR:
2507         return DITHER_HPCR(x, y, r, g, b);
2508      case PF_Lookup:
2509         {
2510            LOOKUP_SETUP;
2511            return LOOKUP( r, g, b );
2512         }
2513      case PF_Grayscale:
2514         return GRAY_RGB( r, g, b );
2515      case PF_Dither_5R6G5B:
2516         /* fall through */
2517      case PF_Dither_True:
2518         {
2519            unsigned long p;
2520            PACK_TRUEDITHER(p, x, y, r, g, b);
2521            return p;
2522         }
2523      default:
2524         _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2525   }
2526   return 0;
2527}
2528
2529
2530/*
2531 * This is typically called when the window size changes and we need
2532 * to reallocate the buffer's back/depth/stencil/accum buffers.
2533 */
2534void
2535XMesaResizeBuffers( XMesaBuffer b )
2536{
2537   GET_CURRENT_CONTEXT(ctx);
2538   XMesaContext xmctx = XMESA_CONTEXT(ctx);
2539   xmesa_check_and_update_buffer_size(xmctx, b);
2540}
2541
2542