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