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