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