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