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