xm_api.c revision 32c3957991bd0e1df744d866943a8c47b2757c9e
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, 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, 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   _mesa_meta_free( mesaCtx );
1472
1473   _swsetup_DestroyContext( mesaCtx );
1474   _swrast_DestroyContext( mesaCtx );
1475   _tnl_DestroyContext( mesaCtx );
1476   _vbo_DestroyContext( mesaCtx );
1477   _mesa_free_context_data( mesaCtx );
1478   free( c );
1479}
1480
1481
1482
1483/**
1484 * Private function for creating an XMesaBuffer which corresponds to an
1485 * X window or pixmap.
1486 * \param v  the window's XMesaVisual
1487 * \param w  the window we're wrapping
1488 * \return  new XMesaBuffer or NULL if error
1489 */
1490PUBLIC XMesaBuffer
1491XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
1492{
1493   XWindowAttributes attr;
1494   XMesaBuffer b;
1495   XMesaColormap cmap;
1496   int depth;
1497
1498   assert(v);
1499   assert(w);
1500
1501   /* Check that window depth matches visual depth */
1502   XGetWindowAttributes( v->display, w, &attr );
1503   depth = attr.depth;
1504   if (GET_VISUAL_DEPTH(v) != depth) {
1505      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1506                    GET_VISUAL_DEPTH(v), depth);
1507      return NULL;
1508   }
1509
1510   /* Find colormap */
1511   if (attr.colormap) {
1512      cmap = attr.colormap;
1513   }
1514   else {
1515      _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
1516      /* this is weird, a window w/out a colormap!? */
1517      /* OK, let's just allocate a new one and hope for the best */
1518      cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1519   }
1520
1521   b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap);
1522   if (!b)
1523      return NULL;
1524
1525   if (!initialize_visual_and_buffer( v, b, (XMesaDrawable) w, cmap )) {
1526      xmesa_free_buffer(b);
1527      return NULL;
1528   }
1529
1530   return b;
1531}
1532
1533
1534
1535/**
1536 * Create a new XMesaBuffer from an X pixmap.
1537 *
1538 * \param v    the XMesaVisual
1539 * \param p    the pixmap
1540 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1541 *             \c GLX_DIRECT_COLOR visual for the pixmap
1542 * \returns new XMesaBuffer or NULL if error
1543 */
1544PUBLIC XMesaBuffer
1545XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
1546{
1547   XMesaBuffer b;
1548
1549   assert(v);
1550
1551   b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
1552   if (!b)
1553      return NULL;
1554
1555   if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) {
1556      xmesa_free_buffer(b);
1557      return NULL;
1558   }
1559
1560   return b;
1561}
1562
1563
1564/**
1565 * For GLX_EXT_texture_from_pixmap
1566 */
1567XMesaBuffer
1568XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p,
1569                               XMesaColormap cmap,
1570                               int format, int target, int mipmap)
1571{
1572   GET_CURRENT_CONTEXT(ctx);
1573   XMesaBuffer b;
1574   GLuint width, height;
1575
1576   assert(v);
1577
1578   b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
1579   if (!b)
1580      return NULL;
1581
1582   /* get pixmap size, update framebuffer/renderbuffer dims */
1583   xmesa_get_window_size(v->display, b, &width, &height);
1584   _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height);
1585
1586   if (target == 0) {
1587      /* examine dims */
1588      if (ctx->Extensions.ARB_texture_non_power_of_two) {
1589         target = GLX_TEXTURE_2D_EXT;
1590      }
1591      else if (   _mesa_bitcount(width)  == 1
1592               && _mesa_bitcount(height) == 1) {
1593         /* power of two size */
1594         if (height == 1) {
1595            target = GLX_TEXTURE_1D_EXT;
1596         }
1597         else {
1598            target = GLX_TEXTURE_2D_EXT;
1599         }
1600      }
1601      else if (ctx->Extensions.NV_texture_rectangle) {
1602         target = GLX_TEXTURE_RECTANGLE_EXT;
1603      }
1604      else {
1605         /* non power of two textures not supported */
1606         XMesaDestroyBuffer(b);
1607         return 0;
1608      }
1609   }
1610
1611   b->TextureTarget = target;
1612   b->TextureFormat = format;
1613   b->TextureMipmap = mipmap;
1614
1615   if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) {
1616      xmesa_free_buffer(b);
1617      return NULL;
1618   }
1619
1620   return b;
1621}
1622
1623
1624
1625XMesaBuffer
1626XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
1627                   unsigned int width, unsigned int height)
1628{
1629   XMesaWindow root;
1630   XMesaDrawable drawable;  /* X Pixmap Drawable */
1631   XMesaBuffer b;
1632
1633   /* allocate pixmap for front buffer */
1634   root = RootWindow( v->display, v->visinfo->screen );
1635   drawable = XCreatePixmap(v->display, root, width, height,
1636                            v->visinfo->depth);
1637   if (!drawable)
1638      return NULL;
1639
1640   b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
1641   if (!b)
1642      return NULL;
1643
1644   if (!initialize_visual_and_buffer(v, b, drawable, cmap)) {
1645      xmesa_free_buffer(b);
1646      return NULL;
1647   }
1648
1649   return b;
1650}
1651
1652
1653
1654/*
1655 * Deallocate an XMesaBuffer structure and all related info.
1656 */
1657PUBLIC void
1658XMesaDestroyBuffer(XMesaBuffer b)
1659{
1660   xmesa_free_buffer(b);
1661}
1662
1663
1664/**
1665 * Query the current window size and update the corresponding struct gl_framebuffer
1666 * and all attached renderbuffers.
1667 * Called when:
1668 *  1. the first time a buffer is bound to a context.
1669 *  2. from glViewport to poll for window size changes
1670 *  3. from the XMesaResizeBuffers() API function.
1671 * Note: it's possible (and legal) for xmctx to be NULL.  That can happen
1672 * when resizing a buffer when no rendering context is bound.
1673 */
1674void
1675xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
1676{
1677   GLuint width, height;
1678   xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height);
1679   if (drawBuffer->mesa_buffer.Width != width ||
1680       drawBuffer->mesa_buffer.Height != height) {
1681      struct gl_context *ctx = xmctx ? &xmctx->mesa : NULL;
1682      _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height);
1683   }
1684   drawBuffer->mesa_buffer.Initialized = GL_TRUE; /* XXX TEMPORARY? */
1685}
1686
1687
1688/*
1689 * Bind buffer b to context c and make c the current rendering context.
1690 */
1691GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
1692{
1693   return XMesaMakeCurrent2( c, b, b );
1694}
1695
1696
1697/*
1698 * Bind buffer b to context c and make c the current rendering context.
1699 */
1700PUBLIC
1701GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1702                             XMesaBuffer readBuffer )
1703{
1704   if (c) {
1705      if (!drawBuffer || !readBuffer)
1706         return GL_FALSE;  /* must specify buffers! */
1707
1708      if (&(c->mesa) == _mesa_get_current_context()
1709          && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
1710          && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
1711          && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) {
1712         /* same context and buffer, do nothing */
1713         return GL_TRUE;
1714      }
1715
1716      c->xm_buffer = drawBuffer;
1717
1718      /* Call this periodically to detect when the user has begun using
1719       * GL rendering from multiple threads.
1720       */
1721      _glapi_check_multithread();
1722
1723      xmesa_check_and_update_buffer_size(c, drawBuffer);
1724      if (readBuffer != drawBuffer)
1725         xmesa_check_and_update_buffer_size(c, readBuffer);
1726
1727      _mesa_make_current(&(c->mesa),
1728                         &drawBuffer->mesa_buffer,
1729                         &readBuffer->mesa_buffer);
1730
1731      /*
1732       * Must recompute and set these pixel values because colormap
1733       * can be different for different windows.
1734       */
1735      c->clearpixel = xmesa_color_to_pixel( &c->mesa,
1736					    c->clearcolor[0],
1737					    c->clearcolor[1],
1738					    c->clearcolor[2],
1739					    c->clearcolor[3],
1740					    c->xm_visual->undithered_pf);
1741      XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
1742
1743      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1744      drawBuffer->wasCurrent = GL_TRUE;
1745   }
1746   else {
1747      /* Detach */
1748      _mesa_make_current( NULL, NULL, NULL );
1749   }
1750   return GL_TRUE;
1751}
1752
1753
1754/*
1755 * Unbind the context c from its buffer.
1756 */
1757GLboolean XMesaUnbindContext( XMesaContext c )
1758{
1759   /* A no-op for XFree86 integration purposes */
1760   return GL_TRUE;
1761}
1762
1763
1764XMesaContext XMesaGetCurrentContext( void )
1765{
1766   GET_CURRENT_CONTEXT(ctx);
1767   if (ctx) {
1768      XMesaContext xmesa = XMESA_CONTEXT(ctx);
1769      return xmesa;
1770   }
1771   else {
1772      return 0;
1773   }
1774}
1775
1776
1777XMesaBuffer XMesaGetCurrentBuffer( void )
1778{
1779   GET_CURRENT_CONTEXT(ctx);
1780   if (ctx) {
1781      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
1782      return xmbuf;
1783   }
1784   else {
1785      return 0;
1786   }
1787}
1788
1789
1790/* New in Mesa 3.1 */
1791XMesaBuffer XMesaGetCurrentReadBuffer( void )
1792{
1793   GET_CURRENT_CONTEXT(ctx);
1794   if (ctx) {
1795      return XMESA_BUFFER(ctx->ReadBuffer);
1796   }
1797   else {
1798      return 0;
1799   }
1800}
1801
1802
1803
1804GLboolean XMesaSetFXmode( GLint mode )
1805{
1806   (void) mode;
1807   return GL_FALSE;
1808}
1809
1810
1811
1812/*
1813 * Copy the back buffer to the front buffer.  If there's no back buffer
1814 * this is a no-op.
1815 */
1816PUBLIC
1817void XMesaSwapBuffers( XMesaBuffer b )
1818{
1819   GET_CURRENT_CONTEXT(ctx);
1820
1821   if (!b->backxrb) {
1822      /* single buffered */
1823      return;
1824   }
1825
1826   /* If we're swapping the buffer associated with the current context
1827    * we have to flush any pending rendering commands first.
1828    */
1829   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
1830      _mesa_notifySwapBuffers(ctx);
1831
1832   if (b->db_mode) {
1833      if (b->backxrb->ximage) {
1834	 /* Copy Ximage (back buf) from client memory to server window */
1835#if defined(USE_XSHM)
1836	 if (b->shm) {
1837            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1838	    XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
1839			  b->swapgc,
1840			  b->backxrb->ximage, 0, 0,
1841			  0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
1842                          False );
1843            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1844	 }
1845	 else
1846#endif
1847         {
1848            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1849            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
1850			   b->swapgc,
1851			   b->backxrb->ximage, 0, 0,
1852			   0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
1853            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1854         }
1855      }
1856      else if (b->backxrb->pixmap) {
1857	 /* Copy pixmap (back buf) to window (front buf) on server */
1858         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1859	 XMesaCopyArea( b->xm_visual->display,
1860			b->backxrb->pixmap,   /* source drawable */
1861			b->frontxrb->drawable,  /* dest. drawable */
1862			b->swapgc,
1863			0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
1864			0, 0                 /* dest region */
1865		      );
1866         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1867      }
1868
1869      if (b->swAlpha)
1870         _mesa_copy_soft_alpha_renderbuffers(ctx, &b->mesa_buffer);
1871   }
1872   XSync( b->xm_visual->display, False );
1873}
1874
1875
1876
1877/*
1878 * Copy sub-region of back buffer to front buffer
1879 */
1880void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
1881{
1882   GET_CURRENT_CONTEXT(ctx);
1883
1884   /* If we're swapping the buffer associated with the current context
1885    * we have to flush any pending rendering commands first.
1886    */
1887   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
1888      _mesa_notifySwapBuffers(ctx);
1889
1890   if (!b->backxrb) {
1891      /* single buffered */
1892      return;
1893   }
1894
1895   if (b->db_mode) {
1896      int yTop = b->mesa_buffer.Height - y - height;
1897      if (b->backxrb->ximage) {
1898         /* Copy Ximage from host's memory to server's window */
1899#if defined(USE_XSHM)
1900         if (b->shm) {
1901            /* XXX assuming width and height aren't too large! */
1902            XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
1903                          b->swapgc,
1904                          b->backxrb->ximage, x, yTop,
1905                          x, yTop, width, height, False );
1906            /* wait for finished event??? */
1907         }
1908         else
1909#endif
1910         {
1911            /* XXX assuming width and height aren't too large! */
1912            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
1913			   b->swapgc,
1914			   b->backxrb->ximage, x, yTop,
1915			   x, yTop, width, height );
1916         }
1917      }
1918      else {
1919         /* Copy pixmap to window on server */
1920         XMesaCopyArea( b->xm_visual->display,
1921			b->backxrb->pixmap,           /* source drawable */
1922			b->frontxrb->drawable,        /* dest. drawable */
1923			b->swapgc,
1924			x, yTop, width, height,  /* source region */
1925			x, yTop                  /* dest region */
1926                      );
1927      }
1928   }
1929}
1930
1931
1932/*
1933 * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
1934 * is a way to get "under the hood" of X/Mesa so one can manipulate the
1935 * back buffer directly.
1936 * Output:  pixmap - pointer to back buffer's Pixmap, or 0
1937 *          ximage - pointer to back buffer's XImage, or NULL
1938 * Return:  GL_TRUE = context is double buffered
1939 *          GL_FALSE = context is single buffered
1940 */
1941GLboolean XMesaGetBackBuffer( XMesaBuffer b,
1942                              XMesaPixmap *pixmap,
1943                              XMesaImage **ximage )
1944{
1945   if (b->db_mode) {
1946      if (pixmap)
1947         *pixmap = b->backxrb->pixmap;
1948      if (ximage)
1949         *ximage = b->backxrb->ximage;
1950      return GL_TRUE;
1951   }
1952   else {
1953      *pixmap = 0;
1954      *ximage = NULL;
1955      return GL_FALSE;
1956   }
1957}
1958
1959
1960/*
1961 * Return the depth buffer associated with an XMesaBuffer.
1962 * Input:  b - the XMesa buffer handle
1963 * Output:  width, height - size of buffer in pixels
1964 *          bytesPerValue - bytes per depth value (2 or 4)
1965 *          buffer - pointer to depth buffer values
1966 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1967 */
1968GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
1969                               GLint *bytesPerValue, void **buffer )
1970{
1971   struct gl_renderbuffer *rb
1972      = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
1973   if (!rb || !rb->Data) {
1974      *width = 0;
1975      *height = 0;
1976      *bytesPerValue = 0;
1977      *buffer = 0;
1978      return GL_FALSE;
1979   }
1980   else {
1981      *width = b->mesa_buffer.Width;
1982      *height = b->mesa_buffer.Height;
1983      *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
1984         ? sizeof(GLushort) : sizeof(GLuint);
1985      *buffer = rb->Data;
1986      return GL_TRUE;
1987   }
1988}
1989
1990
1991void XMesaFlush( XMesaContext c )
1992{
1993   if (c && c->xm_visual) {
1994      XSync( c->xm_visual->display, False );
1995   }
1996}
1997
1998
1999
2000const char *XMesaGetString( XMesaContext c, int name )
2001{
2002   (void) c;
2003   if (name==XMESA_VERSION) {
2004      return "5.0";
2005   }
2006   else if (name==XMESA_EXTENSIONS) {
2007      return "";
2008   }
2009   else {
2010      return NULL;
2011   }
2012}
2013
2014
2015
2016XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2017{
2018   XMesaBuffer b;
2019   for (b=XMesaBufferList; b; b=b->Next) {
2020      if (b->frontxrb->drawable == d && b->display == dpy) {
2021         return b;
2022      }
2023   }
2024   return NULL;
2025}
2026
2027
2028/**
2029 * Free/destroy all XMesaBuffers associated with given display.
2030 */
2031void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
2032{
2033   XMesaBuffer b, next;
2034   for (b = XMesaBufferList; b; b = next) {
2035      next = b->Next;
2036      if (b->display == dpy) {
2037         xmesa_free_buffer(b);
2038      }
2039   }
2040}
2041
2042
2043/*
2044 * Look for XMesaBuffers whose X window has been destroyed.
2045 * Deallocate any such XMesaBuffers.
2046 */
2047void XMesaGarbageCollect( XMesaDisplay* dpy )
2048{
2049   XMesaBuffer b, next;
2050   for (b=XMesaBufferList; b; b=next) {
2051      next = b->Next;
2052      if (b->display && b->display == dpy && b->frontxrb->drawable && b->type == WINDOW) {
2053         XSync(b->display, False);
2054         if (!window_exists( b->display, b->frontxrb->drawable )) {
2055            /* found a dead window, free the ancillary info */
2056            XMesaDestroyBuffer( b );
2057         }
2058      }
2059   }
2060}
2061
2062
2063unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2064                                GLfloat red, GLfloat green,
2065                                GLfloat blue, GLfloat alpha )
2066{
2067   struct gl_context *ctx = &xmesa->mesa;
2068   GLint r = (GLint) (red   * 255.0F);
2069   GLint g = (GLint) (green * 255.0F);
2070   GLint b = (GLint) (blue  * 255.0F);
2071   GLint a = (GLint) (alpha * 255.0F);
2072
2073   switch (xmesa->pixelformat) {
2074      case PF_Index:
2075         return 0;
2076      case PF_Truecolor:
2077         {
2078            unsigned long p;
2079            PACK_TRUECOLOR( p, r, g, b );
2080            return p;
2081         }
2082      case PF_8A8B8G8R:
2083         return PACK_8A8B8G8R( r, g, b, a );
2084      case PF_8A8R8G8B:
2085         return PACK_8A8R8G8B( r, g, b, a );
2086      case PF_8R8G8B:
2087         return PACK_8R8G8B( r, g, b );
2088      case PF_5R6G5B:
2089         return PACK_5R6G5B( r, g, b );
2090      case PF_Dither:
2091         {
2092            DITHER_SETUP;
2093            return DITHER( x, y, r, g, b );
2094         }
2095      case PF_1Bit:
2096         /* 382 = (3*255)/2 */
2097         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2098      case PF_HPCR:
2099         return DITHER_HPCR(x, y, r, g, b);
2100      case PF_Lookup:
2101         {
2102            LOOKUP_SETUP;
2103            return LOOKUP( r, g, b );
2104         }
2105      case PF_Grayscale:
2106         return GRAY_RGB( r, g, b );
2107      case PF_Dither_5R6G5B:
2108         /* fall through */
2109      case PF_Dither_True:
2110         {
2111            unsigned long p;
2112            PACK_TRUEDITHER(p, x, y, r, g, b);
2113            return p;
2114         }
2115      default:
2116         _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2117   }
2118   return 0;
2119}
2120
2121
2122/*
2123 * This is typically called when the window size changes and we need
2124 * to reallocate the buffer's back/depth/stencil/accum buffers.
2125 */
2126PUBLIC void
2127XMesaResizeBuffers( XMesaBuffer b )
2128{
2129   GET_CURRENT_CONTEXT(ctx);
2130   XMesaContext xmctx = XMESA_CONTEXT(ctx);
2131   if (!xmctx)
2132      return;
2133   xmesa_check_and_update_buffer_size(xmctx, b);
2134}
2135
2136
2137static GLint
2138xbuffer_to_renderbuffer(int buffer)
2139{
2140   assert(MAX_AUX_BUFFERS <= 4);
2141
2142   switch (buffer) {
2143   case GLX_FRONT_LEFT_EXT:
2144      return BUFFER_FRONT_LEFT;
2145   case GLX_FRONT_RIGHT_EXT:
2146      return BUFFER_FRONT_RIGHT;
2147   case GLX_BACK_LEFT_EXT:
2148      return BUFFER_BACK_LEFT;
2149   case GLX_BACK_RIGHT_EXT:
2150      return BUFFER_BACK_RIGHT;
2151   case GLX_AUX0_EXT:
2152      return BUFFER_AUX0;
2153   case GLX_AUX1_EXT:
2154   case GLX_AUX2_EXT:
2155   case GLX_AUX3_EXT:
2156   case GLX_AUX4_EXT:
2157   case GLX_AUX5_EXT:
2158   case GLX_AUX6_EXT:
2159   case GLX_AUX7_EXT:
2160   case GLX_AUX8_EXT:
2161   case GLX_AUX9_EXT:
2162   default:
2163      /* BadValue error */
2164      return -1;
2165   }
2166}
2167
2168
2169PUBLIC void
2170XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
2171                  const int *attrib_list)
2172{
2173#if 0
2174   GET_CURRENT_CONTEXT(ctx);
2175   const GLuint unit = ctx->Texture.CurrentUnit;
2176   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
2177   struct gl_texture_object *texObj;
2178#endif
2179   struct gl_renderbuffer *rb;
2180   struct xmesa_renderbuffer *xrb;
2181   GLint b;
2182   XMesaImage *img = NULL;
2183   GLboolean freeImg = GL_FALSE;
2184
2185   b = xbuffer_to_renderbuffer(buffer);
2186   if (b < 0)
2187      return;
2188
2189   if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT)
2190      return; /* BadMatch error */
2191
2192   rb = drawable->mesa_buffer.Attachment[b].Renderbuffer;
2193   if (!rb) {
2194      /* invalid buffer */
2195      return;
2196   }
2197   xrb = xmesa_renderbuffer(rb);
2198
2199#if 0
2200   switch (drawable->TextureTarget) {
2201   case GLX_TEXTURE_1D_EXT:
2202      texObj = texUnit->CurrentTex[TEXTURE_1D_INDEX];
2203      break;
2204   case GLX_TEXTURE_2D_EXT:
2205      texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX];
2206      break;
2207   case GLX_TEXTURE_RECTANGLE_EXT:
2208      texObj = texUnit->CurrentTex[TEXTURE_RECT_INDEX];
2209      break;
2210   default:
2211      return; /* BadMatch error */
2212   }
2213#endif
2214
2215   /*
2216    * The following is a quick and simple way to implement
2217    * BindTexImage.  The better way is to write some new FetchTexel()
2218    * functions which would extract texels from XImages.  We'd still
2219    * need to use GetImage when texturing from a Pixmap (front buffer)
2220    * but texturing from a back buffer (XImage) would avoid an image
2221    * copy.
2222    */
2223
2224   /* get XImage */
2225   if (xrb->pixmap) {
2226      img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L,
2227			  ZPixmap);
2228      freeImg = GL_TRUE;
2229   }
2230   else if (xrb->ximage) {
2231      img = xrb->ximage;
2232   }
2233
2234   /* store the XImage as a new texture image */
2235   if (img) {
2236      GLenum format, type, intFormat;
2237      if (img->bits_per_pixel == 32) {
2238         format = GL_BGRA;
2239         type = GL_UNSIGNED_BYTE;
2240         intFormat = GL_RGBA;
2241      }
2242      else if (img->bits_per_pixel == 24) {
2243         format = GL_BGR;
2244         type = GL_UNSIGNED_BYTE;
2245         intFormat = GL_RGB;
2246      }
2247      else if (img->bits_per_pixel == 16) {
2248         format = GL_BGR;
2249         type = GL_UNSIGNED_SHORT_5_6_5;
2250         intFormat = GL_RGB;
2251      }
2252      else {
2253         _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage");
2254         return;
2255      }
2256      if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) {
2257         intFormat = GL_RGBA;
2258      }
2259      else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) {
2260         intFormat = GL_RGB;
2261      }
2262
2263      _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0,
2264                       format, type, img->data);
2265
2266      if (freeImg) {
2267	 XMesaDestroyImage(img);
2268      }
2269   }
2270}
2271
2272
2273
2274PUBLIC void
2275XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer)
2276{
2277   const GLint b = xbuffer_to_renderbuffer(buffer);
2278   if (b < 0)
2279      return;
2280
2281   /* no-op for now */
2282}
2283
2284