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