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