xm_api.c revision 99f13343cf270d8dfde8445ae363d9b05256e05b
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5
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 */
199static int check_for_xshm( XMesaDisplay *display )
200{
201#if defined(XFree86Server)
202   return 0;
203#elif defined(USE_XSHM)
204   int major, minor, ignore;
205   Bool pixmaps;
206
207   if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
208      if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
209	 return (pixmaps==True) ? 2 : 1;
210      }
211      else {
212	 return 0;
213      }
214   }
215   else {
216      return 0;
217   }
218#else
219   /* No  XSHM support */
220   return 0;
221#endif
222}
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      GLboolean swAlpha;
344
345      b->display = vis->display;
346      b->xm_visual = vis;
347      b->type = type;
348      b->cmap = cmap;
349
350      _mesa_initialize_framebuffer(&b->mesa_buffer, &vis->mesa_visual);
351
352      /* Allocate the framebuffer's renderbuffers */
353      assert(!b->mesa_buffer.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
354      assert(!b->mesa_buffer.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
355
356      /* front renderbuffer */
357      b->frontxrb = xmesa_new_renderbuffer(NULL, 0, vis->mesa_visual.rgbMode,
358                                           GL_FALSE);
359      _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_FRONT_LEFT,
360                             &b->frontxrb->Base);
361
362      /* back renderbuffer */
363      if (vis->mesa_visual.doubleBufferMode) {
364         b->backxrb = xmesa_new_renderbuffer(NULL, 0,
365                                             vis->mesa_visual.rgbMode,
366                                             GL_TRUE);
367         /* determine back buffer implementation */
368         b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP;
369
370         _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_BACK_LEFT,
371                                &b->backxrb->Base);
372      }
373
374      /* determine if we need software alpha planes */
375      if (vis->mesa_visual.alphaBits > 0
376          && vis->undithered_pf != PF_8A8B8G8R
377          && vis->undithered_pf != PF_8A8R8G8B) {
378         /* Visual has alpha, but pixel format doesn't support it.
379          * We'll use an alpha renderbuffer wrapper.
380          */
381         swAlpha = GL_TRUE;
382      }
383      else {
384         swAlpha = GL_FALSE;
385      }
386
387      _mesa_add_soft_renderbuffers(&b->mesa_buffer,
388                                   GL_FALSE,  /* color */
389                                   vis->mesa_visual.haveDepthBuffer,
390                                   vis->mesa_visual.haveStencilBuffer,
391                                   vis->mesa_visual.haveAccumBuffer,
392                                   swAlpha,
393                                   vis->mesa_visual.numAuxBuffers > 0 );
394
395      /* insert into linked list */
396      b->Next = XMesaBufferList;
397      XMesaBufferList = b;
398   }
399   return b;
400}
401
402
403/*
404 * Find an XMesaBuffer by matching X display and colormap but NOT matching
405 * the notThis buffer.
406 */
407static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy,
408                                     XMesaColormap cmap,
409                                     XMesaBuffer notThis)
410{
411   XMesaBuffer b;
412   for (b=XMesaBufferList; b; b=b->Next) {
413      if (b->display==dpy && b->cmap==cmap && b!=notThis) {
414         return b;
415      }
416   }
417   return NULL;
418}
419
420
421/*
422 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
423 * entries.
424 */
425static void free_xmesa_buffer(int client, XMesaBuffer buffer)
426{
427   XMesaBuffer prev = NULL, b;
428   (void) client;
429   for (b=XMesaBufferList; b; b=b->Next) {
430      if (b==buffer) {
431         /* unlink bufer from list */
432         if (prev)
433            prev->Next = buffer->Next;
434         else
435            XMesaBufferList = buffer->Next;
436         /* Check to free X colors */
437         if (buffer->num_alloced>0) {
438            /* If no other buffer uses this X colormap then free the colors. */
439            if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) {
440#ifdef XFree86Server
441               (void)FreeColors(buffer->cmap, client,
442				buffer->num_alloced, buffer->alloced_colors,
443				0);
444#else
445               XFreeColors(buffer->display, buffer->cmap,
446                           buffer->alloced_colors, buffer->num_alloced, 0);
447#endif
448            }
449         }
450
451         _mesa_free_framebuffer_data(&buffer->mesa_buffer);
452         _mesa_free(buffer);
453
454         return;
455      }
456      /* continue search */
457      prev = b;
458   }
459   /* buffer not found in XMesaBufferList */
460   _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n");
461}
462
463
464/* Copy X color table stuff from one XMesaBuffer to another. */
465static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src)
466{
467   MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table));
468   MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r));
469   MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g));
470   MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b));
471   dst->num_alloced = src->num_alloced;
472   MEMCPY(dst->alloced_colors, src->alloced_colors,
473          sizeof(src->alloced_colors));
474}
475
476
477
478/**********************************************************************/
479/*****                   Misc Private Functions                   *****/
480/**********************************************************************/
481
482
483/**
484 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
485 * Return:  GL_TRUE if success, GL_FALSE if error
486 */
487#ifndef XFree86Server
488static GLboolean
489alloc_shm_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
490{
491#ifdef USE_XSHM
492   /*
493    * We have to do a _lot_ of error checking here to be sure we can
494    * really use the XSHM extension.  It seems different servers trigger
495    * errors at different points if the extension won't work.  Therefore
496    * we have to be very careful...
497    */
498   GC gc;
499   int (*old_handler)( XMesaDisplay *, XErrorEvent * );
500
501   if (width == 0 || height == 0) {
502      /* this will be true the first time we're called on 'b' */
503      return GL_FALSE;
504   }
505
506   b->backxrb->ximage = XShmCreateImage(b->xm_visual->display,
507                                        b->xm_visual->visinfo->visual,
508                                        b->xm_visual->visinfo->depth,
509                                        ZPixmap, NULL, &b->shminfo,
510                                        width, height);
511   if (b->backxrb->ximage == NULL) {
512      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.\n");
513      b->shm = 0;
514      return GL_FALSE;
515   }
516
517   b->shminfo.shmid = shmget( IPC_PRIVATE, b->backxrb->ximage->bytes_per_line
518			     * b->backxrb->ximage->height, IPC_CREAT|0777 );
519   if (b->shminfo.shmid < 0) {
520      _mesa_warning(NULL, "shmget failed while allocating back buffer.\n");
521      XDestroyImage( b->backxrb->ximage );
522      b->backxrb->ximage = NULL;
523      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.\n");
524      b->shm = 0;
525      return GL_FALSE;
526   }
527
528   b->shminfo.shmaddr = b->backxrb->ximage->data
529                      = (char*)shmat( b->shminfo.shmid, 0, 0 );
530   if (b->shminfo.shmaddr == (char *) -1) {
531      _mesa_warning(NULL, "shmat() failed while allocating back buffer.\n");
532      XDestroyImage( b->backxrb->ximage );
533      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
534      b->backxrb->ximage = NULL;
535      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.\n");
536      b->shm = 0;
537      return GL_FALSE;
538   }
539
540   b->shminfo.readOnly = False;
541   mesaXErrorFlag = 0;
542   old_handler = XSetErrorHandler( mesaHandleXError );
543   /* This may trigger the X protocol error we're ready to catch: */
544   XShmAttach( b->xm_visual->display, &b->shminfo );
545   XSync( b->xm_visual->display, False );
546
547   if (mesaXErrorFlag) {
548      /* we are on a remote display, this error is normal, don't print it */
549      XFlush( b->xm_visual->display );
550      mesaXErrorFlag = 0;
551      XDestroyImage( b->backxrb->ximage );
552      shmdt( b->shminfo.shmaddr );
553      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
554      b->backxrb->ximage = NULL;
555      b->shm = 0;
556      (void) XSetErrorHandler( old_handler );
557      return GL_FALSE;
558   }
559
560   shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */
561
562   /* Finally, try an XShmPutImage to be really sure the extension works */
563   gc = XCreateGC( b->xm_visual->display, b->frontxrb->drawable, 0, NULL );
564   XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, gc,
565		 b->backxrb->ximage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False );
566   XSync( b->xm_visual->display, False );
567   XFreeGC( b->xm_visual->display, gc );
568   (void) XSetErrorHandler( old_handler );
569   if (mesaXErrorFlag) {
570      XFlush( b->xm_visual->display );
571      mesaXErrorFlag = 0;
572      XDestroyImage( b->backxrb->ximage );
573      shmdt( b->shminfo.shmaddr );
574      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
575      b->backxrb->ximage = NULL;
576      b->shm = 0;
577      return GL_FALSE;
578   }
579
580   return GL_TRUE;
581#else
582   /* Can't compile XSHM support */
583   return GL_FALSE;
584#endif
585}
586#endif
587
588
589
590
591/*
592 * Setup an off-screen pixmap or Ximage to use as the back buffer.
593 * Input:  b - the X/Mesa buffer
594 */
595void
596xmesa_alloc_back_buffer( XMesaBuffer b, GLuint width, GLuint height )
597{
598   if (width == 0 || height == 0)
599      return;
600
601   if (b->db_mode == BACK_XIMAGE) {
602      /* Deallocate the old backxrb->ximage, if any */
603      if (b->backxrb->ximage) {
604#if defined(USE_XSHM) && !defined(XFree86Server)
605	 if (b->shm) {
606	    XShmDetach( b->xm_visual->display, &b->shminfo );
607	    XDestroyImage( b->backxrb->ximage );
608	    shmdt( b->shminfo.shmaddr );
609	 }
610	 else
611#endif
612	   XMesaDestroyImage( b->backxrb->ximage );
613	 b->backxrb->ximage = NULL;
614      }
615
616      /* Allocate new back buffer */
617#ifdef XFree86Server
618      /* Allocate a regular XImage for the back buffer. */
619      b->backxrb->ximage = XMesaCreateImage(b->xm_visual->BitsPerPixel,
620                                            width, height, NULL);
621      {
622#else
623      if (b->shm == 0 || !alloc_shm_back_buffer(b, width, height)) {
624	 /* Allocate a regular XImage for the back buffer. */
625	 b->backxrb->ximage = XCreateImage( b->xm_visual->display,
626                                      b->xm_visual->visinfo->visual,
627                                      GET_VISUAL_DEPTH(b->xm_visual),
628				      ZPixmap, 0,   /* format, offset */
629				      NULL,
630                                      width, height,
631				      8, 0 );  /* pad, bytes_per_line */
632#endif
633	 if (!b->backxrb->ximage) {
634	    _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.\n");
635            return;
636	 }
637         b->backxrb->ximage->data = (char *) MALLOC( b->backxrb->ximage->height
638                                        * b->backxrb->ximage->bytes_per_line );
639         if (!b->backxrb->ximage->data) {
640            _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.\n");
641            XMesaDestroyImage( b->backxrb->ximage );
642            b->backxrb->ximage = NULL;
643         }
644         else {
645            /* this call just updates the width/origin fields in the xrb */
646            b->backxrb->Base.AllocStorage(NULL, &b->backxrb->Base,
647                                          b->backxrb->Base.InternalFormat,
648                                          b->backxrb->ximage->width,
649                                          b->backxrb->ximage->height);
650         }
651      }
652      b->backxrb->pixmap = None;
653   }
654   else if (b->db_mode == 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,
666                                              b->frontxrb->drawable,
667                                              width, height,
668                                              GET_VISUAL_DEPTH(b->xm_visual) );
669      b->backxrb->ximage = NULL;
670   }
671}
672
673
674
675/*
676 * A replacement for XAllocColor.  This function should never
677 * fail to allocate a color.  When XAllocColor fails, we return
678 * the nearest matching color.  If we have to allocate many colors
679 * this function isn't too efficient; the XQueryColors() could be
680 * done just once.
681 * Written by Michael Pichler, Brian Paul, Mark Kilgard
682 * Input:  dpy - X display
683 *         cmap - X colormap
684 *         cmapSize - size of colormap
685 * In/Out: color - the XColor struct
686 * Output:  exact - 1=exact color match, 0=closest match
687 *          alloced - 1=XAlloc worked, 0=XAlloc failed
688 */
689static void
690noFaultXAllocColor( int client,
691                    XMesaDisplay *dpy,
692                    XMesaColormap cmap,
693                    int cmapSize,
694                    XMesaColor *color,
695                    int *exact, int *alloced )
696{
697#ifdef XFree86Server
698   Pixel *ppixIn;
699   xrgb *ctable;
700#else
701   /* we'll try to cache ctable for better remote display performance */
702   static Display *prevDisplay = NULL;
703   static XMesaColormap prevCmap = 0;
704   static int prevCmapSize = 0;
705   static XMesaColor *ctable = NULL;
706#endif
707   XMesaColor subColor;
708   int i, bestmatch;
709   double mindist;       /* 3*2^16^2 exceeds long int precision. */
710
711   (void) client;
712
713   /* First try just using XAllocColor. */
714#ifdef XFree86Server
715   if (AllocColor(cmap,
716		  &color->red, &color->green, &color->blue,
717		  &color->pixel,
718		  client) == Success) {
719#else
720   if (XAllocColor(dpy, cmap, color)) {
721#endif
722      *exact = 1;
723      *alloced = 1;
724      return;
725   }
726
727   /* Alloc failed, search for closest match */
728
729   /* Retrieve color table entries. */
730   /* XXX alloca candidate. */
731#ifdef XFree86Server
732   ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel));
733   ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb));
734   for (i = 0; i < cmapSize; i++) {
735      ppixIn[i] = i;
736   }
737   QueryColors(cmap, cmapSize, ppixIn, ctable);
738#else
739   if (prevDisplay != dpy || prevCmap != cmap
740       || prevCmapSize != cmapSize || !ctable) {
741      /* free previously cached color table */
742      if (ctable)
743         _mesa_free(ctable);
744      /* Get the color table from X */
745      ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor));
746      assert(ctable);
747      for (i = 0; i < cmapSize; i++) {
748         ctable[i].pixel = i;
749      }
750      XQueryColors(dpy, cmap, ctable, cmapSize);
751      prevDisplay = dpy;
752      prevCmap = cmap;
753      prevCmapSize = cmapSize;
754   }
755#endif
756
757   /* Find best match. */
758   bestmatch = -1;
759   mindist = 0.0;
760   for (i = 0; i < cmapSize; i++) {
761      double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
762      double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
763      double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
764      double dist = dr * dr + dg * dg + db * db;
765      if (bestmatch < 0 || dist < mindist) {
766         bestmatch = i;
767         mindist = dist;
768      }
769   }
770
771   /* Return result. */
772   subColor.red   = ctable[bestmatch].red;
773   subColor.green = ctable[bestmatch].green;
774   subColor.blue  = ctable[bestmatch].blue;
775   /* Try to allocate the closest match color.  This should only
776    * fail if the cell is read/write.  Otherwise, we're incrementing
777    * the cell's reference count.
778    */
779#ifdef XFree86Server
780   if (AllocColor(cmap,
781		  &subColor.red, &subColor.green, &subColor.blue,
782		  &subColor.pixel,
783		  client) == Success) {
784#else
785   if (XAllocColor(dpy, cmap, &subColor)) {
786#endif
787      *alloced = 1;
788   }
789   else {
790      /* do this to work around a problem reported by Frank Ortega */
791      subColor.pixel = (unsigned long) bestmatch;
792      subColor.red   = ctable[bestmatch].red;
793      subColor.green = ctable[bestmatch].green;
794      subColor.blue  = ctable[bestmatch].blue;
795      subColor.flags = DoRed | DoGreen | DoBlue;
796      *alloced = 0;
797   }
798#ifdef XFree86Server
799   _mesa_free(ppixIn);
800   _mesa_free(ctable);
801#else
802   /* don't free table, save it for next time */
803#endif
804
805   *color = subColor;
806   *exact = 0;
807}
808
809
810
811
812/*
813 * Do setup for PF_GRAYSCALE pixel format.
814 * Note that buffer may be NULL.
815 */
816static GLboolean setup_grayscale( int client, XMesaVisual v,
817                                  XMesaBuffer buffer, XMesaColormap cmap )
818{
819   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
820      return GL_FALSE;
821   }
822
823   if (buffer) {
824      XMesaBuffer prevBuffer;
825
826      if (!cmap) {
827         return GL_FALSE;
828      }
829
830      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
831      if (prevBuffer &&
832          (buffer->xm_visual->mesa_visual.rgbMode ==
833           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
834         /* Copy colormap stuff from previous XMesaBuffer which uses same
835          * X colormap.  Do this to avoid time spent in noFaultXAllocColor.
836          */
837         copy_colortable_info(buffer, prevBuffer);
838      }
839      else {
840         /* Allocate 256 shades of gray */
841         int gray;
842         int colorsfailed = 0;
843         for (gray=0;gray<256;gray++) {
844            GLint r = gamma_adjust( v->RedGamma,   gray, 255 );
845            GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
846            GLint b = gamma_adjust( v->BlueGamma,  gray, 255 );
847            int exact, alloced;
848            XMesaColor xcol;
849            xcol.red   = (r << 8) | r;
850            xcol.green = (g << 8) | g;
851            xcol.blue  = (b << 8) | b;
852            noFaultXAllocColor( client, v->display,
853                                cmap, GET_COLORMAP_SIZE(v),
854                                &xcol, &exact, &alloced );
855            if (!exact) {
856               colorsfailed++;
857            }
858            if (alloced) {
859               assert(buffer->num_alloced<256);
860               buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
861               buffer->num_alloced++;
862            }
863
864            /*OLD
865            assert(gray < 576);
866            buffer->color_table[gray*3+0] = xcol.pixel;
867            buffer->color_table[gray*3+1] = xcol.pixel;
868            buffer->color_table[gray*3+2] = xcol.pixel;
869            assert(xcol.pixel < 65536);
870            buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
871            buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
872            buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
873            */
874            buffer->color_table[gray] = xcol.pixel;
875            assert(xcol.pixel < 65536);
876            buffer->pixel_to_r[xcol.pixel] = gray;
877            buffer->pixel_to_g[xcol.pixel] = gray;
878            buffer->pixel_to_b[xcol.pixel] = gray;
879         }
880
881         if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
882            _mesa_warning(NULL,
883                  "Note: %d out of 256 needed colors do not match exactly.\n",
884                  colorsfailed );
885         }
886      }
887   }
888
889   v->dithered_pf = PF_Grayscale;
890   v->undithered_pf = PF_Grayscale;
891   return GL_TRUE;
892}
893
894
895
896/*
897 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
898 * or 8-bit TrueColor visual visual.  We try to allocate a palette of 225
899 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
900 * color.  While this function was originally designed just for 8-bit
901 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
902 * Dithering code contributed by Bob Mercier.
903 */
904static GLboolean setup_dithered_color( int client, XMesaVisual v,
905                                       XMesaBuffer buffer, XMesaColormap cmap )
906{
907   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
908      return GL_FALSE;
909   }
910
911   if (buffer) {
912      XMesaBuffer prevBuffer;
913
914      if (!cmap) {
915         return GL_FALSE;
916      }
917
918      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
919      if (prevBuffer &&
920          (buffer->xm_visual->mesa_visual.rgbMode ==
921           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
922         /* Copy colormap stuff from previous, matching XMesaBuffer.
923          * Do this to avoid time spent in noFaultXAllocColor.
924          */
925         copy_colortable_info(buffer, prevBuffer);
926      }
927      else {
928         /* Allocate X colors and initialize color_table[], red_table[], etc */
929         int r, g, b, i;
930         int colorsfailed = 0;
931         for (r = 0; r < DITH_R; r++) {
932            for (g = 0; g < DITH_G; g++) {
933               for (b = 0; b < DITH_B; b++) {
934                  XMesaColor xcol;
935                  int exact, alloced;
936                  xcol.red  =gamma_adjust(v->RedGamma,   r*65535/(DITH_R-1),65535);
937                  xcol.green=gamma_adjust(v->GreenGamma, g*65535/(DITH_G-1),65535);
938                  xcol.blue =gamma_adjust(v->BlueGamma,  b*65535/(DITH_B-1),65535);
939                  noFaultXAllocColor( client, v->display,
940                                      cmap, GET_COLORMAP_SIZE(v),
941                                      &xcol, &exact, &alloced );
942                  if (!exact) {
943                     colorsfailed++;
944                  }
945                  if (alloced) {
946                     assert(buffer->num_alloced<256);
947                     buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
948                     buffer->num_alloced++;
949                  }
950                  i = DITH_MIX( r, g, b );
951                  assert(i < 576);
952                  buffer->color_table[i] = xcol.pixel;
953                  assert(xcol.pixel < 65536);
954                  buffer->pixel_to_r[xcol.pixel] = r * 255 / (DITH_R-1);
955                  buffer->pixel_to_g[xcol.pixel] = g * 255 / (DITH_G-1);
956                  buffer->pixel_to_b[xcol.pixel] = b * 255 / (DITH_B-1);
957               }
958            }
959         }
960
961         if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
962            _mesa_warning(NULL,
963                  "Note: %d out of %d needed colors do not match exactly.\n",
964                  colorsfailed, DITH_R * DITH_G * DITH_B );
965         }
966      }
967   }
968
969   v->dithered_pf = PF_Dither;
970   v->undithered_pf = PF_Lookup;
971   return GL_TRUE;
972}
973
974
975/*
976 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
977 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
978 * Special dithering tables have to be initialized.
979 */
980static void setup_8bit_hpcr( XMesaVisual v )
981{
982   /* HP Color Recovery contributed by:  Alex De Bruyn (ad@lms.be)
983    * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
984    * on the root window AND the colormap obtainable by XGetRGBColormaps
985    * for that atom must be set on the window.  (see also tkInitWindow)
986    * If that colormap is not set, the output will look stripy.
987    */
988
989   /* Setup color tables with gamma correction */
990   int i;
991   double g;
992
993   g = 1.0 / v->RedGamma;
994   for (i=0; i<256; i++) {
995      GLint red = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[0][i]/255.0, g ));
996      v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 );
997   }
998
999   g = 1.0 / v->GreenGamma;
1000   for (i=0; i<256; i++) {
1001      GLint green = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[1][i]/255.0, g ));
1002      v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 );
1003   }
1004
1005   g = 1.0 / v->BlueGamma;
1006   for (i=0; i<256; i++) {
1007      GLint blue = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[2][i]/255.0, g ));
1008      v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 );
1009   }
1010   v->undithered_pf = PF_HPCR;  /* can't really disable dithering for now */
1011   v->dithered_pf = PF_HPCR;
1012
1013   /* which method should I use to clear */
1014   /* GL_FALSE: keep the ordinary method  */
1015   /* GL_TRUE : clear with dither pattern */
1016   v->hpcr_clear_flag = _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE;
1017
1018   if (v->hpcr_clear_flag) {
1019      v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display,
1020                                               DefaultRootWindow(v->display),
1021                                               16, 2, 8);
1022#ifndef XFree86Server
1023      v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap,
1024                                       0, 0, 16, 2, AllPlanes, ZPixmap);
1025#endif
1026   }
1027}
1028
1029
1030/*
1031 * Setup RGB rendering for a window with a True/DirectColor visual.
1032 */
1033static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer,
1034                             XMesaColormap cmap )
1035{
1036   unsigned long rmask, gmask, bmask;
1037   (void) buffer;
1038   (void) cmap;
1039
1040   /* Compute red multiplier (mask) and bit shift */
1041   v->rshift = 0;
1042   rmask = GET_REDMASK(v);
1043   while ((rmask & 1)==0) {
1044      v->rshift++;
1045      rmask = rmask >> 1;
1046   }
1047
1048   /* Compute green multiplier (mask) and bit shift */
1049   v->gshift = 0;
1050   gmask = GET_GREENMASK(v);
1051   while ((gmask & 1)==0) {
1052      v->gshift++;
1053      gmask = gmask >> 1;
1054   }
1055
1056   /* Compute blue multiplier (mask) and bit shift */
1057   v->bshift = 0;
1058   bmask = GET_BLUEMASK(v);
1059   while ((bmask & 1)==0) {
1060      v->bshift++;
1061      bmask = bmask >> 1;
1062   }
1063
1064   /*
1065    * Compute component-to-pixel lookup tables and dithering kernel
1066    */
1067   {
1068      static GLubyte kernel[16] = {
1069          0*16,  8*16,  2*16, 10*16,
1070         12*16,  4*16, 14*16,  6*16,
1071          3*16, 11*16,  1*16,  9*16,
1072         15*16,  7*16, 13*16,  5*16,
1073      };
1074      GLint rBits = _mesa_bitcount(rmask);
1075      GLint gBits = _mesa_bitcount(gmask);
1076      GLint bBits = _mesa_bitcount(bmask);
1077      GLint maxBits;
1078      GLuint i;
1079
1080      /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1081      for (i=0; i<=rmask; i++)
1082         v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
1083      for (i=0; i<=gmask; i++)
1084         v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
1085      for (i=0; i<=bmask; i++)
1086         v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
1087
1088      /* convert RGB values from [0,255] to pixel components */
1089
1090      for (i=0;i<256;i++) {
1091         GLint r = gamma_adjust(v->RedGamma,   i, 255);
1092         GLint g = gamma_adjust(v->GreenGamma, i, 255);
1093         GLint b = gamma_adjust(v->BlueGamma,  i, 255);
1094         v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
1095         v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
1096         v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
1097      }
1098      /* overflow protection */
1099      for (i=256;i<512;i++) {
1100         v->RtoPixel[i] = v->RtoPixel[255];
1101         v->GtoPixel[i] = v->GtoPixel[255];
1102         v->BtoPixel[i] = v->BtoPixel[255];
1103      }
1104
1105      /* setup dithering kernel */
1106      maxBits = rBits;
1107      if (gBits > maxBits)  maxBits = gBits;
1108      if (bBits > maxBits)  maxBits = bBits;
1109      for (i=0;i<16;i++) {
1110         v->Kernel[i] = kernel[i] >> maxBits;
1111      }
1112
1113      v->undithered_pf = PF_Truecolor;
1114      v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor;
1115   }
1116
1117   /*
1118    * Now check for TrueColor visuals which we can optimize.
1119    */
1120   if (   GET_REDMASK(v)  ==0x0000ff
1121       && GET_GREENMASK(v)==0x00ff00
1122       && GET_BLUEMASK(v) ==0xff0000
1123       && CHECK_BYTE_ORDER(v)
1124       && v->BitsPerPixel==32
1125       && sizeof(GLuint)==4
1126       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1127      /* common 32 bpp config used on SGI, Sun */
1128      v->undithered_pf = v->dithered_pf = PF_8A8B8G8R;
1129   }
1130   else if (GET_REDMASK(v)  ==0xff0000
1131       &&   GET_GREENMASK(v)==0x00ff00
1132       &&   GET_BLUEMASK(v) ==0x0000ff
1133       && CHECK_BYTE_ORDER(v)
1134       && v->BitsPerPixel==32
1135       && sizeof(GLuint)==4
1136       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1137      /* common 32 bpp config used on Linux, HP, IBM */
1138      if (GET_VISUAL_DEPTH(v)==32)
1139	  v->undithered_pf = v->dithered_pf = PF_8A8R8G8B;
1140      else
1141	  v->undithered_pf = v->dithered_pf = PF_8R8G8B;
1142   }
1143   else if (GET_REDMASK(v)  ==0xff0000
1144       &&   GET_GREENMASK(v)==0x00ff00
1145       &&   GET_BLUEMASK(v) ==0x0000ff
1146       && CHECK_BYTE_ORDER(v)
1147       && v->BitsPerPixel==24
1148       && sizeof(GLuint)==4
1149       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1150      /* common packed 24 bpp config used on Linux */
1151      v->undithered_pf = v->dithered_pf = PF_8R8G8B24;
1152   }
1153   else if (GET_REDMASK(v)  ==0xf800
1154       &&   GET_GREENMASK(v)==0x07e0
1155       &&   GET_BLUEMASK(v) ==0x001f
1156       && CHECK_BYTE_ORDER(v)
1157       && v->BitsPerPixel==16
1158       && sizeof(GLushort)==2
1159       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1160      /* 5-6-5 color weight on common PC VGA boards */
1161      v->undithered_pf = PF_5R6G5B;
1162      v->dithered_pf = PF_Dither_5R6G5B;
1163   }
1164   else if (GET_REDMASK(v)  ==0xe0
1165       &&   GET_GREENMASK(v)==0x1c
1166       &&   GET_BLUEMASK(v) ==0x03
1167       && CHECK_FOR_HPCR(v)) {
1168      setup_8bit_hpcr( v );
1169   }
1170}
1171
1172
1173
1174/*
1175 * Setup RGB rendering for a window with a monochrome visual.
1176 */
1177static void setup_monochrome( XMesaVisual v, XMesaBuffer b )
1178{
1179   (void) b;
1180   v->dithered_pf = v->undithered_pf = PF_1Bit;
1181   /* if black=1 then we must flip pixel values */
1182   v->bitFlip = (GET_BLACK_PIXEL(v) != 0);
1183}
1184
1185
1186
1187/*
1188 * When a context is "made current" for the first time, we can finally
1189 * finish initializing the context's visual and buffer information.
1190 * Input:  v - the XMesaVisual to initialize
1191 *         b - the XMesaBuffer to initialize (may be NULL)
1192 *         rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1193 *         window - the window/pixmap we're rendering into
1194 *         cmap - the colormap associated with the window/pixmap
1195 * Return:  GL_TRUE=success, GL_FALSE=failure
1196 */
1197static GLboolean initialize_visual_and_buffer( int client,
1198                                               XMesaVisual v,
1199                                               XMesaBuffer b,
1200                                               GLboolean rgb_flag,
1201                                               XMesaDrawable window,
1202                                               XMesaColormap cmap )
1203{
1204   struct xmesa_renderbuffer *front_xrb, *back_xrb;
1205#ifndef XFree86Server
1206   XGCValues gcvalues;
1207#endif
1208
1209   if (b) {
1210      assert(b->xm_visual == v);
1211   }
1212
1213   if (b) {
1214      front_xrb = b->frontxrb;
1215      back_xrb = b->backxrb;
1216   }
1217   else {
1218      front_xrb = back_xrb = NULL;
1219   }
1220
1221   /* Save true bits/pixel */
1222   v->BitsPerPixel = bits_per_pixel(v);
1223   assert(v->BitsPerPixel > 0);
1224
1225
1226   if (rgb_flag==GL_FALSE) {
1227      /* COLOR-INDEXED WINDOW:
1228       * Even if the visual is TrueColor or DirectColor we treat it as
1229       * being color indexed.  This is weird but might be useful to someone.
1230       */
1231      v->dithered_pf = v->undithered_pf = PF_Index;
1232      v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v);
1233   }
1234   else {
1235      /* RGB WINDOW:
1236       * We support RGB rendering into almost any kind of visual.
1237       */
1238      const int xclass = v->mesa_visual.visualType;
1239      if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
1240	 setup_truecolor( v, b, cmap );
1241      }
1242      else if (xclass==GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v)==1) {
1243	 setup_monochrome( v, b );
1244      }
1245      else if (xclass==GLX_GRAY_SCALE || xclass==GLX_STATIC_GRAY) {
1246         if (!setup_grayscale( client, v, b, cmap )) {
1247            return GL_FALSE;
1248         }
1249      }
1250      else if ((xclass==GLX_PSEUDO_COLOR || xclass==GLX_STATIC_COLOR)
1251               && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
1252	 if (!setup_dithered_color( client, v, b, cmap )) {
1253            return GL_FALSE;
1254         }
1255      }
1256      else {
1257	 _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n");
1258	 return GL_FALSE;
1259      }
1260      v->mesa_visual.indexBits = 0;
1261
1262      if (_mesa_getenv("MESA_NO_DITHER")) {
1263	 v->dithered_pf = v->undithered_pf;
1264      }
1265   }
1266
1267
1268   /*
1269    * If MESA_INFO env var is set print out some debugging info
1270    * which can help Brian figure out what's going on when a user
1271    * reports bugs.
1272    */
1273   if (_mesa_getenv("MESA_INFO")) {
1274      _mesa_printf("X/Mesa visual = %p\n", (void *) v);
1275      _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf);
1276      _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf);
1277      _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
1278      _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
1279      _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
1280   }
1281
1282   if (b && window) {
1283      /* Do window-specific initializations */
1284
1285      b->frontxrb->drawable = window;
1286      b->frontxrb->pixmap = (XMesaPixmap) window;
1287
1288      /* Setup for single/double buffering */
1289      if (v->mesa_visual.doubleBufferMode) {
1290         /* Double buffered */
1291         b->shm = check_for_xshm( v->display );
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   = _mesa_bitcount(GET_REDMASK(v));
1596         green_bits = _mesa_bitcount(GET_GREENMASK(v));
1597         blue_bits  = _mesa_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 ENABLE_EXT_texure_compression_s3tc
1693    if (c->Mesa_DXTn) {
1694       _mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc");
1695       _mesa_enable_extension(mesaCtx, "GL_S3_s3tc");
1696    }
1697    _mesa_enable_extension(mesaCtx, "GL_3DFX_texture_compression_FXT1");
1698#endif
1699#if ENABLE_EXT_timer_query
1700    _mesa_enable_extension(mesaCtx, "GL_EXT_timer_query");
1701#endif
1702
1703   /* finish up xmesa context initializations */
1704   c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
1705   c->xm_visual = v;
1706   c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
1707   c->display = v->display;
1708   c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
1709
1710   /* Initialize the software rasterizer and helper modules.
1711    */
1712   if (!_swrast_CreateContext( mesaCtx ) ||
1713       !_ac_CreateContext( mesaCtx ) ||
1714       !_tnl_CreateContext( mesaCtx ) ||
1715       !_swsetup_CreateContext( mesaCtx )) {
1716      _mesa_free_context_data(&c->mesa);
1717      _mesa_free(c);
1718      return NULL;
1719   }
1720
1721   /* tnl setup */
1722   tnl = TNL_CONTEXT(mesaCtx);
1723   tnl->Driver.RunPipeline = _tnl_run_pipeline;
1724   /* swrast setup */
1725   xmesa_register_swrast_functions( mesaCtx );
1726   _swsetup_Wakeup(mesaCtx);
1727
1728   return c;
1729}
1730
1731
1732
1733void XMesaDestroyContext( XMesaContext c )
1734{
1735   GLcontext *mesaCtx = &c->mesa;
1736#ifdef FX
1737   XMesaBuffer xmbuf = XMESA_BUFFER(mesaCtx->DrawBuffer);
1738
1739   if (xmbuf && xmbuf->FXctx)
1740      fxMesaDestroyContext(xmbuf->FXctx);
1741#endif
1742   _swsetup_DestroyContext( mesaCtx );
1743   _swrast_DestroyContext( mesaCtx );
1744   _tnl_DestroyContext( mesaCtx );
1745   _ac_DestroyContext( mesaCtx );
1746   _mesa_free_context_data( mesaCtx );
1747   _mesa_free( c );
1748}
1749
1750
1751
1752/*
1753 * XXX this isn't a public function!  It's a hack for the 3Dfx driver.
1754 * Create a new XMesaBuffer from an X window.
1755 * Input:  v - the XMesaVisual
1756 *         w - the window
1757 *         c - the context
1758 * Return:  new XMesaBuffer or NULL if error
1759 */
1760XMesaBuffer
1761XMesaCreateWindowBuffer2(XMesaVisual v, XMesaWindow w, XMesaContext c)
1762{
1763#ifndef XFree86Server
1764   XWindowAttributes attr;
1765#endif
1766#ifdef FX
1767   char *fxEnvVar;
1768#endif
1769   int client = 0;
1770   XMesaBuffer b;
1771   XMesaColormap cmap;
1772
1773   assert(v);
1774   (void) c;
1775
1776   /* Check that window depth matches visual depth */
1777#ifdef XFree86Server
1778   client = CLIENT_ID(((XMesaDrawable)w)->id);
1779
1780   if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
1781      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1782                    GET_VISUAL_DEPTH(v), ((XMesaDrawable) w)->depth);
1783      return NULL;
1784   }
1785#else
1786   XGetWindowAttributes( v->display, w, &attr );
1787
1788   if (GET_VISUAL_DEPTH(v) != attr.depth) {
1789      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1790                    GET_VISUAL_DEPTH(v), attr.depth);
1791      return NULL;
1792   }
1793#endif
1794
1795   /* Find colormap */
1796#ifdef XFree86Server
1797   cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1798#else
1799   if (attr.colormap) {
1800      cmap = attr.colormap;
1801   }
1802   else {
1803      _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
1804      /* this is weird, a window w/out a colormap!? */
1805      /* OK, let's just allocate a new one and hope for the best */
1806      cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1807   }
1808#endif
1809
1810   b = alloc_xmesa_buffer(v, WINDOW, cmap);
1811   if (!b) {
1812      return NULL;
1813   }
1814
1815   if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
1816                                      (XMesaDrawable) w, cmap )) {
1817      free_xmesa_buffer(client, b);
1818      return NULL;
1819   }
1820
1821#ifdef FX
1822   fxEnvVar = _mesa_getenv("MESA_GLX_FX");
1823   if (fxEnvVar) {
1824     if (fxEnvVar[0]!='d') {
1825       int attribs[100];
1826       int numAttribs = 0;
1827       int hw;
1828       if (v->mesa_visual.depthBits > 0) {
1829	 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
1830	 attribs[numAttribs++] = v->mesa_visual.depthBits;
1831       }
1832       if (v->mesa_visual.doubleBufferMode) {
1833	 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
1834       }
1835       if (v->mesa_visual.accumRedBits > 0) {
1836	 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
1837	 attribs[numAttribs++] = v->mesa_visual.accumRedBits;
1838       }
1839       if (v->mesa_visual.stencilBits > 0) {
1840         attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
1841         attribs[numAttribs++] = v->mesa_visual.stencilBits;
1842       }
1843       if (v->mesa_visual.alphaBits > 0) {
1844         attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
1845         attribs[numAttribs++] = v->mesa_visual.alphaBits;
1846       }
1847       if (1) {
1848         attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
1849         attribs[numAttribs++] = (int) &(c->mesa);
1850       }
1851       attribs[numAttribs++] = FXMESA_NONE;
1852
1853       /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
1854       hw = fxMesaSelectCurrentBoard(0);
1855
1856       /* if these fail, there's a new bug somewhere */
1857       ASSERT(b->mesa_buffer.Width > 0);
1858       ASSERT(b->mesa_buffer.Height > 0);
1859
1860       if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) {
1861         b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
1862                                            b->mesa_buffer.Height, attribs);
1863         if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) {
1864	   b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
1865	   if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) {
1866	     b->FXwindowHack = GL_TRUE;
1867	     FX_grSstControl(GR_CONTROL_DEACTIVATE);
1868	   }
1869           else {
1870	     b->FXwindowHack = GL_FALSE;
1871	   }
1872         }
1873       }
1874       else {
1875         if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1876	   b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
1877					  GR_REFRESH_75Hz, attribs);
1878         else
1879	   b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
1880                                              b->mesa_buffer.Height, attribs);
1881         b->FXisHackUsable = GL_FALSE;
1882         b->FXwindowHack = GL_FALSE;
1883       }
1884       /*
1885       fprintf(stderr,
1886               "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1887               hw, b->mesa_buffer.Width, b->mesa_buffer.Height,
1888	       b->FXisHackUsable, b->FXwindowHack);
1889       */
1890     }
1891   }
1892   else {
1893      _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n");
1894      _mesa_warning(NULL, "         you have not defined the MESA_GLX_FX env. var.\n");
1895      _mesa_warning(NULL, "         (check the README.3DFX file for more information).\n\n");
1896      _mesa_warning(NULL, "         you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1897   }
1898#endif
1899
1900   return b;
1901}
1902
1903
1904XMesaBuffer
1905XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
1906{
1907   return XMesaCreateWindowBuffer2( v, w, NULL );
1908}
1909
1910
1911/**
1912 * Create a new XMesaBuffer from an X pixmap.
1913 *
1914 * \param v    the XMesaVisual
1915 * \param p    the pixmap
1916 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1917 *             \c GLX_DIRECT_COLOR visual for the pixmap
1918 * \returns new XMesaBuffer or NULL if error
1919 */
1920XMesaBuffer
1921XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
1922{
1923   int client = 0;
1924   XMesaBuffer b;
1925
1926   assert(v);
1927
1928   b = alloc_xmesa_buffer(v, PIXMAP, cmap);
1929   if (!b) {
1930      return NULL;
1931   }
1932
1933#ifdef XFree86Server
1934   client = CLIENT_ID(((XMesaDrawable)p)->id);
1935#endif
1936
1937   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1938				     (XMesaDrawable) p, cmap)) {
1939      free_xmesa_buffer(client, b);
1940      return NULL;
1941   }
1942
1943   return b;
1944}
1945
1946
1947
1948XMesaBuffer
1949XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
1950                   unsigned int width, unsigned int height)
1951{
1952#ifdef XFree86Server
1953   return 0;
1954#else
1955   int client = 0;
1956   XMesaWindow root;
1957   XMesaDrawable drawable;  /* X Pixmap Drawable */
1958   XMesaBuffer b;
1959
1960   b = alloc_xmesa_buffer(v, PBUFFER, cmap);
1961   if (!b) {
1962      return NULL;
1963   }
1964
1965   /* allocate pixmap for front buffer */
1966   root = RootWindow( v->display, v->visinfo->screen );
1967   drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth );
1968
1969   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1970				     drawable, cmap)) {
1971      free_xmesa_buffer(client, b);
1972      return NULL;
1973   }
1974
1975   return b;
1976#endif
1977}
1978
1979
1980
1981/*
1982 * Deallocate an XMesaBuffer structure and all related info.
1983 */
1984void XMesaDestroyBuffer( XMesaBuffer b )
1985{
1986   int client = 0;
1987
1988#ifdef XFree86Server
1989   if (b->frontxrb->drawable)
1990       client = CLIENT_ID(b->frontxrb->drawable->id);
1991#endif
1992
1993   if (b->gc)  XMesaFreeGC( b->xm_visual->display, b->gc );
1994   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
1995   if (b->swapgc)  XMesaFreeGC( b->xm_visual->display, b->swapgc );
1996
1997   if (b->xm_visual->mesa_visual.doubleBufferMode)
1998   {
1999      if (b->backxrb->ximage) {
2000#if defined(USE_XSHM) && !defined(XFree86Server)
2001         if (b->shm) {
2002            XShmDetach( b->xm_visual->display, &b->shminfo );
2003            XDestroyImage( b->backxrb->ximage );
2004            shmdt( b->shminfo.shmaddr );
2005         }
2006         else
2007#endif
2008            XMesaDestroyImage( b->backxrb->ximage );
2009      }
2010      if (b->backxrb->pixmap) {
2011         XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
2012         if (b->xm_visual->hpcr_clear_flag) {
2013            XMesaFreePixmap( b->xm_visual->display,
2014                             b->xm_visual->hpcr_clear_pixmap );
2015            XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
2016         }
2017      }
2018   }
2019   if (b->rowimage) {
2020      _mesa_free( b->rowimage->data );
2021      b->rowimage->data = NULL;
2022      XMesaDestroyImage( b->rowimage );
2023   }
2024
2025   free_xmesa_buffer(client, b);
2026}
2027
2028
2029
2030/*
2031 * Bind buffer b to context c and make c the current rendering context.
2032 */
2033GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
2034{
2035   return XMesaMakeCurrent2( c, b, b );
2036}
2037
2038
2039/*
2040 * Bind buffer b to context c and make c the current rendering context.
2041 */
2042GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
2043                             XMesaBuffer readBuffer )
2044{
2045   if (c) {
2046      if (!drawBuffer || !readBuffer)
2047         return GL_FALSE;  /* must specify buffers! */
2048
2049#ifdef FX
2050      if (drawBuffer->FXctx) {
2051         fxMesaMakeCurrent(drawBuffer->FXctx);
2052
2053         c->xm_buffer = drawBuffer;
2054
2055         return GL_TRUE;
2056      }
2057#endif
2058      if (&(c->mesa) == _mesa_get_current_context()
2059          && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
2060          && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
2061          && ((XMesaBuffer) c->mesa.DrawBuffer)->wasCurrent) {
2062         /* same context and buffer, do nothing */
2063         return GL_TRUE;
2064      }
2065
2066      c->xm_buffer = drawBuffer;
2067
2068      _mesa_make_current(&(c->mesa),
2069                         &drawBuffer->mesa_buffer,
2070                         &readBuffer->mesa_buffer);
2071
2072      if (c->xm_visual->mesa_visual.rgbMode) {
2073         /*
2074          * Must recompute and set these pixel values because colormap
2075          * can be different for different windows.
2076          */
2077         c->clearpixel = xmesa_color_to_pixel( &c->mesa,
2078                                               c->clearcolor[0],
2079                                               c->clearcolor[1],
2080                                               c->clearcolor[2],
2081                                               c->clearcolor[3],
2082                                               c->xm_visual->undithered_pf);
2083         XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
2084      }
2085
2086      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2087      drawBuffer->wasCurrent = GL_TRUE;
2088   }
2089   else {
2090      /* Detach */
2091      _mesa_make_current( NULL, NULL, NULL );
2092   }
2093   return GL_TRUE;
2094}
2095
2096
2097/*
2098 * Unbind the context c from its buffer.
2099 */
2100GLboolean XMesaUnbindContext( XMesaContext c )
2101{
2102   /* A no-op for XFree86 integration purposes */
2103   return GL_TRUE;
2104}
2105
2106
2107XMesaContext XMesaGetCurrentContext( void )
2108{
2109   GET_CURRENT_CONTEXT(ctx);
2110   if (ctx) {
2111      XMesaContext xmesa = XMESA_CONTEXT(ctx);
2112      return xmesa;
2113   }
2114   else {
2115      return 0;
2116   }
2117}
2118
2119
2120XMesaBuffer XMesaGetCurrentBuffer( void )
2121{
2122   GET_CURRENT_CONTEXT(ctx);
2123   if (ctx) {
2124      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2125      return xmbuf;
2126   }
2127   else {
2128      return 0;
2129   }
2130}
2131
2132
2133/* New in Mesa 3.1 */
2134XMesaBuffer XMesaGetCurrentReadBuffer( void )
2135{
2136   GET_CURRENT_CONTEXT(ctx);
2137   if (ctx) {
2138      return (XMesaBuffer) (ctx->ReadBuffer);
2139   }
2140   else {
2141      return 0;
2142   }
2143}
2144
2145
2146GLboolean XMesaForceCurrent(XMesaContext c)
2147{
2148   if (c) {
2149      if (&(c->mesa) != _mesa_get_current_context()) {
2150	 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
2151      }
2152   }
2153   else {
2154      _mesa_make_current(NULL, NULL, NULL);
2155   }
2156   return GL_TRUE;
2157}
2158
2159
2160GLboolean XMesaLoseCurrent(XMesaContext c)
2161{
2162   (void) c;
2163   _mesa_make_current(NULL, NULL, NULL);
2164   return GL_TRUE;
2165}
2166
2167
2168/*
2169 * Switch 3Dfx support hack between window and full-screen mode.
2170 */
2171GLboolean XMesaSetFXmode( GLint mode )
2172{
2173#ifdef FX
2174   const char *fx = _mesa_getenv("MESA_GLX_FX");
2175   if (fx && fx[0] != 'd') {
2176      GET_CURRENT_CONTEXT(ctx);
2177      GrHwConfiguration hw;
2178      if (!FX_grSstQueryHardware(&hw)) {
2179         /*fprintf(stderr, "!grSstQueryHardware\n");*/
2180         return GL_FALSE;
2181      }
2182      if (hw.num_sst < 1) {
2183         /*fprintf(stderr, "hw.num_sst < 1\n");*/
2184         return GL_FALSE;
2185      }
2186      if (ctx) {
2187         /* [dBorca] Hack alert:
2188	  * oh, this is sooo wrong: ctx above is
2189	  * really an fxMesaContext, not an XMesaContext
2190	  */
2191         XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2192         if (mode == XMESA_FX_WINDOW) {
2193	    if (xmbuf->FXisHackUsable) {
2194	       FX_grSstControl(GR_CONTROL_DEACTIVATE);
2195	       xmbuf->FXwindowHack = GL_TRUE;
2196	       return GL_TRUE;
2197	    }
2198	 }
2199	 else if (mode == XMESA_FX_FULLSCREEN) {
2200	    FX_grSstControl(GR_CONTROL_ACTIVATE);
2201	    xmbuf->FXwindowHack = GL_FALSE;
2202	    return GL_TRUE;
2203	 }
2204	 else {
2205	    /* Error: Bad mode value */
2206	 }
2207      }
2208   }
2209   /*fprintf(stderr, "fallthrough\n");*/
2210#else
2211   (void) mode;
2212#endif
2213   return GL_FALSE;
2214}
2215
2216
2217
2218#ifdef FX
2219/*
2220 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2221 */
2222static void FXgetImage( XMesaBuffer b )
2223{
2224   GET_CURRENT_CONTEXT(ctx);
2225   static unsigned short pixbuf[MAX_WIDTH];
2226   GLuint x, y;
2227   int xpos, ypos;
2228   XMesaWindow root;
2229   unsigned int bw, depth, width, height;
2230   XMesaContext xmesa = XMESA_CONTEXT(ctx);
2231
2232#ifdef XFree86Server
2233   x = b->frontxrb->pixmap->x;
2234   y = b->frontxrb->pixmap->y;
2235   width = b->frontxrb->pixmap->width;
2236   height = b->frontxrb->pixmap->height;
2237   depth = b->frontxrb->pixmap->depth;
2238#else
2239   XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap,
2240                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2241#endif
2242   if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) {
2243      b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width);
2244      b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height);
2245      if (b->mesa_buffer.Width & 1)
2246         b->mesa_buffer.Width--;  /* prevent odd width */
2247      xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height);
2248   }
2249
2250   /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
2251   /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
2252   if (b->xm_visual->undithered_pf==PF_5R6G5B) {
2253      /* Special case: 16bpp RGB */
2254      grLfbReadRegion( GR_BUFFER_FRONTBUFFER,       /* src buffer */
2255                       0, b->FXctx->height - b->mesa_buffer.Height,  /*pos*/
2256                       b->mesa_buffer.Width, b->mesa_buffer.Height,  /* size */
2257                       b->mesa_buffer.Width * sizeof(GLushort), /* stride */
2258                       b->backxrb->ximage->data);         /* dest buffer */
2259   }
2260   else if (b->xm_visual->dithered_pf==PF_Dither
2261	    && GET_VISUAL_DEPTH(b->xm_visual)==8) {
2262      /* Special case: 8bpp RGB */
2263      for (y=0;y<b->mesa_buffer.Height;y++) {
2264         GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data
2265                        + b->backxrb->ximage->bytes_per_line * y;
2266         XDITHER_SETUP(y);
2267
2268         /* read row from 3Dfx frame buffer */
2269         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2270                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2271                          b->mesa_buffer.Width, 1,
2272                          0,
2273                          pixbuf );
2274
2275         /* write to XImage back buffer */
2276         for (x=0;x<b->mesa_buffer.Width;x++) {
2277            GLubyte r = (pixbuf[x] & 0xf800) >> 8;
2278            GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
2279            GLubyte b = (pixbuf[x] & 0x001f) << 3;
2280            *ptr++ = XDITHER( x, r, g, b);
2281         }
2282      }
2283   }
2284   else {
2285      /* General case: slow! */
2286      for (y=0;y<b->mesa_buffer.Height;y++) {
2287         /* read row from 3Dfx frame buffer */
2288         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2289                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2290                          b->mesa_buffer.Width, 1,
2291                          0,
2292                          pixbuf );
2293
2294         /* write to XImage back buffer */
2295         for (x=0;x<b->mesa_buffer.Width;x++) {
2296            XMesaPutPixel(b->backxrb->ximage,x,y,
2297			  xmesa_color_to_pixel(ctx,
2298					       (pixbuf[x] & 0xf800) >> 8,
2299					       (pixbuf[x] & 0x07e0) >> 3,
2300					       (pixbuf[x] & 0x001f) << 3,
2301					       0xff,
2302                                               b->xm_visual->undithered_pf));
2303         }
2304      }
2305   }
2306   /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
2307}
2308#endif
2309
2310
2311/*
2312 * Copy the back buffer to the front buffer.  If there's no back buffer
2313 * this is a no-op.
2314 */
2315void XMesaSwapBuffers( XMesaBuffer b )
2316{
2317   GET_CURRENT_CONTEXT(ctx);
2318
2319   if (!b->backxrb) {
2320      /* single buffered */
2321      return;
2322   }
2323
2324   /* If we're swapping the buffer associated with the current context
2325    * we have to flush any pending rendering commands first.
2326    */
2327   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2328      _mesa_notifySwapBuffers(ctx);
2329
2330   if (b->db_mode) {
2331#ifdef FX
2332      if (b->FXctx) {
2333         fxMesaSwapBuffers();
2334
2335         if (b->FXwindowHack)
2336            FXgetImage(b);
2337         else
2338            return;
2339      }
2340#endif
2341     if (b->backxrb->ximage) {
2342	 /* Copy Ximage from host's memory to server's window */
2343#if defined(USE_XSHM) && !defined(XFree86Server)
2344	 if (b->shm) {
2345            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2346	    XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2347			  b->swapgc,
2348			  b->backxrb->ximage, 0, 0,
2349			  0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2350                          False );
2351            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2352	 }
2353	 else
2354#endif
2355         {
2356            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2357            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2358			   b->swapgc,
2359			   b->backxrb->ximage, 0, 0,
2360			   0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
2361            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2362         }
2363      }
2364      else {
2365	 /* Copy pixmap to window on server */
2366         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2367	 XMesaCopyArea( b->xm_visual->display,
2368			b->backxrb->pixmap,   /* source drawable */
2369			b->frontxrb->drawable,  /* dest. drawable */
2370			b->swapgc,
2371			0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2372			0, 0                 /* dest region */
2373		      );
2374         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2375      }
2376   }
2377#if !defined(XFree86Server)
2378   XSync( b->xm_visual->display, False );
2379#endif
2380}
2381
2382
2383
2384/*
2385 * Copy sub-region of back buffer to front buffer
2386 */
2387void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2388{
2389   GET_CURRENT_CONTEXT(ctx);
2390
2391   /* If we're swapping the buffer associated with the current context
2392    * we have to flush any pending rendering commands first.
2393    */
2394   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2395      _mesa_notifySwapBuffers(ctx);
2396
2397   if (!b->backxrb) {
2398      /* single buffered */
2399      return;
2400   }
2401
2402   if (b->db_mode) {
2403      int yTop = b->mesa_buffer.Height - y - height;
2404#ifdef FX
2405      if (b->FXctx) {
2406         fxMesaSwapBuffers();
2407         if (b->FXwindowHack)
2408            FXgetImage(b);
2409         else
2410            return;
2411      }
2412#endif
2413      if (b->backxrb->ximage) {
2414         /* Copy Ximage from host's memory to server's window */
2415#if defined(USE_XSHM) && !defined(XFree86Server)
2416         if (b->shm) {
2417            /* XXX assuming width and height aren't too large! */
2418            XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2419                          b->swapgc,
2420                          b->backxrb->ximage, x, yTop,
2421                          x, yTop, width, height, False );
2422            /* wait for finished event??? */
2423         }
2424         else
2425#endif
2426         {
2427            /* XXX assuming width and height aren't too large! */
2428            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2429			   b->swapgc,
2430			   b->backxrb->ximage, x, yTop,
2431			   x, yTop, width, height );
2432         }
2433      }
2434      else {
2435         /* Copy pixmap to window on server */
2436         XMesaCopyArea( b->xm_visual->display,
2437			b->backxrb->pixmap,           /* source drawable */
2438			b->frontxrb->drawable,        /* dest. drawable */
2439			b->swapgc,
2440			x, yTop, width, height,  /* source region */
2441			x, yTop                  /* dest region */
2442                      );
2443      }
2444   }
2445}
2446
2447
2448/*
2449 * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
2450 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2451 * back buffer directly.
2452 * Output:  pixmap - pointer to back buffer's Pixmap, or 0
2453 *          ximage - pointer to back buffer's XImage, or NULL
2454 * Return:  GL_TRUE = context is double buffered
2455 *          GL_FALSE = context is single buffered
2456 */
2457#ifndef XFree86Server
2458GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2459                              XMesaPixmap *pixmap,
2460                              XMesaImage **ximage )
2461{
2462   if (b->db_mode) {
2463      if (pixmap)
2464         *pixmap = b->backxrb->pixmap;
2465      if (ximage)
2466         *ximage = b->backxrb->ximage;
2467      return GL_TRUE;
2468   }
2469   else {
2470      *pixmap = 0;
2471      *ximage = NULL;
2472      return GL_FALSE;
2473   }
2474}
2475#endif /* XFree86Server */
2476
2477
2478/*
2479 * Return the depth buffer associated with an XMesaBuffer.
2480 * Input:  b - the XMesa buffer handle
2481 * Output:  width, height - size of buffer in pixels
2482 *          bytesPerValue - bytes per depth value (2 or 4)
2483 *          buffer - pointer to depth buffer values
2484 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
2485 */
2486GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2487                               GLint *bytesPerValue, void **buffer )
2488{
2489   struct gl_renderbuffer *rb
2490      = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
2491   if (!rb || !rb->Data) {
2492      *width = 0;
2493      *height = 0;
2494      *bytesPerValue = 0;
2495      *buffer = 0;
2496      return GL_FALSE;
2497   }
2498   else {
2499      *width = b->mesa_buffer.Width;
2500      *height = b->mesa_buffer.Height;
2501      *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
2502         ? sizeof(GLushort) : sizeof(GLuint);
2503      *buffer = rb->Data;
2504      return GL_TRUE;
2505   }
2506}
2507
2508
2509void XMesaFlush( XMesaContext c )
2510{
2511   if (c && c->xm_visual) {
2512#ifdef XFree86Server
2513      /* NOT_NEEDED */
2514#else
2515      XSync( c->xm_visual->display, False );
2516#endif
2517   }
2518}
2519
2520
2521
2522const char *XMesaGetString( XMesaContext c, int name )
2523{
2524   (void) c;
2525   if (name==XMESA_VERSION) {
2526      return "5.0";
2527   }
2528   else if (name==XMESA_EXTENSIONS) {
2529      return "";
2530   }
2531   else {
2532      return NULL;
2533   }
2534}
2535
2536
2537
2538XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2539{
2540   XMesaBuffer b;
2541   for (b=XMesaBufferList; b; b=b->Next) {
2542      if (b->frontxrb->drawable == d && b->display == dpy) {
2543         return b;
2544      }
2545   }
2546   return NULL;
2547}
2548
2549
2550
2551/*
2552 * Look for XMesaBuffers whose X window has been destroyed.
2553 * Deallocate any such XMesaBuffers.
2554 */
2555void XMesaGarbageCollect( void )
2556{
2557   XMesaBuffer b, next;
2558   for (b=XMesaBufferList; b; b=next) {
2559      next = b->Next;
2560      if (b->display && b->frontxrb->drawable && b->type == WINDOW) {
2561#ifdef XFree86Server
2562	 /* NOT_NEEDED */
2563#else
2564         XSync(b->display, False);
2565         if (!window_exists( b->display, b->frontxrb->drawable )) {
2566            /* found a dead window, free the ancillary info */
2567            XMesaDestroyBuffer( b );
2568         }
2569#endif
2570      }
2571   }
2572}
2573
2574
2575void XMesaReset( void )
2576{
2577    while (XMesaBufferList)
2578	XMesaDestroyBuffer(XMesaBufferList);
2579
2580    XMesaBufferList = NULL;
2581}
2582
2583
2584unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2585                                GLfloat red, GLfloat green,
2586                                GLfloat blue, GLfloat alpha )
2587{
2588   GLcontext *ctx = &xmesa->mesa;
2589   GLint r = (GLint) (red   * 255.0F);
2590   GLint g = (GLint) (green * 255.0F);
2591   GLint b = (GLint) (blue  * 255.0F);
2592   GLint a = (GLint) (alpha * 255.0F);
2593
2594   switch (xmesa->pixelformat) {
2595      case PF_Index:
2596         return 0;
2597      case PF_Truecolor:
2598         {
2599            unsigned long p;
2600            PACK_TRUECOLOR( p, r, g, b );
2601            return p;
2602         }
2603      case PF_8A8B8G8R:
2604         return PACK_8A8B8G8R( r, g, b, a );
2605      case PF_8A8R8G8B:
2606         return PACK_8A8R8G8B( r, g, b, a );
2607      case PF_8R8G8B:
2608         return PACK_8R8G8B( r, g, b );
2609      case PF_5R6G5B:
2610         return PACK_5R6G5B( r, g, b );
2611      case PF_Dither:
2612         {
2613            DITHER_SETUP;
2614            return DITHER( x, y, r, g, b );
2615         }
2616      case PF_1Bit:
2617         /* 382 = (3*255)/2 */
2618         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2619      case PF_HPCR:
2620         return DITHER_HPCR(x, y, r, g, b);
2621      case PF_Lookup:
2622         {
2623            LOOKUP_SETUP;
2624            return LOOKUP( r, g, b );
2625         }
2626      case PF_Grayscale:
2627         return GRAY_RGB( r, g, b );
2628      case PF_Dither_5R6G5B:
2629         /* fall through */
2630      case PF_Dither_True:
2631         {
2632            unsigned long p;
2633            PACK_TRUEDITHER(p, x, y, r, g, b);
2634            return p;
2635         }
2636      default:
2637         _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2638   }
2639   return 0;
2640}
2641
2642
2643/*
2644 * This is typically called when the window size changes and we need
2645 * to reallocate the buffer's back/depth/stencil/accum buffers.
2646 */
2647void XMesaResizeBuffers( XMesaBuffer b )
2648{
2649#ifdef XFree86Server
2650   GLuint winwidth, winheight;
2651   GET_CURRENT_CONTEXT(ctx);
2652
2653   winwidth = MIN2(b->frontxrb->drawable->width, MAX_WIDTH);
2654   winheight = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT);
2655
2656   xmesa_resize_buffers(ctx, &(b->mesa_buffer), winwidth, winheight);
2657#else
2658   Window root;
2659   int xpos, ypos;
2660   unsigned int width, height, bw, depth;
2661   GET_CURRENT_CONTEXT(ctx);
2662   XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap,
2663                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2664   xmesa_resize_buffers(ctx, &(b->mesa_buffer), width, height);
2665#endif
2666}
2667
2668