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