xm_api.c revision 6c06ce281aa7a7e20eab1934f573bc5c673d41cb
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.1
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 "made current" for the first time, we can finally
1189 * finish initializing the context's visual and buffer information.
1190 * Input:  v - the XMesaVisual to initialize
1191 *         b - the XMesaBuffer to initialize (may be NULL)
1192 *         rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1193 *         window - the window/pixmap we're rendering into
1194 *         cmap - the colormap associated with the window/pixmap
1195 * Return:  GL_TRUE=success, GL_FALSE=failure
1196 */
1197static GLboolean initialize_visual_and_buffer( int client,
1198                                               XMesaVisual v,
1199                                               XMesaBuffer b,
1200                                               GLboolean rgb_flag,
1201                                               XMesaDrawable window,
1202                                               XMesaColormap cmap )
1203{
1204   struct xmesa_renderbuffer *front_xrb, *back_xrb;
1205#ifndef XFree86Server
1206   XGCValues gcvalues;
1207#endif
1208
1209   if (b) {
1210      assert(b->xm_visual == v);
1211   }
1212
1213   if (b) {
1214      front_xrb = b->frontxrb;
1215      back_xrb = b->backxrb;
1216   }
1217   else {
1218      front_xrb = back_xrb = NULL;
1219   }
1220
1221   /* Save true bits/pixel */
1222   v->BitsPerPixel = bits_per_pixel(v);
1223   assert(v->BitsPerPixel > 0);
1224
1225
1226   if (rgb_flag==GL_FALSE) {
1227      /* COLOR-INDEXED WINDOW:
1228       * Even if the visual is TrueColor or DirectColor we treat it as
1229       * being color indexed.  This is weird but might be useful to someone.
1230       */
1231      v->dithered_pf = v->undithered_pf = PF_Index;
1232      v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v);
1233   }
1234   else {
1235      /* RGB WINDOW:
1236       * We support RGB rendering into almost any kind of visual.
1237       */
1238      const int xclass = v->mesa_visual.visualType;
1239      if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
1240	 setup_truecolor( v, b, cmap );
1241      }
1242      else if (xclass==GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v)==1) {
1243	 setup_monochrome( v, b );
1244      }
1245      else if (xclass==GLX_GRAY_SCALE || xclass==GLX_STATIC_GRAY) {
1246         if (!setup_grayscale( client, v, b, cmap )) {
1247            return GL_FALSE;
1248         }
1249      }
1250      else if ((xclass==GLX_PSEUDO_COLOR || xclass==GLX_STATIC_COLOR)
1251               && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
1252	 if (!setup_dithered_color( client, v, b, cmap )) {
1253            return GL_FALSE;
1254         }
1255      }
1256      else {
1257	 _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n");
1258	 return GL_FALSE;
1259      }
1260      v->mesa_visual.indexBits = 0;
1261
1262      if (_mesa_getenv("MESA_NO_DITHER")) {
1263	 v->dithered_pf = v->undithered_pf;
1264      }
1265   }
1266
1267
1268   /*
1269    * If MESA_INFO env var is set print out some debugging info
1270    * which can help Brian figure out what's going on when a user
1271    * reports bugs.
1272    */
1273   if (_mesa_getenv("MESA_INFO")) {
1274      _mesa_printf("X/Mesa visual = %p\n", (void *) v);
1275      _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf);
1276      _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf);
1277      _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
1278      _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
1279      _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
1280   }
1281
1282   if (b && window) {
1283      /* Do window-specific initializations */
1284
1285      b->frontxrb->drawable = window;
1286      b->frontxrb->pixmap = (XMesaPixmap) window;
1287
1288      /* Setup for single/double buffering */
1289      if (v->mesa_visual.doubleBufferMode) {
1290         /* Double buffered */
1291         b->shm = check_for_xshm( v->display );
1292         xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height);
1293      }
1294
1295      /* X11 graphics contexts */
1296#ifdef XFree86Server
1297      b->gc = CreateScratchGC(v->display, window->depth);
1298#else
1299      b->gc = XCreateGC( v->display, window, 0, NULL );
1300#endif
1301      XMesaSetFunction( v->display, b->gc, GXcopy );
1302
1303      /* cleargc - for glClear() */
1304#ifdef XFree86Server
1305      b->cleargc = CreateScratchGC(v->display, window->depth);
1306#else
1307      b->cleargc = XCreateGC( v->display, window, 0, NULL );
1308#endif
1309      XMesaSetFunction( v->display, b->cleargc, GXcopy );
1310
1311      /*
1312       * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1313       * Patch contributed by Michael Pichler May 15, 1995.
1314       */
1315#ifdef XFree86Server
1316      b->swapgc = CreateScratchGC(v->display, window->depth);
1317      {
1318         CARD32 v[1];
1319         v[0] = FALSE;
1320         dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL);
1321      }
1322#else
1323      gcvalues.graphics_exposures = False;
1324      b->swapgc = XCreateGC( v->display, window,
1325                              GCGraphicsExposures, &gcvalues);
1326#endif
1327      XMesaSetFunction( v->display, b->swapgc, GXcopy );
1328      /*
1329       * Set fill style and tile pixmap once for all for HPCR stuff
1330       * (instead of doing it each time in clear_color_HPCR_pixmap())
1331       * Initialize whole stuff
1332       * Patch contributed by Jacques Leroy March 8, 1998.
1333       */
1334      if (v->hpcr_clear_flag && back_xrb->pixmap) {
1335	int i;
1336	for (i=0; i<16; i++)
1337        {
1338	   XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0);
1339	   XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0);
1340        }
1341        XMesaPutImage(b->display, (XMesaDrawable) v->hpcr_clear_pixmap,
1342		      b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
1343	XMesaSetFillStyle( v->display, b->cleargc, FillTiled);
1344	XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap );
1345      }
1346
1347      /* Initialize the row buffer XImage for use in write_color_span() */
1348#ifdef XFree86Server
1349      b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1,
1350				     (char *)MALLOC(MAX_WIDTH*4));
1351#else
1352      b->rowimage = XCreateImage( v->display,
1353                                  v->visinfo->visual,
1354                                  v->visinfo->depth,
1355                                  ZPixmap, 0,           /*format, offset*/
1356                                  (char*) MALLOC(MAX_WIDTH*4),  /*data*/
1357                                  MAX_WIDTH, 1,         /*width, height*/
1358                                  32,                   /*bitmap_pad*/
1359                                  0                     /*bytes_per_line*/ );
1360#endif
1361      if (!b->rowimage)
1362         return GL_FALSE;
1363   }
1364
1365   return GL_TRUE;
1366}
1367
1368
1369
1370/*
1371 * Convert an RGBA color to a pixel value.
1372 */
1373unsigned long
1374xmesa_color_to_pixel(GLcontext *ctx,
1375                     GLubyte r, GLubyte g, GLubyte b, GLubyte a,
1376                     GLuint pixelFormat)
1377{
1378   XMesaContext xmesa = XMESA_CONTEXT(ctx);
1379   switch (pixelFormat) {
1380      case PF_Index:
1381         return 0;
1382      case PF_Truecolor:
1383         {
1384            unsigned long p;
1385            PACK_TRUECOLOR( p, r, g, b );
1386            return p;
1387         }
1388      case PF_8A8B8G8R:
1389         return PACK_8A8B8G8R( r, g, b, a );
1390      case PF_8A8R8G8B:
1391         return PACK_8A8R8G8B( r, g, b, a );
1392      case PF_8R8G8B:
1393         /* fall through */
1394      case PF_8R8G8B24:
1395         return PACK_8R8G8B( r, g, b );
1396      case PF_5R6G5B:
1397         return PACK_5R6G5B( r, g, b );
1398      case PF_Dither:
1399         {
1400            DITHER_SETUP;
1401            return DITHER( 1, 0, r, g, b );
1402         }
1403      case PF_1Bit:
1404         /* 382 = (3*255)/2 */
1405         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
1406      case PF_HPCR:
1407         return DITHER_HPCR(1, 1, r, g, b);
1408      case PF_Lookup:
1409         {
1410            LOOKUP_SETUP;
1411            return LOOKUP( r, g, b );
1412         }
1413      case PF_Grayscale:
1414         return GRAY_RGB( r, g, b );
1415      case PF_Dither_True:
1416         /* fall through */
1417      case PF_Dither_5R6G5B:
1418         {
1419            unsigned long p;
1420            PACK_TRUEDITHER(p, 1, 0, r, g, b);
1421            return p;
1422         }
1423      default:
1424         _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel");
1425   }
1426   return 0;
1427}
1428
1429
1430#define NUM_VISUAL_TYPES   6
1431
1432/**
1433 * Convert an X visual type to a GLX visual type.
1434 *
1435 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
1436 *        to be converted.
1437 * \return If \c visualType is a valid X visual type, a GLX visual type will
1438 *         be returned.  Otherwise \c GLX_NONE will be returned.
1439 *
1440 * \note
1441 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
1442 * DRI CVS tree.
1443 */
1444static GLint
1445xmesa_convert_from_x_visual_type( int visualType )
1446{
1447    static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
1448	GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
1449	GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
1450	GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
1451    };
1452
1453    return ( (unsigned) visualType < NUM_VISUAL_TYPES )
1454	? glx_visual_types[ visualType ] : GLX_NONE;
1455}
1456
1457
1458/**********************************************************************/
1459/*****                       Public Functions                     *****/
1460/**********************************************************************/
1461
1462
1463/*
1464 * Create a new X/Mesa visual.
1465 * Input:  display - X11 display
1466 *         visinfo - an XVisualInfo pointer
1467 *         rgb_flag - GL_TRUE = RGB mode,
1468 *                    GL_FALSE = color index mode
1469 *         alpha_flag - alpha buffer requested?
1470 *         db_flag - GL_TRUE = double-buffered,
1471 *                   GL_FALSE = single buffered
1472 *         stereo_flag - stereo visual?
1473 *         ximage_flag - GL_TRUE = use an XImage for back buffer,
1474 *                       GL_FALSE = use an off-screen pixmap for back buffer
1475 *         depth_size - requested bits/depth values, or zero
1476 *         stencil_size - requested bits/stencil values, or zero
1477 *         accum_red_size - requested bits/red accum values, or zero
1478 *         accum_green_size - requested bits/green accum values, or zero
1479 *         accum_blue_size - requested bits/blue accum values, or zero
1480 *         accum_alpha_size - requested bits/alpha accum values, or zero
1481 *         num_samples - number of samples/pixel if multisampling, or zero
1482 *         level - visual level, usually 0
1483 *         visualCaveat - ala the GLX extension, usually GLX_NONE
1484 * Return;  a new XMesaVisual or 0 if error.
1485 */
1486XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
1487                               XMesaVisualInfo visinfo,
1488                               GLboolean rgb_flag,
1489                               GLboolean alpha_flag,
1490                               GLboolean db_flag,
1491                               GLboolean stereo_flag,
1492                               GLboolean ximage_flag,
1493                               GLint depth_size,
1494                               GLint stencil_size,
1495                               GLint accum_red_size,
1496                               GLint accum_green_size,
1497                               GLint accum_blue_size,
1498                               GLint accum_alpha_size,
1499                               GLint num_samples,
1500                               GLint level,
1501                               GLint visualCaveat )
1502{
1503   char *gamma;
1504   XMesaVisual v;
1505   GLint red_bits, green_bits, blue_bits, alpha_bits;
1506
1507   /* For debugging only */
1508   if (_mesa_getenv("MESA_XSYNC")) {
1509      /* This makes debugging X easier.
1510       * In your debugger, set a breakpoint on _XError to stop when an
1511       * X protocol error is generated.
1512       */
1513#ifdef XFree86Server
1514      /* NOT_NEEDED */
1515#else
1516      XSynchronize( display, 1 );
1517#endif
1518   }
1519
1520   v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
1521   if (!v) {
1522      return NULL;
1523   }
1524
1525   /*
1526    * In the X server, NULL is passed in for the display.  It will have
1527    * to be set before using this visual.  See XMesaSetVisualDisplay()
1528    * below.
1529    */
1530   v->display = display;
1531
1532   /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
1533    * the struct but we may need some of the information contained in it
1534    * at a later time.
1535    */
1536#ifndef XFree86Server
1537   v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
1538   if(!v->visinfo) {
1539      _mesa_free(v);
1540      return NULL;
1541   }
1542   MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
1543#endif
1544
1545   /* check for MESA_GAMMA environment variable */
1546   gamma = _mesa_getenv("MESA_GAMMA");
1547   if (gamma) {
1548      v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
1549      sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
1550      if (v->RedGamma<=0.0)    v->RedGamma = 1.0;
1551      if (v->GreenGamma<=0.0)  v->GreenGamma = v->RedGamma;
1552      if (v->BlueGamma<=0.0)   v->BlueGamma = v->RedGamma;
1553   }
1554   else {
1555      v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
1556   }
1557
1558   v->ximage_flag = ximage_flag;
1559
1560#ifdef XFree86Server
1561   /* We could calculate these values by ourselves.  nplanes is either the sum
1562    * of the red, green, and blue bits or the number index bits.
1563    * ColormapEntries is either (1U << index_bits) or
1564    * (1U << max(redBits, greenBits, blueBits)).
1565    */
1566   assert(visinfo->nplanes > 0);
1567   v->nplanes = visinfo->nplanes;
1568   v->ColormapEntries = visinfo->ColormapEntries;
1569
1570   v->mesa_visual.redMask = visinfo->redMask;
1571   v->mesa_visual.greenMask = visinfo->greenMask;
1572   v->mesa_visual.blueMask = visinfo->blueMask;
1573   v->mesa_visual.visualID = visinfo->vid;
1574   v->mesa_visual.screen = 0; /* FIXME: What should be done here? */
1575#else
1576   v->mesa_visual.redMask = visinfo->red_mask;
1577   v->mesa_visual.greenMask = visinfo->green_mask;
1578   v->mesa_visual.blueMask = visinfo->blue_mask;
1579   v->mesa_visual.visualID = visinfo->visualid;
1580   v->mesa_visual.screen = visinfo->screen;
1581#endif
1582
1583#if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
1584   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
1585#else
1586   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
1587#endif
1588
1589   v->mesa_visual.visualRating = visualCaveat;
1590
1591   (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 );
1592
1593   {
1594      const int xclass = v->mesa_visual.visualType;
1595      if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
1596         red_bits   = _mesa_bitcount(GET_REDMASK(v));
1597         green_bits = _mesa_bitcount(GET_GREENMASK(v));
1598         blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
1599         alpha_bits = 0;
1600      }
1601      else {
1602         /* this is an approximation */
1603         int depth;
1604         depth = GET_VISUAL_DEPTH(v);
1605         red_bits = depth / 3;
1606         depth -= red_bits;
1607         green_bits = depth / 2;
1608         depth -= green_bits;
1609         blue_bits = depth;
1610         alpha_bits = 0;
1611         assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
1612      }
1613   }
1614
1615   if (alpha_flag && alpha_bits == 0)
1616      alpha_bits = 8;
1617
1618   _mesa_initialize_visual( &v->mesa_visual,
1619                            rgb_flag, db_flag, stereo_flag,
1620                            red_bits, green_bits,
1621                            blue_bits, alpha_bits,
1622                            v->mesa_visual.indexBits,
1623                            depth_size,
1624                            stencil_size,
1625                            accum_red_size, accum_green_size,
1626                            accum_blue_size, accum_alpha_size,
1627                            0 );
1628
1629   /* XXX minor hack */
1630   v->mesa_visual.level = level;
1631   return v;
1632}
1633
1634
1635void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v )
1636{
1637    v->display = dpy;
1638}
1639
1640
1641void XMesaDestroyVisual( XMesaVisual v )
1642{
1643#ifndef XFree86Server
1644   _mesa_free(v->visinfo);
1645#endif
1646   _mesa_free(v);
1647}
1648
1649
1650
1651/**
1652 * Create a new XMesaContext.
1653 * \param v  the XMesaVisual
1654 * \param share_list  another XMesaContext with which to share display
1655 *                    lists or NULL if no sharing is wanted.
1656 * \return an XMesaContext or NULL if error.
1657 */
1658XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
1659{
1660   static GLboolean firstTime = GL_TRUE;
1661   XMesaContext c;
1662   GLcontext *mesaCtx;
1663   struct dd_function_table functions;
1664   TNLcontext *tnl;
1665
1666   if (firstTime) {
1667      _glthread_INIT_MUTEX(_xmesa_lock);
1668      firstTime = GL_FALSE;
1669   }
1670
1671   /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
1672   c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
1673   if (!c)
1674      return NULL;
1675
1676   mesaCtx = &(c->mesa);
1677
1678   /* initialize with default driver functions, then plug in XMesa funcs */
1679   _mesa_init_driver_functions(&functions);
1680   xmesa_init_driver_functions(v, &functions);
1681   if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual,
1682                      share_list ? &(share_list->mesa) : (GLcontext *) NULL,
1683                      &functions, (void *) c)) {
1684      _mesa_free(c);
1685      return NULL;
1686   }
1687
1688   _mesa_enable_sw_extensions(mesaCtx);
1689   _mesa_enable_1_3_extensions(mesaCtx);
1690   _mesa_enable_1_4_extensions(mesaCtx);
1691   _mesa_enable_1_5_extensions(mesaCtx);
1692   _mesa_enable_2_0_extensions(mesaCtx);
1693#if ENABLE_EXT_texure_compression_s3tc
1694    if (c->Mesa_DXTn) {
1695       _mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc");
1696       _mesa_enable_extension(mesaCtx, "GL_S3_s3tc");
1697    }
1698    _mesa_enable_extension(mesaCtx, "GL_3DFX_texture_compression_FXT1");
1699#endif
1700#if ENABLE_EXT_timer_query
1701    _mesa_enable_extension(mesaCtx, "GL_EXT_timer_query");
1702#endif
1703
1704   /* finish up xmesa context initializations */
1705   c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
1706   c->xm_visual = v;
1707   c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
1708   c->display = v->display;
1709   c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
1710
1711   /* Initialize the software rasterizer and helper modules.
1712    */
1713   if (!_swrast_CreateContext( mesaCtx ) ||
1714       !_ac_CreateContext( mesaCtx ) ||
1715       !_tnl_CreateContext( mesaCtx ) ||
1716       !_swsetup_CreateContext( mesaCtx )) {
1717      _mesa_free_context_data(&c->mesa);
1718      _mesa_free(c);
1719      return NULL;
1720   }
1721
1722   /* tnl setup */
1723   tnl = TNL_CONTEXT(mesaCtx);
1724   tnl->Driver.RunPipeline = _tnl_run_pipeline;
1725   /* swrast setup */
1726   xmesa_register_swrast_functions( mesaCtx );
1727   _swsetup_Wakeup(mesaCtx);
1728
1729   return c;
1730}
1731
1732
1733
1734void XMesaDestroyContext( XMesaContext c )
1735{
1736   GLcontext *mesaCtx = &c->mesa;
1737#ifdef FX
1738   XMesaBuffer xmbuf = XMESA_BUFFER(mesaCtx->DrawBuffer);
1739
1740   if (xmbuf && xmbuf->FXctx)
1741      fxMesaDestroyContext(xmbuf->FXctx);
1742#endif
1743   _swsetup_DestroyContext( mesaCtx );
1744   _swrast_DestroyContext( mesaCtx );
1745   _tnl_DestroyContext( mesaCtx );
1746   _ac_DestroyContext( mesaCtx );
1747   _mesa_free_context_data( mesaCtx );
1748   _mesa_free( c );
1749}
1750
1751
1752
1753/*
1754 * XXX this isn't a public function!  It's a hack for the 3Dfx driver.
1755 * Create a new XMesaBuffer from an X window.
1756 * Input:  v - the XMesaVisual
1757 *         w - the window
1758 *         c - the context
1759 * Return:  new XMesaBuffer or NULL if error
1760 */
1761XMesaBuffer
1762XMesaCreateWindowBuffer2(XMesaVisual v, XMesaWindow w, XMesaContext c)
1763{
1764#ifndef XFree86Server
1765   XWindowAttributes attr;
1766#endif
1767#ifdef FX
1768   char *fxEnvVar;
1769#endif
1770   int client = 0;
1771   XMesaBuffer b;
1772   XMesaColormap cmap;
1773
1774   assert(v);
1775   (void) c;
1776
1777   /* Check that window depth matches visual depth */
1778#ifdef XFree86Server
1779   client = CLIENT_ID(((XMesaDrawable)w)->id);
1780
1781   if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
1782      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1783                    GET_VISUAL_DEPTH(v), ((XMesaDrawable) w)->depth);
1784      return NULL;
1785   }
1786#else
1787   XGetWindowAttributes( v->display, w, &attr );
1788
1789   if (GET_VISUAL_DEPTH(v) != attr.depth) {
1790      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1791                    GET_VISUAL_DEPTH(v), attr.depth);
1792      return NULL;
1793   }
1794#endif
1795
1796   /* Find colormap */
1797#ifdef XFree86Server
1798   cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1799#else
1800   if (attr.colormap) {
1801      cmap = attr.colormap;
1802   }
1803   else {
1804      _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
1805      /* this is weird, a window w/out a colormap!? */
1806      /* OK, let's just allocate a new one and hope for the best */
1807      cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1808   }
1809#endif
1810
1811   b = alloc_xmesa_buffer(v, WINDOW, cmap);
1812   if (!b) {
1813      return NULL;
1814   }
1815
1816   if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
1817                                      (XMesaDrawable) w, cmap )) {
1818      free_xmesa_buffer(client, b);
1819      return NULL;
1820   }
1821
1822#ifdef FX
1823   fxEnvVar = _mesa_getenv("MESA_GLX_FX");
1824   if (fxEnvVar) {
1825     if (fxEnvVar[0]!='d') {
1826       int attribs[100];
1827       int numAttribs = 0;
1828       int hw;
1829       if (v->mesa_visual.depthBits > 0) {
1830	 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
1831	 attribs[numAttribs++] = v->mesa_visual.depthBits;
1832       }
1833       if (v->mesa_visual.doubleBufferMode) {
1834	 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
1835       }
1836       if (v->mesa_visual.accumRedBits > 0) {
1837	 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
1838	 attribs[numAttribs++] = v->mesa_visual.accumRedBits;
1839       }
1840       if (v->mesa_visual.stencilBits > 0) {
1841         attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
1842         attribs[numAttribs++] = v->mesa_visual.stencilBits;
1843       }
1844       if (v->mesa_visual.alphaBits > 0) {
1845         attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
1846         attribs[numAttribs++] = v->mesa_visual.alphaBits;
1847       }
1848       if (1) {
1849         attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
1850         attribs[numAttribs++] = (int) &(c->mesa);
1851       }
1852       attribs[numAttribs++] = FXMESA_NONE;
1853
1854       /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
1855       hw = fxMesaSelectCurrentBoard(0);
1856
1857       /* if these fail, there's a new bug somewhere */
1858       ASSERT(b->mesa_buffer.Width > 0);
1859       ASSERT(b->mesa_buffer.Height > 0);
1860
1861       if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) {
1862         b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
1863                                            b->mesa_buffer.Height, attribs);
1864         if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) {
1865	   b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
1866	   if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) {
1867	     b->FXwindowHack = GL_TRUE;
1868	     FX_grSstControl(GR_CONTROL_DEACTIVATE);
1869	   }
1870           else {
1871	     b->FXwindowHack = GL_FALSE;
1872	   }
1873         }
1874       }
1875       else {
1876         if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1877	   b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
1878					  GR_REFRESH_75Hz, attribs);
1879         else
1880	   b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
1881                                              b->mesa_buffer.Height, attribs);
1882         b->FXisHackUsable = GL_FALSE;
1883         b->FXwindowHack = GL_FALSE;
1884       }
1885       /*
1886       fprintf(stderr,
1887               "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1888               hw, b->mesa_buffer.Width, b->mesa_buffer.Height,
1889	       b->FXisHackUsable, b->FXwindowHack);
1890       */
1891     }
1892   }
1893   else {
1894      _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n");
1895      _mesa_warning(NULL, "         you have not defined the MESA_GLX_FX env. var.\n");
1896      _mesa_warning(NULL, "         (check the README.3DFX file for more information).\n\n");
1897      _mesa_warning(NULL, "         you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1898   }
1899#endif
1900
1901   return b;
1902}
1903
1904
1905XMesaBuffer
1906XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
1907{
1908   return XMesaCreateWindowBuffer2( v, w, NULL );
1909}
1910
1911
1912/**
1913 * Create a new XMesaBuffer from an X pixmap.
1914 *
1915 * \param v    the XMesaVisual
1916 * \param p    the pixmap
1917 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1918 *             \c GLX_DIRECT_COLOR visual for the pixmap
1919 * \returns new XMesaBuffer or NULL if error
1920 */
1921XMesaBuffer
1922XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
1923{
1924   int client = 0;
1925   XMesaBuffer b;
1926
1927   assert(v);
1928
1929   b = alloc_xmesa_buffer(v, PIXMAP, cmap);
1930   if (!b) {
1931      return NULL;
1932   }
1933
1934#ifdef XFree86Server
1935   client = CLIENT_ID(((XMesaDrawable)p)->id);
1936#endif
1937
1938   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1939				     (XMesaDrawable) p, cmap)) {
1940      free_xmesa_buffer(client, b);
1941      return NULL;
1942   }
1943
1944   return b;
1945}
1946
1947
1948
1949XMesaBuffer
1950XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
1951                   unsigned int width, unsigned int height)
1952{
1953#ifdef XFree86Server
1954   return 0;
1955#else
1956   int client = 0;
1957   XMesaWindow root;
1958   XMesaDrawable drawable;  /* X Pixmap Drawable */
1959   XMesaBuffer b;
1960
1961   b = alloc_xmesa_buffer(v, PBUFFER, cmap);
1962   if (!b) {
1963      return NULL;
1964   }
1965
1966   /* allocate pixmap for front buffer */
1967   root = RootWindow( v->display, v->visinfo->screen );
1968   drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth );
1969
1970   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1971				     drawable, cmap)) {
1972      free_xmesa_buffer(client, b);
1973      return NULL;
1974   }
1975
1976   return b;
1977#endif
1978}
1979
1980
1981
1982/*
1983 * Deallocate an XMesaBuffer structure and all related info.
1984 */
1985void XMesaDestroyBuffer( XMesaBuffer b )
1986{
1987   int client = 0;
1988
1989#ifdef XFree86Server
1990   if (b->frontxrb->drawable)
1991       client = CLIENT_ID(b->frontxrb->drawable->id);
1992#endif
1993
1994   if (b->gc)  XMesaFreeGC( b->xm_visual->display, b->gc );
1995   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
1996   if (b->swapgc)  XMesaFreeGC( b->xm_visual->display, b->swapgc );
1997
1998   if (b->xm_visual->mesa_visual.doubleBufferMode)
1999   {
2000      if (b->backxrb->ximage) {
2001#if defined(USE_XSHM) && !defined(XFree86Server)
2002         if (b->shm) {
2003            XShmDetach( b->xm_visual->display, &b->shminfo );
2004            XDestroyImage( b->backxrb->ximage );
2005            shmdt( b->shminfo.shmaddr );
2006         }
2007         else
2008#endif
2009            XMesaDestroyImage( b->backxrb->ximage );
2010      }
2011      if (b->backxrb->pixmap) {
2012         XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
2013         if (b->xm_visual->hpcr_clear_flag) {
2014            XMesaFreePixmap( b->xm_visual->display,
2015                             b->xm_visual->hpcr_clear_pixmap );
2016            XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
2017         }
2018      }
2019   }
2020   if (b->rowimage) {
2021      _mesa_free( b->rowimage->data );
2022      b->rowimage->data = NULL;
2023      XMesaDestroyImage( b->rowimage );
2024   }
2025
2026   free_xmesa_buffer(client, b);
2027}
2028
2029
2030
2031/*
2032 * Bind buffer b to context c and make c the current rendering context.
2033 */
2034GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
2035{
2036   return XMesaMakeCurrent2( c, b, b );
2037}
2038
2039
2040/*
2041 * Bind buffer b to context c and make c the current rendering context.
2042 */
2043GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
2044                             XMesaBuffer readBuffer )
2045{
2046   if (c) {
2047      if (!drawBuffer || !readBuffer)
2048         return GL_FALSE;  /* must specify buffers! */
2049
2050#ifdef FX
2051      if (drawBuffer->FXctx) {
2052         fxMesaMakeCurrent(drawBuffer->FXctx);
2053
2054         c->xm_buffer = drawBuffer;
2055
2056         return GL_TRUE;
2057      }
2058#endif
2059      if (&(c->mesa) == _mesa_get_current_context()
2060          && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
2061          && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
2062          && ((XMesaBuffer) c->mesa.DrawBuffer)->wasCurrent) {
2063         /* same context and buffer, do nothing */
2064         return GL_TRUE;
2065      }
2066
2067      c->xm_buffer = drawBuffer;
2068
2069      /* Call this periodically to detect when the user has begun using
2070       * GL rendering from multiple threads.
2071       */
2072      _glapi_check_multithread();
2073
2074      _mesa_make_current(&(c->mesa),
2075                         &drawBuffer->mesa_buffer,
2076                         &readBuffer->mesa_buffer);
2077
2078      if (c->xm_visual->mesa_visual.rgbMode) {
2079         /*
2080          * Must recompute and set these pixel values because colormap
2081          * can be different for different windows.
2082          */
2083         c->clearpixel = xmesa_color_to_pixel( &c->mesa,
2084                                               c->clearcolor[0],
2085                                               c->clearcolor[1],
2086                                               c->clearcolor[2],
2087                                               c->clearcolor[3],
2088                                               c->xm_visual->undithered_pf);
2089         XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
2090      }
2091
2092      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2093      drawBuffer->wasCurrent = GL_TRUE;
2094   }
2095   else {
2096      /* Detach */
2097      _mesa_make_current( NULL, NULL, NULL );
2098   }
2099   return GL_TRUE;
2100}
2101
2102
2103/*
2104 * Unbind the context c from its buffer.
2105 */
2106GLboolean XMesaUnbindContext( XMesaContext c )
2107{
2108   /* A no-op for XFree86 integration purposes */
2109   return GL_TRUE;
2110}
2111
2112
2113XMesaContext XMesaGetCurrentContext( void )
2114{
2115   GET_CURRENT_CONTEXT(ctx);
2116   if (ctx) {
2117      XMesaContext xmesa = XMESA_CONTEXT(ctx);
2118      return xmesa;
2119   }
2120   else {
2121      return 0;
2122   }
2123}
2124
2125
2126XMesaBuffer XMesaGetCurrentBuffer( void )
2127{
2128   GET_CURRENT_CONTEXT(ctx);
2129   if (ctx) {
2130      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2131      return xmbuf;
2132   }
2133   else {
2134      return 0;
2135   }
2136}
2137
2138
2139/* New in Mesa 3.1 */
2140XMesaBuffer XMesaGetCurrentReadBuffer( void )
2141{
2142   GET_CURRENT_CONTEXT(ctx);
2143   if (ctx) {
2144      return (XMesaBuffer) (ctx->ReadBuffer);
2145   }
2146   else {
2147      return 0;
2148   }
2149}
2150
2151
2152GLboolean XMesaForceCurrent(XMesaContext c)
2153{
2154   if (c) {
2155      if (&(c->mesa) != _mesa_get_current_context()) {
2156	 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
2157      }
2158   }
2159   else {
2160      _mesa_make_current(NULL, NULL, NULL);
2161   }
2162   return GL_TRUE;
2163}
2164
2165
2166GLboolean XMesaLoseCurrent(XMesaContext c)
2167{
2168   (void) c;
2169   _mesa_make_current(NULL, NULL, NULL);
2170   return GL_TRUE;
2171}
2172
2173
2174/*
2175 * Switch 3Dfx support hack between window and full-screen mode.
2176 */
2177GLboolean XMesaSetFXmode( GLint mode )
2178{
2179#ifdef FX
2180   const char *fx = _mesa_getenv("MESA_GLX_FX");
2181   if (fx && fx[0] != 'd') {
2182      GET_CURRENT_CONTEXT(ctx);
2183      GrHwConfiguration hw;
2184      if (!FX_grSstQueryHardware(&hw)) {
2185         /*fprintf(stderr, "!grSstQueryHardware\n");*/
2186         return GL_FALSE;
2187      }
2188      if (hw.num_sst < 1) {
2189         /*fprintf(stderr, "hw.num_sst < 1\n");*/
2190         return GL_FALSE;
2191      }
2192      if (ctx) {
2193         /* [dBorca] Hack alert:
2194	  * oh, this is sooo wrong: ctx above is
2195	  * really an fxMesaContext, not an XMesaContext
2196	  */
2197         XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2198         if (mode == XMESA_FX_WINDOW) {
2199	    if (xmbuf->FXisHackUsable) {
2200	       FX_grSstControl(GR_CONTROL_DEACTIVATE);
2201	       xmbuf->FXwindowHack = GL_TRUE;
2202	       return GL_TRUE;
2203	    }
2204	 }
2205	 else if (mode == XMESA_FX_FULLSCREEN) {
2206	    FX_grSstControl(GR_CONTROL_ACTIVATE);
2207	    xmbuf->FXwindowHack = GL_FALSE;
2208	    return GL_TRUE;
2209	 }
2210	 else {
2211	    /* Error: Bad mode value */
2212	 }
2213      }
2214   }
2215   /*fprintf(stderr, "fallthrough\n");*/
2216#else
2217   (void) mode;
2218#endif
2219   return GL_FALSE;
2220}
2221
2222
2223
2224#ifdef FX
2225/*
2226 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2227 */
2228static void FXgetImage( XMesaBuffer b )
2229{
2230   GET_CURRENT_CONTEXT(ctx);
2231   static unsigned short pixbuf[MAX_WIDTH];
2232   GLuint x, y;
2233   int xpos, ypos;
2234   XMesaWindow root;
2235   unsigned int bw, depth, width, height;
2236   XMesaContext xmesa = XMESA_CONTEXT(ctx);
2237
2238#ifdef XFree86Server
2239   x = b->frontxrb->pixmap->x;
2240   y = b->frontxrb->pixmap->y;
2241   width = b->frontxrb->pixmap->width;
2242   height = b->frontxrb->pixmap->height;
2243   depth = b->frontxrb->pixmap->depth;
2244#else
2245   XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap,
2246                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2247#endif
2248   if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) {
2249      b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width);
2250      b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height);
2251      if (b->mesa_buffer.Width & 1)
2252         b->mesa_buffer.Width--;  /* prevent odd width */
2253      xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height);
2254   }
2255
2256   /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
2257   /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
2258   if (b->xm_visual->undithered_pf==PF_5R6G5B) {
2259      /* Special case: 16bpp RGB */
2260      grLfbReadRegion( GR_BUFFER_FRONTBUFFER,       /* src buffer */
2261                       0, b->FXctx->height - b->mesa_buffer.Height,  /*pos*/
2262                       b->mesa_buffer.Width, b->mesa_buffer.Height,  /* size */
2263                       b->mesa_buffer.Width * sizeof(GLushort), /* stride */
2264                       b->backxrb->ximage->data);         /* dest buffer */
2265   }
2266   else if (b->xm_visual->dithered_pf==PF_Dither
2267	    && GET_VISUAL_DEPTH(b->xm_visual)==8) {
2268      /* Special case: 8bpp RGB */
2269      for (y=0;y<b->mesa_buffer.Height;y++) {
2270         GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data
2271                        + b->backxrb->ximage->bytes_per_line * y;
2272         XDITHER_SETUP(y);
2273
2274         /* read row from 3Dfx frame buffer */
2275         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2276                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2277                          b->mesa_buffer.Width, 1,
2278                          0,
2279                          pixbuf );
2280
2281         /* write to XImage back buffer */
2282         for (x=0;x<b->mesa_buffer.Width;x++) {
2283            GLubyte r = (pixbuf[x] & 0xf800) >> 8;
2284            GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
2285            GLubyte b = (pixbuf[x] & 0x001f) << 3;
2286            *ptr++ = XDITHER( x, r, g, b);
2287         }
2288      }
2289   }
2290   else {
2291      /* General case: slow! */
2292      for (y=0;y<b->mesa_buffer.Height;y++) {
2293         /* read row from 3Dfx frame buffer */
2294         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2295                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2296                          b->mesa_buffer.Width, 1,
2297                          0,
2298                          pixbuf );
2299
2300         /* write to XImage back buffer */
2301         for (x=0;x<b->mesa_buffer.Width;x++) {
2302            XMesaPutPixel(b->backxrb->ximage,x,y,
2303			  xmesa_color_to_pixel(ctx,
2304					       (pixbuf[x] & 0xf800) >> 8,
2305					       (pixbuf[x] & 0x07e0) >> 3,
2306					       (pixbuf[x] & 0x001f) << 3,
2307					       0xff,
2308                                               b->xm_visual->undithered_pf));
2309         }
2310      }
2311   }
2312   /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
2313}
2314#endif
2315
2316
2317/*
2318 * Copy the back buffer to the front buffer.  If there's no back buffer
2319 * this is a no-op.
2320 */
2321void XMesaSwapBuffers( XMesaBuffer b )
2322{
2323   GET_CURRENT_CONTEXT(ctx);
2324
2325   if (!b->backxrb) {
2326      /* single buffered */
2327      return;
2328   }
2329
2330   /* If we're swapping the buffer associated with the current context
2331    * we have to flush any pending rendering commands first.
2332    */
2333   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2334      _mesa_notifySwapBuffers(ctx);
2335
2336   if (b->db_mode) {
2337#ifdef FX
2338      if (b->FXctx) {
2339         fxMesaSwapBuffers();
2340
2341         if (b->FXwindowHack)
2342            FXgetImage(b);
2343         else
2344            return;
2345      }
2346#endif
2347     if (b->backxrb->ximage) {
2348	 /* Copy Ximage from host's memory to server's window */
2349#if defined(USE_XSHM) && !defined(XFree86Server)
2350	 if (b->shm) {
2351            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2352	    XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2353			  b->swapgc,
2354			  b->backxrb->ximage, 0, 0,
2355			  0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2356                          False );
2357            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2358	 }
2359	 else
2360#endif
2361         {
2362            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2363            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2364			   b->swapgc,
2365			   b->backxrb->ximage, 0, 0,
2366			   0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
2367            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2368         }
2369      }
2370      else {
2371	 /* Copy pixmap to window on server */
2372         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2373	 XMesaCopyArea( b->xm_visual->display,
2374			b->backxrb->pixmap,   /* source drawable */
2375			b->frontxrb->drawable,  /* dest. drawable */
2376			b->swapgc,
2377			0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2378			0, 0                 /* dest region */
2379		      );
2380         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2381      }
2382   }
2383#if !defined(XFree86Server)
2384   XSync( b->xm_visual->display, False );
2385#endif
2386}
2387
2388
2389
2390/*
2391 * Copy sub-region of back buffer to front buffer
2392 */
2393void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2394{
2395   GET_CURRENT_CONTEXT(ctx);
2396
2397   /* If we're swapping the buffer associated with the current context
2398    * we have to flush any pending rendering commands first.
2399    */
2400   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2401      _mesa_notifySwapBuffers(ctx);
2402
2403   if (!b->backxrb) {
2404      /* single buffered */
2405      return;
2406   }
2407
2408   if (b->db_mode) {
2409      int yTop = b->mesa_buffer.Height - y - height;
2410#ifdef FX
2411      if (b->FXctx) {
2412         fxMesaSwapBuffers();
2413         if (b->FXwindowHack)
2414            FXgetImage(b);
2415         else
2416            return;
2417      }
2418#endif
2419      if (b->backxrb->ximage) {
2420         /* Copy Ximage from host's memory to server's window */
2421#if defined(USE_XSHM) && !defined(XFree86Server)
2422         if (b->shm) {
2423            /* XXX assuming width and height aren't too large! */
2424            XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2425                          b->swapgc,
2426                          b->backxrb->ximage, x, yTop,
2427                          x, yTop, width, height, False );
2428            /* wait for finished event??? */
2429         }
2430         else
2431#endif
2432         {
2433            /* XXX assuming width and height aren't too large! */
2434            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2435			   b->swapgc,
2436			   b->backxrb->ximage, x, yTop,
2437			   x, yTop, width, height );
2438         }
2439      }
2440      else {
2441         /* Copy pixmap to window on server */
2442         XMesaCopyArea( b->xm_visual->display,
2443			b->backxrb->pixmap,           /* source drawable */
2444			b->frontxrb->drawable,        /* dest. drawable */
2445			b->swapgc,
2446			x, yTop, width, height,  /* source region */
2447			x, yTop                  /* dest region */
2448                      );
2449      }
2450   }
2451}
2452
2453
2454/*
2455 * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
2456 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2457 * back buffer directly.
2458 * Output:  pixmap - pointer to back buffer's Pixmap, or 0
2459 *          ximage - pointer to back buffer's XImage, or NULL
2460 * Return:  GL_TRUE = context is double buffered
2461 *          GL_FALSE = context is single buffered
2462 */
2463#ifndef XFree86Server
2464GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2465                              XMesaPixmap *pixmap,
2466                              XMesaImage **ximage )
2467{
2468   if (b->db_mode) {
2469      if (pixmap)
2470         *pixmap = b->backxrb->pixmap;
2471      if (ximage)
2472         *ximage = b->backxrb->ximage;
2473      return GL_TRUE;
2474   }
2475   else {
2476      *pixmap = 0;
2477      *ximage = NULL;
2478      return GL_FALSE;
2479   }
2480}
2481#endif /* XFree86Server */
2482
2483
2484/*
2485 * Return the depth buffer associated with an XMesaBuffer.
2486 * Input:  b - the XMesa buffer handle
2487 * Output:  width, height - size of buffer in pixels
2488 *          bytesPerValue - bytes per depth value (2 or 4)
2489 *          buffer - pointer to depth buffer values
2490 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
2491 */
2492GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2493                               GLint *bytesPerValue, void **buffer )
2494{
2495   struct gl_renderbuffer *rb
2496      = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
2497   if (!rb || !rb->Data) {
2498      *width = 0;
2499      *height = 0;
2500      *bytesPerValue = 0;
2501      *buffer = 0;
2502      return GL_FALSE;
2503   }
2504   else {
2505      *width = b->mesa_buffer.Width;
2506      *height = b->mesa_buffer.Height;
2507      *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
2508         ? sizeof(GLushort) : sizeof(GLuint);
2509      *buffer = rb->Data;
2510      return GL_TRUE;
2511   }
2512}
2513
2514
2515void XMesaFlush( XMesaContext c )
2516{
2517   if (c && c->xm_visual) {
2518#ifdef XFree86Server
2519      /* NOT_NEEDED */
2520#else
2521      XSync( c->xm_visual->display, False );
2522#endif
2523   }
2524}
2525
2526
2527
2528const char *XMesaGetString( XMesaContext c, int name )
2529{
2530   (void) c;
2531   if (name==XMESA_VERSION) {
2532      return "5.0";
2533   }
2534   else if (name==XMESA_EXTENSIONS) {
2535      return "";
2536   }
2537   else {
2538      return NULL;
2539   }
2540}
2541
2542
2543
2544XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2545{
2546   XMesaBuffer b;
2547   for (b=XMesaBufferList; b; b=b->Next) {
2548      if (b->frontxrb->drawable == d && b->display == dpy) {
2549         return b;
2550      }
2551   }
2552   return NULL;
2553}
2554
2555
2556/**
2557 * Free/destroy all XMesaBuffers associated with given display.
2558 */
2559void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
2560{
2561   XMesaBuffer b, next;
2562   for (b = XMesaBufferList; b; b = next) {
2563      next = b->Next;
2564      if (b->display == dpy) {
2565         free_xmesa_buffer(0, b);
2566      }
2567   }
2568}
2569
2570
2571/*
2572 * Look for XMesaBuffers whose X window has been destroyed.
2573 * Deallocate any such XMesaBuffers.
2574 */
2575void XMesaGarbageCollect( void )
2576{
2577   XMesaBuffer b, next;
2578   for (b=XMesaBufferList; b; b=next) {
2579      next = b->Next;
2580      if (b->display && b->frontxrb->drawable && b->type == WINDOW) {
2581#ifdef XFree86Server
2582	 /* NOT_NEEDED */
2583#else
2584         XSync(b->display, False);
2585         if (!window_exists( b->display, b->frontxrb->drawable )) {
2586            /* found a dead window, free the ancillary info */
2587            XMesaDestroyBuffer( b );
2588         }
2589#endif
2590      }
2591   }
2592}
2593
2594
2595void XMesaReset( void )
2596{
2597    while (XMesaBufferList)
2598	XMesaDestroyBuffer(XMesaBufferList);
2599
2600    XMesaBufferList = NULL;
2601}
2602
2603
2604unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2605                                GLfloat red, GLfloat green,
2606                                GLfloat blue, GLfloat alpha )
2607{
2608   GLcontext *ctx = &xmesa->mesa;
2609   GLint r = (GLint) (red   * 255.0F);
2610   GLint g = (GLint) (green * 255.0F);
2611   GLint b = (GLint) (blue  * 255.0F);
2612   GLint a = (GLint) (alpha * 255.0F);
2613
2614   switch (xmesa->pixelformat) {
2615      case PF_Index:
2616         return 0;
2617      case PF_Truecolor:
2618         {
2619            unsigned long p;
2620            PACK_TRUECOLOR( p, r, g, b );
2621            return p;
2622         }
2623      case PF_8A8B8G8R:
2624         return PACK_8A8B8G8R( r, g, b, a );
2625      case PF_8A8R8G8B:
2626         return PACK_8A8R8G8B( r, g, b, a );
2627      case PF_8R8G8B:
2628         return PACK_8R8G8B( r, g, b );
2629      case PF_5R6G5B:
2630         return PACK_5R6G5B( r, g, b );
2631      case PF_Dither:
2632         {
2633            DITHER_SETUP;
2634            return DITHER( x, y, r, g, b );
2635         }
2636      case PF_1Bit:
2637         /* 382 = (3*255)/2 */
2638         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2639      case PF_HPCR:
2640         return DITHER_HPCR(x, y, r, g, b);
2641      case PF_Lookup:
2642         {
2643            LOOKUP_SETUP;
2644            return LOOKUP( r, g, b );
2645         }
2646      case PF_Grayscale:
2647         return GRAY_RGB( r, g, b );
2648      case PF_Dither_5R6G5B:
2649         /* fall through */
2650      case PF_Dither_True:
2651         {
2652            unsigned long p;
2653            PACK_TRUEDITHER(p, x, y, r, g, b);
2654            return p;
2655         }
2656      default:
2657         _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2658   }
2659   return 0;
2660}
2661
2662
2663/*
2664 * This is typically called when the window size changes and we need
2665 * to reallocate the buffer's back/depth/stencil/accum buffers.
2666 */
2667void XMesaResizeBuffers( XMesaBuffer b )
2668{
2669#ifdef XFree86Server
2670   GLuint winwidth, winheight;
2671   GET_CURRENT_CONTEXT(ctx);
2672
2673   winwidth = MIN2(b->frontxrb->drawable->width, MAX_WIDTH);
2674   winheight = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT);
2675
2676   xmesa_resize_buffers(ctx, &(b->mesa_buffer), winwidth, winheight);
2677#else
2678   Window root;
2679   int xpos, ypos;
2680   unsigned int width, height, bw, depth;
2681   GET_CURRENT_CONTEXT(ctx);
2682   XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap,
2683                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2684   xmesa_resize_buffers(ctx, &(b->mesa_buffer), width, height);
2685#endif
2686}
2687
2688