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