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