xm_api.c revision ad271b8c98021dc82c0714d768a6642aee10794f
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.");
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");
521      XDestroyImage( b->backxrb->ximage );
522      b->backxrb->ximage = NULL;
523      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.");
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");
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.");
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.");
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.");
641            XMesaDestroyImage( b->backxrb->ximage );
642            b->backxrb->ximage = NULL;
643         }
644         /* this call just updates the width/origin fields in the xrb */
645         b->backxrb->Base.AllocStorage(NULL, &b->backxrb->Base,
646                                       b->backxrb->Base.InternalFormat,
647                                       b->backxrb->ximage->width,
648                                       b->backxrb->ximage->height);
649      }
650      b->backxrb->pixmap = None;
651   }
652   else if (b->db_mode == BACK_PIXMAP) {
653      if (!width)
654         width = 1;
655      if (!height)
656         height = 1;
657
658      /* Free the old back pixmap */
659      if (b->backxrb->pixmap) {
660	 XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
661      }
662      /* Allocate new back pixmap */
663      b->backxrb->pixmap = XMesaCreatePixmap( b->xm_visual->display,
664                                              b->frontxrb->drawable,
665                                              width, height,
666                                              GET_VISUAL_DEPTH(b->xm_visual) );
667      b->backxrb->ximage = NULL;
668   }
669}
670
671
672
673/*
674 * A replacement for XAllocColor.  This function should never
675 * fail to allocate a color.  When XAllocColor fails, we return
676 * the nearest matching color.  If we have to allocate many colors
677 * this function isn't too efficient; the XQueryColors() could be
678 * done just once.
679 * Written by Michael Pichler, Brian Paul, Mark Kilgard
680 * Input:  dpy - X display
681 *         cmap - X colormap
682 *         cmapSize - size of colormap
683 * In/Out: color - the XColor struct
684 * Output:  exact - 1=exact color match, 0=closest match
685 *          alloced - 1=XAlloc worked, 0=XAlloc failed
686 */
687static void
688noFaultXAllocColor( int client,
689                    XMesaDisplay *dpy,
690                    XMesaColormap cmap,
691                    int cmapSize,
692                    XMesaColor *color,
693                    int *exact, int *alloced )
694{
695#ifdef XFree86Server
696   Pixel *ppixIn;
697   xrgb *ctable;
698#else
699   /* we'll try to cache ctable for better remote display performance */
700   static Display *prevDisplay = NULL;
701   static XMesaColormap prevCmap = 0;
702   static int prevCmapSize = 0;
703   static XMesaColor *ctable = NULL;
704#endif
705   XMesaColor subColor;
706   int i, bestmatch;
707   double mindist;       /* 3*2^16^2 exceeds long int precision. */
708
709   (void) client;
710
711   /* First try just using XAllocColor. */
712#ifdef XFree86Server
713   if (AllocColor(cmap,
714		  &color->red, &color->green, &color->blue,
715		  &color->pixel,
716		  client) == Success) {
717#else
718   if (XAllocColor(dpy, cmap, color)) {
719#endif
720      *exact = 1;
721      *alloced = 1;
722      return;
723   }
724
725   /* Alloc failed, search for closest match */
726
727   /* Retrieve color table entries. */
728   /* XXX alloca candidate. */
729#ifdef XFree86Server
730   ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel));
731   ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb));
732   for (i = 0; i < cmapSize; i++) {
733      ppixIn[i] = i;
734   }
735   QueryColors(cmap, cmapSize, ppixIn, ctable);
736#else
737   if (prevDisplay != dpy || prevCmap != cmap
738       || prevCmapSize != cmapSize || !ctable) {
739      /* free previously cached color table */
740      if (ctable)
741         _mesa_free(ctable);
742      /* Get the color table from X */
743      ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor));
744      assert(ctable);
745      for (i = 0; i < cmapSize; i++) {
746         ctable[i].pixel = i;
747      }
748      XQueryColors(dpy, cmap, ctable, cmapSize);
749      prevDisplay = dpy;
750      prevCmap = cmap;
751      prevCmapSize = cmapSize;
752   }
753#endif
754
755   /* Find best match. */
756   bestmatch = -1;
757   mindist = 0.0;
758   for (i = 0; i < cmapSize; i++) {
759      double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
760      double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
761      double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
762      double dist = dr * dr + dg * dg + db * db;
763      if (bestmatch < 0 || dist < mindist) {
764         bestmatch = i;
765         mindist = dist;
766      }
767   }
768
769   /* Return result. */
770   subColor.red   = ctable[bestmatch].red;
771   subColor.green = ctable[bestmatch].green;
772   subColor.blue  = ctable[bestmatch].blue;
773   /* Try to allocate the closest match color.  This should only
774    * fail if the cell is read/write.  Otherwise, we're incrementing
775    * the cell's reference count.
776    */
777#ifdef XFree86Server
778   if (AllocColor(cmap,
779		  &subColor.red, &subColor.green, &subColor.blue,
780		  &subColor.pixel,
781		  client) == Success) {
782#else
783   if (XAllocColor(dpy, cmap, &subColor)) {
784#endif
785      *alloced = 1;
786   }
787   else {
788      /* do this to work around a problem reported by Frank Ortega */
789      subColor.pixel = (unsigned long) bestmatch;
790      subColor.red   = ctable[bestmatch].red;
791      subColor.green = ctable[bestmatch].green;
792      subColor.blue  = ctable[bestmatch].blue;
793      subColor.flags = DoRed | DoGreen | DoBlue;
794      *alloced = 0;
795   }
796#ifdef XFree86Server
797   _mesa_free(ppixIn);
798   _mesa_free(ctable);
799#else
800   /* don't free table, save it for next time */
801#endif
802
803   *color = subColor;
804   *exact = 0;
805}
806
807
808
809
810/*
811 * Do setup for PF_GRAYSCALE pixel format.
812 * Note that buffer may be NULL.
813 */
814static GLboolean setup_grayscale( int client, XMesaVisual v,
815                                  XMesaBuffer buffer, XMesaColormap cmap )
816{
817   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
818      return GL_FALSE;
819   }
820
821   if (buffer) {
822      XMesaBuffer prevBuffer;
823
824      if (!cmap) {
825         return GL_FALSE;
826      }
827
828      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
829      if (prevBuffer &&
830          (buffer->xm_visual->mesa_visual.rgbMode ==
831           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
832         /* Copy colormap stuff from previous XMesaBuffer which uses same
833          * X colormap.  Do this to avoid time spent in noFaultXAllocColor.
834          */
835         copy_colortable_info(buffer, prevBuffer);
836      }
837      else {
838         /* Allocate 256 shades of gray */
839         int gray;
840         int colorsfailed = 0;
841         for (gray=0;gray<256;gray++) {
842            GLint r = gamma_adjust( v->RedGamma,   gray, 255 );
843            GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
844            GLint b = gamma_adjust( v->BlueGamma,  gray, 255 );
845            int exact, alloced;
846            XMesaColor xcol;
847            xcol.red   = (r << 8) | r;
848            xcol.green = (g << 8) | g;
849            xcol.blue  = (b << 8) | b;
850            noFaultXAllocColor( client, v->display,
851                                cmap, GET_COLORMAP_SIZE(v),
852                                &xcol, &exact, &alloced );
853            if (!exact) {
854               colorsfailed++;
855            }
856            if (alloced) {
857               assert(buffer->num_alloced<256);
858               buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
859               buffer->num_alloced++;
860            }
861
862            /*OLD
863            assert(gray < 576);
864            buffer->color_table[gray*3+0] = xcol.pixel;
865            buffer->color_table[gray*3+1] = xcol.pixel;
866            buffer->color_table[gray*3+2] = xcol.pixel;
867            assert(xcol.pixel < 65536);
868            buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
869            buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
870            buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
871            */
872            buffer->color_table[gray] = xcol.pixel;
873            assert(xcol.pixel < 65536);
874            buffer->pixel_to_r[xcol.pixel] = gray;
875            buffer->pixel_to_g[xcol.pixel] = gray;
876            buffer->pixel_to_b[xcol.pixel] = gray;
877         }
878
879         if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
880            _mesa_warning(NULL,
881                  "Note: %d out of 256 needed colors do not match exactly.\n",
882                  colorsfailed );
883         }
884      }
885   }
886
887   v->dithered_pf = PF_Grayscale;
888   v->undithered_pf = PF_Grayscale;
889   return GL_TRUE;
890}
891
892
893
894/*
895 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
896 * or 8-bit TrueColor visual visual.  We try to allocate a palette of 225
897 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
898 * color.  While this function was originally designed just for 8-bit
899 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
900 * Dithering code contributed by Bob Mercier.
901 */
902static GLboolean setup_dithered_color( int client, XMesaVisual v,
903                                       XMesaBuffer buffer, XMesaColormap cmap )
904{
905   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
906      return GL_FALSE;
907   }
908
909   if (buffer) {
910      XMesaBuffer prevBuffer;
911
912      if (!cmap) {
913         return GL_FALSE;
914      }
915
916      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
917      if (prevBuffer &&
918          (buffer->xm_visual->mesa_visual.rgbMode ==
919           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
920         /* Copy colormap stuff from previous, matching XMesaBuffer.
921          * Do this to avoid time spent in noFaultXAllocColor.
922          */
923         copy_colortable_info(buffer, prevBuffer);
924      }
925      else {
926         /* Allocate X colors and initialize color_table[], red_table[], etc */
927         int r, g, b, i;
928         int colorsfailed = 0;
929         for (r = 0; r < DITH_R; r++) {
930            for (g = 0; g < DITH_G; g++) {
931               for (b = 0; b < DITH_B; b++) {
932                  XMesaColor xcol;
933                  int exact, alloced;
934                  xcol.red  =gamma_adjust(v->RedGamma,   r*65535/(DITH_R-1),65535);
935                  xcol.green=gamma_adjust(v->GreenGamma, g*65535/(DITH_G-1),65535);
936                  xcol.blue =gamma_adjust(v->BlueGamma,  b*65535/(DITH_B-1),65535);
937                  noFaultXAllocColor( client, v->display,
938                                      cmap, GET_COLORMAP_SIZE(v),
939                                      &xcol, &exact, &alloced );
940                  if (!exact) {
941                     colorsfailed++;
942                  }
943                  if (alloced) {
944                     assert(buffer->num_alloced<256);
945                     buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
946                     buffer->num_alloced++;
947                  }
948                  i = DITH_MIX( r, g, b );
949                  assert(i < 576);
950                  buffer->color_table[i] = xcol.pixel;
951                  assert(xcol.pixel < 65536);
952                  buffer->pixel_to_r[xcol.pixel] = r * 255 / (DITH_R-1);
953                  buffer->pixel_to_g[xcol.pixel] = g * 255 / (DITH_G-1);
954                  buffer->pixel_to_b[xcol.pixel] = b * 255 / (DITH_B-1);
955               }
956            }
957         }
958
959         if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
960            _mesa_warning(NULL,
961                  "Note: %d out of %d needed colors do not match exactly.\n",
962                  colorsfailed, DITH_R * DITH_G * DITH_B );
963         }
964      }
965   }
966
967   v->dithered_pf = PF_Dither;
968   v->undithered_pf = PF_Lookup;
969   return GL_TRUE;
970}
971
972
973/*
974 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
975 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
976 * Special dithering tables have to be initialized.
977 */
978static void setup_8bit_hpcr( XMesaVisual v )
979{
980   /* HP Color Recovery contributed by:  Alex De Bruyn (ad@lms.be)
981    * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
982    * on the root window AND the colormap obtainable by XGetRGBColormaps
983    * for that atom must be set on the window.  (see also tkInitWindow)
984    * If that colormap is not set, the output will look stripy.
985    */
986
987   /* Setup color tables with gamma correction */
988   int i;
989   double g;
990
991   g = 1.0 / v->RedGamma;
992   for (i=0; i<256; i++) {
993      GLint red = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[0][i]/255.0, g ));
994      v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 );
995   }
996
997   g = 1.0 / v->GreenGamma;
998   for (i=0; i<256; i++) {
999      GLint green = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[1][i]/255.0, g ));
1000      v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 );
1001   }
1002
1003   g = 1.0 / v->BlueGamma;
1004   for (i=0; i<256; i++) {
1005      GLint blue = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[2][i]/255.0, g ));
1006      v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 );
1007   }
1008   v->undithered_pf = PF_HPCR;  /* can't really disable dithering for now */
1009   v->dithered_pf = PF_HPCR;
1010
1011   /* which method should I use to clear */
1012   /* GL_FALSE: keep the ordinary method  */
1013   /* GL_TRUE : clear with dither pattern */
1014   v->hpcr_clear_flag = _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE;
1015
1016   if (v->hpcr_clear_flag) {
1017      v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display,
1018                                               DefaultRootWindow(v->display),
1019                                               16, 2, 8);
1020#ifndef XFree86Server
1021      v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap,
1022                                       0, 0, 16, 2, AllPlanes, ZPixmap);
1023#endif
1024   }
1025}
1026
1027
1028/*
1029 * Setup RGB rendering for a window with a True/DirectColor visual.
1030 */
1031static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer,
1032                             XMesaColormap cmap )
1033{
1034   unsigned long rmask, gmask, bmask;
1035   (void) buffer;
1036   (void) cmap;
1037
1038   /* Compute red multiplier (mask) and bit shift */
1039   v->rshift = 0;
1040   rmask = GET_REDMASK(v);
1041   while ((rmask & 1)==0) {
1042      v->rshift++;
1043      rmask = rmask >> 1;
1044   }
1045
1046   /* Compute green multiplier (mask) and bit shift */
1047   v->gshift = 0;
1048   gmask = GET_GREENMASK(v);
1049   while ((gmask & 1)==0) {
1050      v->gshift++;
1051      gmask = gmask >> 1;
1052   }
1053
1054   /* Compute blue multiplier (mask) and bit shift */
1055   v->bshift = 0;
1056   bmask = GET_BLUEMASK(v);
1057   while ((bmask & 1)==0) {
1058      v->bshift++;
1059      bmask = bmask >> 1;
1060   }
1061
1062   /*
1063    * Compute component-to-pixel lookup tables and dithering kernel
1064    */
1065   {
1066      static GLubyte kernel[16] = {
1067          0*16,  8*16,  2*16, 10*16,
1068         12*16,  4*16, 14*16,  6*16,
1069          3*16, 11*16,  1*16,  9*16,
1070         15*16,  7*16, 13*16,  5*16,
1071      };
1072      GLint rBits = _mesa_bitcount(rmask);
1073      GLint gBits = _mesa_bitcount(gmask);
1074      GLint bBits = _mesa_bitcount(bmask);
1075      GLint maxBits;
1076      GLuint i;
1077
1078      /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1079      for (i=0; i<=rmask; i++)
1080         v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
1081      for (i=0; i<=gmask; i++)
1082         v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
1083      for (i=0; i<=bmask; i++)
1084         v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
1085
1086      /* convert RGB values from [0,255] to pixel components */
1087
1088      for (i=0;i<256;i++) {
1089         GLint r = gamma_adjust(v->RedGamma,   i, 255);
1090         GLint g = gamma_adjust(v->GreenGamma, i, 255);
1091         GLint b = gamma_adjust(v->BlueGamma,  i, 255);
1092         v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
1093         v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
1094         v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
1095      }
1096      /* overflow protection */
1097      for (i=256;i<512;i++) {
1098         v->RtoPixel[i] = v->RtoPixel[255];
1099         v->GtoPixel[i] = v->GtoPixel[255];
1100         v->BtoPixel[i] = v->BtoPixel[255];
1101      }
1102
1103      /* setup dithering kernel */
1104      maxBits = rBits;
1105      if (gBits > maxBits)  maxBits = gBits;
1106      if (bBits > maxBits)  maxBits = bBits;
1107      for (i=0;i<16;i++) {
1108         v->Kernel[i] = kernel[i] >> maxBits;
1109      }
1110
1111      v->undithered_pf = PF_Truecolor;
1112      v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor;
1113   }
1114
1115   /*
1116    * Now check for TrueColor visuals which we can optimize.
1117    */
1118   if (   GET_REDMASK(v)  ==0x0000ff
1119       && GET_GREENMASK(v)==0x00ff00
1120       && GET_BLUEMASK(v) ==0xff0000
1121       && CHECK_BYTE_ORDER(v)
1122       && v->BitsPerPixel==32
1123       && sizeof(GLuint)==4
1124       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1125      /* common 32 bpp config used on SGI, Sun */
1126      v->undithered_pf = v->dithered_pf = PF_8A8B8G8R;
1127   }
1128   else if (GET_REDMASK(v)  ==0xff0000
1129       &&   GET_GREENMASK(v)==0x00ff00
1130       &&   GET_BLUEMASK(v) ==0x0000ff
1131       && CHECK_BYTE_ORDER(v)
1132       && v->BitsPerPixel==32
1133       && sizeof(GLuint)==4
1134       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1135      /* common 32 bpp config used on Linux, HP, IBM */
1136      if (GET_VISUAL_DEPTH(v)==32)
1137	  v->undithered_pf = v->dithered_pf = PF_8A8R8G8B;
1138      else
1139	  v->undithered_pf = v->dithered_pf = PF_8R8G8B;
1140   }
1141   else if (GET_REDMASK(v)  ==0xff0000
1142       &&   GET_GREENMASK(v)==0x00ff00
1143       &&   GET_BLUEMASK(v) ==0x0000ff
1144       && CHECK_BYTE_ORDER(v)
1145       && v->BitsPerPixel==24
1146       && sizeof(GLuint)==4
1147       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1148      /* common packed 24 bpp config used on Linux */
1149      v->undithered_pf = v->dithered_pf = PF_8R8G8B24;
1150   }
1151   else if (GET_REDMASK(v)  ==0xf800
1152       &&   GET_GREENMASK(v)==0x07e0
1153       &&   GET_BLUEMASK(v) ==0x001f
1154       && CHECK_BYTE_ORDER(v)
1155       && v->BitsPerPixel==16
1156       && sizeof(GLushort)==2
1157       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1158      /* 5-6-5 color weight on common PC VGA boards */
1159      v->undithered_pf = PF_5R6G5B;
1160      v->dithered_pf = PF_Dither_5R6G5B;
1161   }
1162   else if (GET_REDMASK(v)  ==0xe0
1163       &&   GET_GREENMASK(v)==0x1c
1164       &&   GET_BLUEMASK(v) ==0x03
1165       && CHECK_FOR_HPCR(v)) {
1166      setup_8bit_hpcr( v );
1167   }
1168}
1169
1170
1171
1172/*
1173 * Setup RGB rendering for a window with a monochrome visual.
1174 */
1175static void setup_monochrome( XMesaVisual v, XMesaBuffer b )
1176{
1177   (void) b;
1178   v->dithered_pf = v->undithered_pf = PF_1Bit;
1179   /* if black=1 then we must flip pixel values */
1180   v->bitFlip = (GET_BLACK_PIXEL(v) != 0);
1181}
1182
1183
1184
1185/*
1186 * When a context is "made current" for the first time, we can finally
1187 * finish initializing the context's visual and buffer information.
1188 * Input:  v - the XMesaVisual to initialize
1189 *         b - the XMesaBuffer to initialize (may be NULL)
1190 *         rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1191 *         window - the window/pixmap we're rendering into
1192 *         cmap - the colormap associated with the window/pixmap
1193 * Return:  GL_TRUE=success, GL_FALSE=failure
1194 */
1195static GLboolean initialize_visual_and_buffer( int client,
1196                                               XMesaVisual v,
1197                                               XMesaBuffer b,
1198                                               GLboolean rgb_flag,
1199                                               XMesaDrawable window,
1200                                               XMesaColormap cmap )
1201{
1202   struct xmesa_renderbuffer *front_xrb, *back_xrb;
1203#ifndef XFree86Server
1204   XGCValues gcvalues;
1205#endif
1206
1207   if (b) {
1208      assert(b->xm_visual == v);
1209   }
1210
1211   if (b) {
1212      front_xrb = b->frontxrb;
1213      back_xrb = b->backxrb;
1214   }
1215   else {
1216      front_xrb = back_xrb = NULL;
1217   }
1218
1219   /* Save true bits/pixel */
1220   v->BitsPerPixel = bits_per_pixel(v);
1221   assert(v->BitsPerPixel > 0);
1222
1223
1224   if (rgb_flag==GL_FALSE) {
1225      /* COLOR-INDEXED WINDOW:
1226       * Even if the visual is TrueColor or DirectColor we treat it as
1227       * being color indexed.  This is weird but might be useful to someone.
1228       */
1229      v->dithered_pf = v->undithered_pf = PF_Index;
1230      v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v);
1231   }
1232   else {
1233      /* RGB WINDOW:
1234       * We support RGB rendering into almost any kind of visual.
1235       */
1236      const int xclass = v->mesa_visual.visualType;
1237      if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
1238	 setup_truecolor( v, b, cmap );
1239      }
1240      else if (xclass==GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v)==1) {
1241	 setup_monochrome( v, b );
1242      }
1243      else if (xclass==GLX_GRAY_SCALE || xclass==GLX_STATIC_GRAY) {
1244         if (!setup_grayscale( client, v, b, cmap )) {
1245            return GL_FALSE;
1246         }
1247      }
1248      else if ((xclass==GLX_PSEUDO_COLOR || xclass==GLX_STATIC_COLOR)
1249               && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
1250	 if (!setup_dithered_color( client, v, b, cmap )) {
1251            return GL_FALSE;
1252         }
1253      }
1254      else {
1255	 _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.");
1256	 return GL_FALSE;
1257      }
1258      v->mesa_visual.indexBits = 0;
1259
1260      if (_mesa_getenv("MESA_NO_DITHER")) {
1261	 v->dithered_pf = v->undithered_pf;
1262      }
1263   }
1264
1265
1266   /*
1267    * If MESA_INFO env var is set print out some debugging info
1268    * which can help Brian figure out what's going on when a user
1269    * reports bugs.
1270    */
1271   if (_mesa_getenv("MESA_INFO")) {
1272      _mesa_printf("X/Mesa visual = %p\n", (void *) v);
1273      _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf);
1274      _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf);
1275      _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
1276      _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
1277      _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
1278   }
1279
1280   if (b && window) {
1281      /* Do window-specific initializations */
1282
1283      b->frontxrb->drawable = window;
1284      b->frontxrb->pixmap = (XMesaPixmap) window;
1285
1286      /* Setup for single/double buffering */
1287      if (v->mesa_visual.doubleBufferMode) {
1288         /* Double buffered */
1289         b->shm = check_for_xshm( v->display );
1290         xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height);
1291      }
1292
1293      /* X11 graphics contexts */
1294#ifdef XFree86Server
1295      b->gc = CreateScratchGC(v->display, window->depth);
1296#else
1297      b->gc = XCreateGC( v->display, window, 0, NULL );
1298#endif
1299      XMesaSetFunction( v->display, b->gc, GXcopy );
1300
1301      /* cleargc - for glClear() */
1302#ifdef XFree86Server
1303      b->cleargc = CreateScratchGC(v->display, window->depth);
1304#else
1305      b->cleargc = XCreateGC( v->display, window, 0, NULL );
1306#endif
1307      XMesaSetFunction( v->display, b->cleargc, GXcopy );
1308
1309      /*
1310       * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1311       * Patch contributed by Michael Pichler May 15, 1995.
1312       */
1313#ifdef XFree86Server
1314      b->swapgc = CreateScratchGC(v->display, window->depth);
1315      {
1316         CARD32 v[1];
1317         v[0] = FALSE;
1318         dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL);
1319      }
1320#else
1321      gcvalues.graphics_exposures = False;
1322      b->swapgc = XCreateGC( v->display, window,
1323                              GCGraphicsExposures, &gcvalues);
1324#endif
1325      XMesaSetFunction( v->display, b->swapgc, GXcopy );
1326      /*
1327       * Set fill style and tile pixmap once for all for HPCR stuff
1328       * (instead of doing it each time in clear_color_HPCR_pixmap())
1329       * Initialize whole stuff
1330       * Patch contributed by Jacques Leroy March 8, 1998.
1331       */
1332      if (v->hpcr_clear_flag && back_xrb->pixmap) {
1333	int i;
1334	for (i=0; i<16; i++)
1335        {
1336	   XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0);
1337	   XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0);
1338        }
1339        XMesaPutImage(b->display, (XMesaDrawable) v->hpcr_clear_pixmap,
1340		      b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
1341	XMesaSetFillStyle( v->display, b->cleargc, FillTiled);
1342	XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap );
1343      }
1344
1345      /* Initialize the row buffer XImage for use in write_color_span() */
1346#ifdef XFree86Server
1347      b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1,
1348				     (char *)MALLOC(MAX_WIDTH*4));
1349#else
1350      b->rowimage = XCreateImage( v->display,
1351                                  v->visinfo->visual,
1352                                  v->visinfo->depth,
1353                                  ZPixmap, 0,           /*format, offset*/
1354                                  (char*) MALLOC(MAX_WIDTH*4),  /*data*/
1355                                  MAX_WIDTH, 1,         /*width, height*/
1356                                  32,                   /*bitmap_pad*/
1357                                  0                     /*bytes_per_line*/ );
1358#endif
1359      if (!b->rowimage)
1360         return GL_FALSE;
1361   }
1362
1363   return GL_TRUE;
1364}
1365
1366
1367
1368/*
1369 * Convert an RGBA color to a pixel value.
1370 */
1371unsigned long
1372xmesa_color_to_pixel(GLcontext *ctx,
1373                     GLubyte r, GLubyte g, GLubyte b, GLubyte a,
1374                     GLuint pixelFormat)
1375{
1376   XMesaContext xmesa = XMESA_CONTEXT(ctx);
1377   switch (pixelFormat) {
1378      case PF_Index:
1379         return 0;
1380      case PF_Truecolor:
1381         {
1382            unsigned long p;
1383            PACK_TRUECOLOR( p, r, g, b );
1384            return p;
1385         }
1386      case PF_8A8B8G8R:
1387         return PACK_8A8B8G8R( r, g, b, a );
1388      case PF_8A8R8G8B:
1389         return PACK_8A8R8G8B( r, g, b, a );
1390      case PF_8R8G8B:
1391         /* fall through */
1392      case PF_8R8G8B24:
1393         return PACK_8R8G8B( r, g, b );
1394      case PF_5R6G5B:
1395         return PACK_5R6G5B( r, g, b );
1396      case PF_Dither:
1397         {
1398            DITHER_SETUP;
1399            return DITHER( 1, 0, r, g, b );
1400         }
1401      case PF_1Bit:
1402         /* 382 = (3*255)/2 */
1403         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
1404      case PF_HPCR:
1405         return DITHER_HPCR(1, 1, r, g, b);
1406      case PF_Lookup:
1407         {
1408            LOOKUP_SETUP;
1409            return LOOKUP( r, g, b );
1410         }
1411      case PF_Grayscale:
1412         return GRAY_RGB( r, g, b );
1413      case PF_Dither_True:
1414         /* fall through */
1415      case PF_Dither_5R6G5B:
1416         {
1417            unsigned long p;
1418            PACK_TRUEDITHER(p, 1, 0, r, g, b);
1419            return p;
1420         }
1421      default:
1422         _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel");
1423   }
1424   return 0;
1425}
1426
1427
1428#define NUM_VISUAL_TYPES   6
1429
1430/**
1431 * Convert an X visual type to a GLX visual type.
1432 *
1433 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
1434 *        to be converted.
1435 * \return If \c visualType is a valid X visual type, a GLX visual type will
1436 *         be returned.  Otherwise \c GLX_NONE will be returned.
1437 *
1438 * \note
1439 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
1440 * DRI CVS tree.
1441 */
1442static GLint
1443xmesa_convert_from_x_visual_type( int visualType )
1444{
1445    static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
1446	GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
1447	GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
1448	GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
1449    };
1450
1451    return ( (unsigned) visualType < NUM_VISUAL_TYPES )
1452	? glx_visual_types[ visualType ] : GLX_NONE;
1453}
1454
1455
1456/**********************************************************************/
1457/*****                       Public Functions                     *****/
1458/**********************************************************************/
1459
1460
1461/*
1462 * Create a new X/Mesa visual.
1463 * Input:  display - X11 display
1464 *         visinfo - an XVisualInfo pointer
1465 *         rgb_flag - GL_TRUE = RGB mode,
1466 *                    GL_FALSE = color index mode
1467 *         alpha_flag - alpha buffer requested?
1468 *         db_flag - GL_TRUE = double-buffered,
1469 *                   GL_FALSE = single buffered
1470 *         stereo_flag - stereo visual?
1471 *         ximage_flag - GL_TRUE = use an XImage for back buffer,
1472 *                       GL_FALSE = use an off-screen pixmap for back buffer
1473 *         depth_size - requested bits/depth values, or zero
1474 *         stencil_size - requested bits/stencil values, or zero
1475 *         accum_red_size - requested bits/red accum values, or zero
1476 *         accum_green_size - requested bits/green accum values, or zero
1477 *         accum_blue_size - requested bits/blue accum values, or zero
1478 *         accum_alpha_size - requested bits/alpha accum values, or zero
1479 *         num_samples - number of samples/pixel if multisampling, or zero
1480 *         level - visual level, usually 0
1481 *         visualCaveat - ala the GLX extension, usually GLX_NONE
1482 * Return;  a new XMesaVisual or 0 if error.
1483 */
1484XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
1485                               XMesaVisualInfo visinfo,
1486                               GLboolean rgb_flag,
1487                               GLboolean alpha_flag,
1488                               GLboolean db_flag,
1489                               GLboolean stereo_flag,
1490                               GLboolean ximage_flag,
1491                               GLint depth_size,
1492                               GLint stencil_size,
1493                               GLint accum_red_size,
1494                               GLint accum_green_size,
1495                               GLint accum_blue_size,
1496                               GLint accum_alpha_size,
1497                               GLint num_samples,
1498                               GLint level,
1499                               GLint visualCaveat )
1500{
1501   char *gamma;
1502   XMesaVisual v;
1503   GLint red_bits, green_bits, blue_bits, alpha_bits;
1504
1505   /* For debugging only */
1506   if (_mesa_getenv("MESA_XSYNC")) {
1507      /* This makes debugging X easier.
1508       * In your debugger, set a breakpoint on _XError to stop when an
1509       * X protocol error is generated.
1510       */
1511#ifdef XFree86Server
1512      /* NOT_NEEDED */
1513#else
1514      XSynchronize( display, 1 );
1515#endif
1516   }
1517
1518   v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
1519   if (!v) {
1520      return NULL;
1521   }
1522
1523   /*
1524    * In the X server, NULL is passed in for the display.  It will have
1525    * to be set before using this visual.  See XMesaSetVisualDisplay()
1526    * below.
1527    */
1528   v->display = display;
1529
1530   /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
1531    * the struct but we may need some of the information contained in it
1532    * at a later time.
1533    */
1534#ifndef XFree86Server
1535   v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
1536   if(!v->visinfo) {
1537      _mesa_free(v);
1538      return NULL;
1539   }
1540   MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
1541#endif
1542
1543   /* check for MESA_GAMMA environment variable */
1544   gamma = _mesa_getenv("MESA_GAMMA");
1545   if (gamma) {
1546      v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
1547      sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
1548      if (v->RedGamma<=0.0)    v->RedGamma = 1.0;
1549      if (v->GreenGamma<=0.0)  v->GreenGamma = v->RedGamma;
1550      if (v->BlueGamma<=0.0)   v->BlueGamma = v->RedGamma;
1551   }
1552   else {
1553      v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
1554   }
1555
1556   v->ximage_flag = ximage_flag;
1557
1558#ifdef XFree86Server
1559   /* We could calculate these values by ourselves.  nplanes is either the sum
1560    * of the red, green, and blue bits or the number index bits.
1561    * ColormapEntries is either (1U << index_bits) or
1562    * (1U << max(redBits, greenBits, blueBits)).
1563    */
1564   v->nplanes = visinfo->nplanes;
1565   v->ColormapEntries = visinfo->ColormapEntries;
1566
1567   v->mesa_visual.redMask = visinfo->redMask;
1568   v->mesa_visual.greenMask = visinfo->greenMask;
1569   v->mesa_visual.blueMask = visinfo->blueMask;
1570   v->mesa_visual.visualID = visinfo->vid;
1571   v->mesa_visual.screen = 0; /* FIXME: What should be done here? */
1572#else
1573   v->mesa_visual.redMask = visinfo->red_mask;
1574   v->mesa_visual.greenMask = visinfo->green_mask;
1575   v->mesa_visual.blueMask = visinfo->blue_mask;
1576   v->mesa_visual.visualID = visinfo->visualid;
1577   v->mesa_visual.screen = visinfo->screen;
1578#endif
1579
1580#if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
1581   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
1582#else
1583   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
1584#endif
1585
1586   v->mesa_visual.visualRating = visualCaveat;
1587
1588   (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 );
1589
1590   {
1591      const int xclass = v->mesa_visual.visualType;
1592      if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
1593         red_bits   = _mesa_bitcount(GET_REDMASK(v));
1594         green_bits = _mesa_bitcount(GET_GREENMASK(v));
1595         blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
1596         alpha_bits = 0;
1597      }
1598      else {
1599         /* this is an approximation */
1600         int depth;
1601         depth = GET_VISUAL_DEPTH(v);
1602         red_bits = depth / 3;
1603         depth -= red_bits;
1604         green_bits = depth / 2;
1605         depth -= green_bits;
1606         blue_bits = depth;
1607         alpha_bits = 0;
1608         assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
1609      }
1610   }
1611
1612   if (alpha_flag && alpha_bits == 0)
1613      alpha_bits = 8;
1614
1615   _mesa_initialize_visual( &v->mesa_visual,
1616                            rgb_flag, db_flag, stereo_flag,
1617                            red_bits, green_bits,
1618                            blue_bits, alpha_bits,
1619                            v->mesa_visual.indexBits,
1620                            depth_size,
1621                            stencil_size,
1622                            accum_red_size, accum_green_size,
1623                            accum_blue_size, accum_alpha_size,
1624                            0 );
1625
1626   /* XXX minor hack */
1627   v->mesa_visual.level = level;
1628   return v;
1629}
1630
1631
1632void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v )
1633{
1634    v->display = dpy;
1635}
1636
1637
1638void XMesaDestroyVisual( XMesaVisual v )
1639{
1640#ifndef XFree86Server
1641   _mesa_free(v->visinfo);
1642#endif
1643   _mesa_free(v);
1644}
1645
1646
1647
1648/**
1649 * Create a new XMesaContext.
1650 * \param v  the XMesaVisual
1651 * \param share_list  another XMesaContext with which to share display
1652 *                    lists or NULL if no sharing is wanted.
1653 * \return an XMesaContext or NULL if error.
1654 */
1655XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
1656{
1657   static GLboolean firstTime = GL_TRUE;
1658   XMesaContext c;
1659   GLcontext *mesaCtx;
1660   struct dd_function_table functions;
1661   TNLcontext *tnl;
1662
1663   if (firstTime) {
1664      _glthread_INIT_MUTEX(_xmesa_lock);
1665      firstTime = GL_FALSE;
1666   }
1667
1668   /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
1669   c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
1670   if (!c)
1671      return NULL;
1672
1673   mesaCtx = &(c->mesa);
1674
1675   /* initialize with default driver functions, then plug in XMesa funcs */
1676   _mesa_init_driver_functions(&functions);
1677   xmesa_init_driver_functions(v, &functions);
1678   if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual,
1679                      share_list ? &(share_list->mesa) : (GLcontext *) NULL,
1680                      &functions, (void *) c)) {
1681      _mesa_free(c);
1682      return NULL;
1683   }
1684
1685   _mesa_enable_sw_extensions(mesaCtx);
1686   _mesa_enable_1_3_extensions(mesaCtx);
1687   _mesa_enable_1_4_extensions(mesaCtx);
1688   _mesa_enable_1_5_extensions(mesaCtx);
1689   _mesa_enable_2_0_extensions(mesaCtx);
1690#if ENABLE_EXT_texure_compression_s3tc
1691    if (c->Mesa_DXTn) {
1692       _mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc");
1693       _mesa_enable_extension(mesaCtx, "GL_S3_s3tc");
1694    }
1695    _mesa_enable_extension(mesaCtx, "GL_3DFX_texture_compression_FXT1");
1696#endif
1697#if ENABLE_EXT_timer_query
1698    _mesa_enable_extension(mesaCtx, "GL_EXT_timer_query");
1699#endif
1700
1701   /* finish up xmesa context initializations */
1702   c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
1703   c->xm_visual = v;
1704   c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
1705   c->display = v->display;
1706   c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
1707
1708   /* Initialize the software rasterizer and helper modules.
1709    */
1710   if (!_swrast_CreateContext( mesaCtx ) ||
1711       !_ac_CreateContext( mesaCtx ) ||
1712       !_tnl_CreateContext( mesaCtx ) ||
1713       !_swsetup_CreateContext( mesaCtx )) {
1714      _mesa_free_context_data(&c->mesa);
1715      _mesa_free(c);
1716      return NULL;
1717   }
1718
1719   /* tnl setup */
1720   tnl = TNL_CONTEXT(mesaCtx);
1721   tnl->Driver.RunPipeline = _tnl_run_pipeline;
1722   /* swrast setup */
1723   xmesa_register_swrast_functions( mesaCtx );
1724   _swsetup_Wakeup(mesaCtx);
1725
1726   return c;
1727}
1728
1729
1730
1731void XMesaDestroyContext( XMesaContext c )
1732{
1733   GLcontext *mesaCtx = &c->mesa;
1734#ifdef FX
1735   XMesaBuffer xmbuf = XMESA_BUFFER(mesaCtx->DrawBuffer);
1736
1737   if (xmbuf && xmbuf->FXctx)
1738      fxMesaDestroyContext(xmbuf->FXctx);
1739#endif
1740   _swsetup_DestroyContext( mesaCtx );
1741   _swrast_DestroyContext( mesaCtx );
1742   _tnl_DestroyContext( mesaCtx );
1743   _ac_DestroyContext( mesaCtx );
1744   _mesa_free_context_data( mesaCtx );
1745   _mesa_free( c );
1746}
1747
1748
1749
1750/*
1751 * XXX this isn't a public function!  It's a hack for the 3Dfx driver.
1752 * Create a new XMesaBuffer from an X window.
1753 * Input:  v - the XMesaVisual
1754 *         w - the window
1755 *         c - the context
1756 * Return:  new XMesaBuffer or NULL if error
1757 */
1758XMesaBuffer
1759XMesaCreateWindowBuffer2(XMesaVisual v, XMesaWindow w, XMesaContext c)
1760{
1761#ifndef XFree86Server
1762   XWindowAttributes attr;
1763#endif
1764#ifdef FX
1765   char *fxEnvVar;
1766#endif
1767   int client = 0;
1768   XMesaBuffer b;
1769   XMesaColormap cmap;
1770
1771   assert(v);
1772   (void) c;
1773
1774   /* Check that window depth matches visual depth */
1775#ifdef XFree86Server
1776   client = CLIENT_ID(((XMesaDrawable)w)->id);
1777
1778   if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
1779      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1780                    GET_VISUAL_DEPTH(v), ((XMesaDrawable) w)->depth);
1781      return NULL;
1782   }
1783#else
1784   XGetWindowAttributes( v->display, w, &attr );
1785
1786   if (GET_VISUAL_DEPTH(v) != attr.depth) {
1787      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1788                    GET_VISUAL_DEPTH(v), attr.depth);
1789      return NULL;
1790   }
1791#endif
1792
1793   /* Find colormap */
1794#ifdef XFree86Server
1795   cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1796#else
1797   if (attr.colormap) {
1798      cmap = attr.colormap;
1799   }
1800   else {
1801      _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
1802      /* this is weird, a window w/out a colormap!? */
1803      /* OK, let's just allocate a new one and hope for the best */
1804      cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1805   }
1806#endif
1807
1808   b = alloc_xmesa_buffer(v, WINDOW, cmap);
1809   if (!b) {
1810      return NULL;
1811   }
1812
1813   if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
1814                                      (XMesaDrawable) w, cmap )) {
1815      free_xmesa_buffer(client, b);
1816      return NULL;
1817   }
1818
1819#ifdef FX
1820   fxEnvVar = _mesa_getenv("MESA_GLX_FX");
1821   if (fxEnvVar) {
1822     if (fxEnvVar[0]!='d') {
1823       int attribs[100];
1824       int numAttribs = 0;
1825       int hw;
1826       if (v->mesa_visual.depthBits > 0) {
1827	 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
1828	 attribs[numAttribs++] = v->mesa_visual.depthBits;
1829       }
1830       if (v->mesa_visual.doubleBufferMode) {
1831	 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
1832       }
1833       if (v->mesa_visual.accumRedBits > 0) {
1834	 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
1835	 attribs[numAttribs++] = v->mesa_visual.accumRedBits;
1836       }
1837       if (v->mesa_visual.stencilBits > 0) {
1838         attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
1839         attribs[numAttribs++] = v->mesa_visual.stencilBits;
1840       }
1841       if (v->mesa_visual.alphaBits > 0) {
1842         attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
1843         attribs[numAttribs++] = v->mesa_visual.alphaBits;
1844       }
1845       if (1) {
1846         attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
1847         attribs[numAttribs++] = (int) &(c->mesa);
1848       }
1849       attribs[numAttribs++] = FXMESA_NONE;
1850
1851       /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
1852       hw = fxMesaSelectCurrentBoard(0);
1853
1854       /* if these fail, there's a new bug somewhere */
1855       ASSERT(b->mesa_buffer.Width > 0);
1856       ASSERT(b->mesa_buffer.Height > 0);
1857
1858       if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) {
1859         b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
1860                                            b->mesa_buffer.Height, attribs);
1861         if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) {
1862	   b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
1863	   if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) {
1864	     b->FXwindowHack = GL_TRUE;
1865	     FX_grSstControl(GR_CONTROL_DEACTIVATE);
1866	   }
1867           else {
1868	     b->FXwindowHack = GL_FALSE;
1869	   }
1870         }
1871       }
1872       else {
1873         if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1874	   b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
1875					  GR_REFRESH_75Hz, attribs);
1876         else
1877	   b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
1878                                              b->mesa_buffer.Height, attribs);
1879         b->FXisHackUsable = GL_FALSE;
1880         b->FXwindowHack = GL_FALSE;
1881       }
1882       /*
1883       fprintf(stderr,
1884               "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1885               hw, b->mesa_buffer.Width, b->mesa_buffer.Height,
1886	       b->FXisHackUsable, b->FXwindowHack);
1887       */
1888     }
1889   }
1890   else {
1891      _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n");
1892      _mesa_warning(NULL, "         you have not defined the MESA_GLX_FX env. var.\n");
1893      _mesa_warning(NULL, "         (check the README.3DFX file for more information).\n\n");
1894      _mesa_warning(NULL, "         you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1895   }
1896#endif
1897
1898   return b;
1899}
1900
1901
1902XMesaBuffer
1903XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
1904{
1905   return XMesaCreateWindowBuffer2( v, w, NULL );
1906}
1907
1908
1909/**
1910 * Create a new XMesaBuffer from an X pixmap.
1911 *
1912 * \param v    the XMesaVisual
1913 * \param p    the pixmap
1914 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1915 *             \c GLX_DIRECT_COLOR visual for the pixmap
1916 * \returns new XMesaBuffer or NULL if error
1917 */
1918XMesaBuffer
1919XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
1920{
1921   int client = 0;
1922   XMesaBuffer b;
1923
1924   assert(v);
1925
1926   b = alloc_xmesa_buffer(v, PIXMAP, cmap);
1927   if (!b) {
1928      return NULL;
1929   }
1930
1931#ifdef XFree86Server
1932   client = CLIENT_ID(((XMesaDrawable)p)->id);
1933#endif
1934
1935   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1936				     (XMesaDrawable) p, cmap)) {
1937      free_xmesa_buffer(client, b);
1938      return NULL;
1939   }
1940
1941   return b;
1942}
1943
1944
1945
1946XMesaBuffer
1947XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
1948                   unsigned int width, unsigned int height)
1949{
1950#ifdef XFree86Server
1951   return 0;
1952#else
1953   int client = 0;
1954   XMesaWindow root;
1955   XMesaDrawable drawable;  /* X Pixmap Drawable */
1956   XMesaBuffer b;
1957
1958   b = alloc_xmesa_buffer(v, PBUFFER, cmap);
1959   if (!b) {
1960      return NULL;
1961   }
1962
1963   /* allocate pixmap for front buffer */
1964   root = RootWindow( v->display, v->visinfo->screen );
1965   drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth );
1966
1967   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1968				     drawable, cmap)) {
1969      free_xmesa_buffer(client, b);
1970      return NULL;
1971   }
1972
1973   return b;
1974#endif
1975}
1976
1977
1978
1979/*
1980 * Deallocate an XMesaBuffer structure and all related info.
1981 */
1982void XMesaDestroyBuffer( XMesaBuffer b )
1983{
1984   int client = 0;
1985
1986#ifdef XFree86Server
1987   if (b->frontxrb->drawable)
1988       client = CLIENT_ID(b->frontxrb->drawable->id);
1989#endif
1990
1991   if (b->gc)  XMesaFreeGC( b->xm_visual->display, b->gc );
1992   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
1993   if (b->swapgc)  XMesaFreeGC( b->xm_visual->display, b->swapgc );
1994
1995   if (b->xm_visual->mesa_visual.doubleBufferMode)
1996   {
1997      if (b->backxrb->ximage) {
1998#if defined(USE_XSHM) && !defined(XFree86Server)
1999         if (b->shm) {
2000            XShmDetach( b->xm_visual->display, &b->shminfo );
2001            XDestroyImage( b->backxrb->ximage );
2002            shmdt( b->shminfo.shmaddr );
2003         }
2004         else
2005#endif
2006            XMesaDestroyImage( b->backxrb->ximage );
2007      }
2008      if (b->backxrb->pixmap) {
2009         XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
2010         if (b->xm_visual->hpcr_clear_flag) {
2011            XMesaFreePixmap( b->xm_visual->display,
2012                             b->xm_visual->hpcr_clear_pixmap );
2013            XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
2014         }
2015      }
2016   }
2017   if (b->rowimage) {
2018      _mesa_free( b->rowimage->data );
2019      b->rowimage->data = NULL;
2020      XMesaDestroyImage( b->rowimage );
2021   }
2022
2023   free_xmesa_buffer(client, b);
2024}
2025
2026
2027
2028/*
2029 * Bind buffer b to context c and make c the current rendering context.
2030 */
2031GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
2032{
2033   return XMesaMakeCurrent2( c, b, b );
2034}
2035
2036
2037/*
2038 * Bind buffer b to context c and make c the current rendering context.
2039 */
2040GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
2041                             XMesaBuffer readBuffer )
2042{
2043   if (c) {
2044      if (!drawBuffer || !readBuffer)
2045         return GL_FALSE;  /* must specify buffers! */
2046
2047#ifdef FX
2048      if (drawBuffer->FXctx) {
2049         fxMesaMakeCurrent(drawBuffer->FXctx);
2050
2051         c->xm_buffer = drawBuffer;
2052
2053         return GL_TRUE;
2054      }
2055#endif
2056      if (&(c->mesa) == _mesa_get_current_context()
2057          && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
2058          && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
2059          && ((XMesaBuffer) c->mesa.DrawBuffer)->wasCurrent) {
2060         /* same context and buffer, do nothing */
2061         return GL_TRUE;
2062      }
2063
2064      c->xm_buffer = drawBuffer;
2065
2066      _mesa_make_current(&(c->mesa),
2067                         &drawBuffer->mesa_buffer,
2068                         &readBuffer->mesa_buffer);
2069
2070      if (c->xm_visual->mesa_visual.rgbMode) {
2071         /*
2072          * Must recompute and set these pixel values because colormap
2073          * can be different for different windows.
2074          */
2075         c->clearpixel = xmesa_color_to_pixel( &c->mesa,
2076                                               c->clearcolor[0],
2077                                               c->clearcolor[1],
2078                                               c->clearcolor[2],
2079                                               c->clearcolor[3],
2080                                               c->xm_visual->undithered_pf);
2081         XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
2082      }
2083
2084      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2085      drawBuffer->wasCurrent = GL_TRUE;
2086   }
2087   else {
2088      /* Detach */
2089      _mesa_make_current( NULL, NULL, NULL );
2090   }
2091   return GL_TRUE;
2092}
2093
2094
2095/*
2096 * Unbind the context c from its buffer.
2097 */
2098GLboolean XMesaUnbindContext( XMesaContext c )
2099{
2100   /* A no-op for XFree86 integration purposes */
2101   return GL_TRUE;
2102}
2103
2104
2105XMesaContext XMesaGetCurrentContext( void )
2106{
2107   GET_CURRENT_CONTEXT(ctx);
2108   if (ctx) {
2109      XMesaContext xmesa = XMESA_CONTEXT(ctx);
2110      return xmesa;
2111   }
2112   else {
2113      return 0;
2114   }
2115}
2116
2117
2118XMesaBuffer XMesaGetCurrentBuffer( void )
2119{
2120   GET_CURRENT_CONTEXT(ctx);
2121   if (ctx) {
2122      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2123      return xmbuf;
2124   }
2125   else {
2126      return 0;
2127   }
2128}
2129
2130
2131/* New in Mesa 3.1 */
2132XMesaBuffer XMesaGetCurrentReadBuffer( void )
2133{
2134   GET_CURRENT_CONTEXT(ctx);
2135   if (ctx) {
2136      return (XMesaBuffer) (ctx->ReadBuffer);
2137   }
2138   else {
2139      return 0;
2140   }
2141}
2142
2143
2144GLboolean XMesaForceCurrent(XMesaContext c)
2145{
2146   if (c) {
2147      if (&(c->mesa) != _mesa_get_current_context()) {
2148	 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
2149      }
2150   }
2151   else {
2152      _mesa_make_current(NULL, NULL, NULL);
2153   }
2154   return GL_TRUE;
2155}
2156
2157
2158GLboolean XMesaLoseCurrent(XMesaContext c)
2159{
2160   (void) c;
2161   _mesa_make_current(NULL, NULL, NULL);
2162   return GL_TRUE;
2163}
2164
2165
2166/*
2167 * Switch 3Dfx support hack between window and full-screen mode.
2168 */
2169GLboolean XMesaSetFXmode( GLint mode )
2170{
2171#ifdef FX
2172   const char *fx = _mesa_getenv("MESA_GLX_FX");
2173   if (fx && fx[0] != 'd') {
2174      GET_CURRENT_CONTEXT(ctx);
2175      GrHwConfiguration hw;
2176      if (!FX_grSstQueryHardware(&hw)) {
2177         /*fprintf(stderr, "!grSstQueryHardware\n");*/
2178         return GL_FALSE;
2179      }
2180      if (hw.num_sst < 1) {
2181         /*fprintf(stderr, "hw.num_sst < 1\n");*/
2182         return GL_FALSE;
2183      }
2184      if (ctx) {
2185         /* [dBorca] Hack alert:
2186	  * oh, this is sooo wrong: ctx above is
2187	  * really an fxMesaContext, not an XMesaContext
2188	  */
2189         XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2190         if (mode == XMESA_FX_WINDOW) {
2191	    if (xmbuf->FXisHackUsable) {
2192	       FX_grSstControl(GR_CONTROL_DEACTIVATE);
2193	       xmbuf->FXwindowHack = GL_TRUE;
2194	       return GL_TRUE;
2195	    }
2196	 }
2197	 else if (mode == XMESA_FX_FULLSCREEN) {
2198	    FX_grSstControl(GR_CONTROL_ACTIVATE);
2199	    xmbuf->FXwindowHack = GL_FALSE;
2200	    return GL_TRUE;
2201	 }
2202	 else {
2203	    /* Error: Bad mode value */
2204	 }
2205      }
2206   }
2207   /*fprintf(stderr, "fallthrough\n");*/
2208#else
2209   (void) mode;
2210#endif
2211   return GL_FALSE;
2212}
2213
2214
2215
2216#ifdef FX
2217/*
2218 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2219 */
2220static void FXgetImage( XMesaBuffer b )
2221{
2222   GET_CURRENT_CONTEXT(ctx);
2223   static unsigned short pixbuf[MAX_WIDTH];
2224   GLuint x, y;
2225   int xpos, ypos;
2226   XMesaWindow root;
2227   unsigned int bw, depth, width, height;
2228   XMesaContext xmesa = XMESA_CONTEXT(ctx);
2229
2230#ifdef XFree86Server
2231   x = b->frontxrb->pixmap->x;
2232   y = b->frontxrb->pixmap->y;
2233   width = b->frontxrb->pixmap->width;
2234   height = b->frontxrb->pixmap->height;
2235   depth = b->frontxrb->pixmap->depth;
2236#else
2237   XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap,
2238                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2239#endif
2240   if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) {
2241      b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width);
2242      b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height);
2243      if (b->mesa_buffer.Width & 1)
2244         b->mesa_buffer.Width--;  /* prevent odd width */
2245      xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height);
2246   }
2247
2248   /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
2249   /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
2250   if (b->xm_visual->undithered_pf==PF_5R6G5B) {
2251      /* Special case: 16bpp RGB */
2252      grLfbReadRegion( GR_BUFFER_FRONTBUFFER,       /* src buffer */
2253                       0, b->FXctx->height - b->mesa_buffer.Height,  /*pos*/
2254                       b->mesa_buffer.Width, b->mesa_buffer.Height,  /* size */
2255                       b->mesa_buffer.Width * sizeof(GLushort), /* stride */
2256                       b->backxrb->ximage->data);         /* dest buffer */
2257   }
2258   else if (b->xm_visual->dithered_pf==PF_Dither
2259	    && GET_VISUAL_DEPTH(b->xm_visual)==8) {
2260      /* Special case: 8bpp RGB */
2261      for (y=0;y<b->mesa_buffer.Height;y++) {
2262         GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data
2263                        + b->backxrb->ximage->bytes_per_line * y;
2264         XDITHER_SETUP(y);
2265
2266         /* read row from 3Dfx frame buffer */
2267         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2268                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2269                          b->mesa_buffer.Width, 1,
2270                          0,
2271                          pixbuf );
2272
2273         /* write to XImage back buffer */
2274         for (x=0;x<b->mesa_buffer.Width;x++) {
2275            GLubyte r = (pixbuf[x] & 0xf800) >> 8;
2276            GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
2277            GLubyte b = (pixbuf[x] & 0x001f) << 3;
2278            *ptr++ = XDITHER( x, r, g, b);
2279         }
2280      }
2281   }
2282   else {
2283      /* General case: slow! */
2284      for (y=0;y<b->mesa_buffer.Height;y++) {
2285         /* read row from 3Dfx frame buffer */
2286         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2287                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2288                          b->mesa_buffer.Width, 1,
2289                          0,
2290                          pixbuf );
2291
2292         /* write to XImage back buffer */
2293         for (x=0;x<b->mesa_buffer.Width;x++) {
2294            XMesaPutPixel(b->backxrb->ximage,x,y,
2295			  xmesa_color_to_pixel(ctx,
2296					       (pixbuf[x] & 0xf800) >> 8,
2297					       (pixbuf[x] & 0x07e0) >> 3,
2298					       (pixbuf[x] & 0x001f) << 3,
2299					       0xff,
2300                                               b->xm_visual->undithered_pf));
2301         }
2302      }
2303   }
2304   /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
2305}
2306#endif
2307
2308
2309/*
2310 * Copy the back buffer to the front buffer.  If there's no back buffer
2311 * this is a no-op.
2312 */
2313void XMesaSwapBuffers( XMesaBuffer b )
2314{
2315   GET_CURRENT_CONTEXT(ctx);
2316
2317   if (!b->backxrb) {
2318      /* single buffered */
2319      return;
2320   }
2321
2322   /* If we're swapping the buffer associated with the current context
2323    * we have to flush any pending rendering commands first.
2324    */
2325   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2326      _mesa_notifySwapBuffers(ctx);
2327
2328   if (b->db_mode) {
2329#ifdef FX
2330      if (b->FXctx) {
2331         fxMesaSwapBuffers();
2332
2333         if (b->FXwindowHack)
2334            FXgetImage(b);
2335         else
2336            return;
2337      }
2338#endif
2339     if (b->backxrb->ximage) {
2340	 /* Copy Ximage from host's memory to server's window */
2341#if defined(USE_XSHM) && !defined(XFree86Server)
2342	 if (b->shm) {
2343            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2344	    XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2345			  b->swapgc,
2346			  b->backxrb->ximage, 0, 0,
2347			  0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2348                          False );
2349            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2350	 }
2351	 else
2352#endif
2353         {
2354            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2355            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2356			   b->swapgc,
2357			   b->backxrb->ximage, 0, 0,
2358			   0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
2359            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2360         }
2361      }
2362      else {
2363	 /* Copy pixmap to window on server */
2364         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2365	 XMesaCopyArea( b->xm_visual->display,
2366			b->backxrb->pixmap,   /* source drawable */
2367			b->frontxrb->drawable,  /* dest. drawable */
2368			b->swapgc,
2369			0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2370			0, 0                 /* dest region */
2371		      );
2372         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2373      }
2374   }
2375#if !defined(XFree86Server)
2376   XSync( b->xm_visual->display, False );
2377#endif
2378}
2379
2380
2381
2382/*
2383 * Copy sub-region of back buffer to front buffer
2384 */
2385void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2386{
2387   GET_CURRENT_CONTEXT(ctx);
2388
2389   /* If we're swapping the buffer associated with the current context
2390    * we have to flush any pending rendering commands first.
2391    */
2392   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2393      _mesa_notifySwapBuffers(ctx);
2394
2395   if (!b->backxrb) {
2396      /* single buffered */
2397      return;
2398   }
2399
2400   if (b->db_mode) {
2401      int yTop = b->mesa_buffer.Height - y - height;
2402#ifdef FX
2403      if (b->FXctx) {
2404         fxMesaSwapBuffers();
2405         if (b->FXwindowHack)
2406            FXgetImage(b);
2407         else
2408            return;
2409      }
2410#endif
2411      if (b->backxrb->ximage) {
2412         /* Copy Ximage from host's memory to server's window */
2413#if defined(USE_XSHM) && !defined(XFree86Server)
2414         if (b->shm) {
2415            /* XXX assuming width and height aren't too large! */
2416            XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2417                          b->swapgc,
2418                          b->backxrb->ximage, x, yTop,
2419                          x, yTop, width, height, False );
2420            /* wait for finished event??? */
2421         }
2422         else
2423#endif
2424         {
2425            /* XXX assuming width and height aren't too large! */
2426            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2427			   b->swapgc,
2428			   b->backxrb->ximage, x, yTop,
2429			   x, yTop, width, height );
2430         }
2431      }
2432      else {
2433         /* Copy pixmap to window on server */
2434         XMesaCopyArea( b->xm_visual->display,
2435			b->backxrb->pixmap,           /* source drawable */
2436			b->frontxrb->drawable,        /* dest. drawable */
2437			b->swapgc,
2438			x, yTop, width, height,  /* source region */
2439			x, yTop                  /* dest region */
2440                      );
2441      }
2442   }
2443}
2444
2445
2446/*
2447 * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
2448 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2449 * back buffer directly.
2450 * Output:  pixmap - pointer to back buffer's Pixmap, or 0
2451 *          ximage - pointer to back buffer's XImage, or NULL
2452 * Return:  GL_TRUE = context is double buffered
2453 *          GL_FALSE = context is single buffered
2454 */
2455#ifndef XFree86Server
2456GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2457                              XMesaPixmap *pixmap,
2458                              XMesaImage **ximage )
2459{
2460   if (b->db_mode) {
2461      if (pixmap)
2462         *pixmap = b->backxrb->pixmap;
2463      if (ximage)
2464         *ximage = b->backxrb->ximage;
2465      return GL_TRUE;
2466   }
2467   else {
2468      *pixmap = 0;
2469      *ximage = NULL;
2470      return GL_FALSE;
2471   }
2472}
2473#endif /* XFree86Server */
2474
2475
2476/*
2477 * Return the depth buffer associated with an XMesaBuffer.
2478 * Input:  b - the XMesa buffer handle
2479 * Output:  width, height - size of buffer in pixels
2480 *          bytesPerValue - bytes per depth value (2 or 4)
2481 *          buffer - pointer to depth buffer values
2482 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
2483 */
2484GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2485                               GLint *bytesPerValue, void **buffer )
2486{
2487   struct gl_renderbuffer *rb
2488      = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
2489   if (!rb || !rb->Data) {
2490      *width = 0;
2491      *height = 0;
2492      *bytesPerValue = 0;
2493      *buffer = 0;
2494      return GL_FALSE;
2495   }
2496   else {
2497      *width = b->mesa_buffer.Width;
2498      *height = b->mesa_buffer.Height;
2499      *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
2500         ? sizeof(GLushort) : sizeof(GLuint);
2501      *buffer = rb->Data;
2502      return GL_TRUE;
2503   }
2504}
2505
2506
2507void XMesaFlush( XMesaContext c )
2508{
2509   if (c && c->xm_visual) {
2510#ifdef XFree86Server
2511      /* NOT_NEEDED */
2512#else
2513      XSync( c->xm_visual->display, False );
2514#endif
2515   }
2516}
2517
2518
2519
2520const char *XMesaGetString( XMesaContext c, int name )
2521{
2522   (void) c;
2523   if (name==XMESA_VERSION) {
2524      return "5.0";
2525   }
2526   else if (name==XMESA_EXTENSIONS) {
2527      return "";
2528   }
2529   else {
2530      return NULL;
2531   }
2532}
2533
2534
2535
2536XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2537{
2538   XMesaBuffer b;
2539   for (b=XMesaBufferList; b; b=b->Next) {
2540      if (b->frontxrb->drawable == d && b->display == dpy) {
2541         return b;
2542      }
2543   }
2544   return NULL;
2545}
2546
2547
2548
2549/*
2550 * Look for XMesaBuffers whose X window has been destroyed.
2551 * Deallocate any such XMesaBuffers.
2552 */
2553void XMesaGarbageCollect( void )
2554{
2555   XMesaBuffer b, next;
2556   for (b=XMesaBufferList; b; b=next) {
2557      next = b->Next;
2558      if (b->display && b->frontxrb->drawable && b->type == WINDOW) {
2559#ifdef XFree86Server
2560	 /* NOT_NEEDED */
2561#else
2562         XSync(b->display, False);
2563         if (!window_exists( b->display, b->frontxrb->drawable )) {
2564            /* found a dead window, free the ancillary info */
2565            XMesaDestroyBuffer( b );
2566         }
2567#endif
2568      }
2569   }
2570}
2571
2572
2573void XMesaReset( void )
2574{
2575    while (XMesaBufferList)
2576	XMesaDestroyBuffer(XMesaBufferList);
2577
2578    XMesaBufferList = NULL;
2579}
2580
2581
2582unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2583                                GLfloat red, GLfloat green,
2584                                GLfloat blue, GLfloat alpha )
2585{
2586   GLcontext *ctx = &xmesa->mesa;
2587   GLint r = (GLint) (red   * 255.0F);
2588   GLint g = (GLint) (green * 255.0F);
2589   GLint b = (GLint) (blue  * 255.0F);
2590   GLint a = (GLint) (alpha * 255.0F);
2591
2592   switch (xmesa->pixelformat) {
2593      case PF_Index:
2594         return 0;
2595      case PF_Truecolor:
2596         {
2597            unsigned long p;
2598            PACK_TRUECOLOR( p, r, g, b );
2599            return p;
2600         }
2601      case PF_8A8B8G8R:
2602         return PACK_8A8B8G8R( r, g, b, a );
2603      case PF_8A8R8G8B:
2604         return PACK_8A8R8G8B( r, g, b, a );
2605      case PF_8R8G8B:
2606         return PACK_8R8G8B( r, g, b );
2607      case PF_5R6G5B:
2608         return PACK_5R6G5B( r, g, b );
2609      case PF_Dither:
2610         {
2611            DITHER_SETUP;
2612            return DITHER( x, y, r, g, b );
2613         }
2614      case PF_1Bit:
2615         /* 382 = (3*255)/2 */
2616         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2617      case PF_HPCR:
2618         return DITHER_HPCR(x, y, r, g, b);
2619      case PF_Lookup:
2620         {
2621            LOOKUP_SETUP;
2622            return LOOKUP( r, g, b );
2623         }
2624      case PF_Grayscale:
2625         return GRAY_RGB( r, g, b );
2626      case PF_Dither_5R6G5B:
2627         /* fall through */
2628      case PF_Dither_True:
2629         {
2630            unsigned long p;
2631            PACK_TRUEDITHER(p, x, y, r, g, b);
2632            return p;
2633         }
2634      default:
2635         _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2636   }
2637   return 0;
2638}
2639
2640
2641/*
2642 * This is typically called when the window size changes and we need
2643 * to reallocate the buffer's back/depth/stencil/accum buffers.
2644 */
2645void XMesaResizeBuffers( XMesaBuffer b )
2646{
2647#ifdef XFree86Server
2648   GLuint winwidth, winheight;
2649   GET_CURRENT_CONTEXT(ctx);
2650
2651   winwidth = MIN2(b->frontxrb->drawable->width, MAX_WIDTH);
2652   winheight = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT);
2653
2654   xmesa_resize_buffers(ctx, &(b->mesa_buffer), winwidth, winheight);
2655#else
2656   Window root;
2657   int xpos, ypos;
2658   unsigned int width, height, bw, depth;
2659   GET_CURRENT_CONTEXT(ctx);
2660   XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap,
2661                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2662   xmesa_resize_buffers(ctx, &(b->mesa_buffer), width, height);
2663#endif
2664}
2665
2666