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