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