1 #include "sgcf.h"
2 #if defined(HAVE_X11)
3 
4 /* $Id: xmesa1.c,v 1.4 2000/12/31 16:32:58 mholst Exp $ */
5 
6 /*
7  * Mesa 3-D graphics library
8  * Version:  2.2
9  * Copyright (C) 1995-1997  Brian Paul
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the Free
23  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 
26 /*
27  * Mesa/X11 interface, part 1.
28  *
29  * This file contains the implementations of all the XMesa* functions.
30  *
31  *
32  * NOTES:
33  *
34  * The window coordinate system origin (0,0) is in the lower-left corner
35  * of the window.  X11's window coordinate origin is in the upper-left
36  * corner of the window.  Therefore, most drawing functions in this
37  * file have to flip Y coordinates.
38  *
39  * Define SHM in the Makefile with -DSHM if you want to compile in support
40  * for the MIT Shared Memory extension.  If enabled, when you use an Ximage
41  * for the back buffer in double buffered mode, the "swap" operation will
42  * be faster.  You must also link with -lXext.
43  *
44  * Byte swapping:  If the Mesa host and the X display use a different
45  * byte order then there's some trickiness to be aware of when using
46  * XImages.  The byte ordering used for the XImage is that of the X
47  * display, not the Mesa host.
48  * The color-to-pixel encoding for True/DirectColor must be done
49  * according to the display's visual red_mask, green_mask, and blue_mask.
50  * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
51  * do byte swapping if needed.  If one wants to directly "poke" the pixel
52  * into the XImage's buffer then the pixel must be byte swapped first.  In
53  * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
54  * and use XPutPixel everywhere except in the implementation of
55  * glClear(GL_COLOR_BUFFER_BIT).  We want this function to be fast so
56  * instead of using XPutPixel we "poke" our values after byte-swapping
57  * the clear pixel value if needed.
58  *
59  */
60 
61 
62 #include <assert.h>
63 #include <math.h>
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <X11/Xlib.h>
68 #include <X11/Xutil.h>
69 #ifdef SHM
70 #  include <sys/ipc.h>
71 #  include <sys/shm.h>
72 #  include <X11/extensions/XShm.h>
73 #endif
74 #include "GL/xmesa.h"
75 #include "xmesaP.h"
76 #include "context.h"
77 #include "macros.h"
78 #include "matrix.h"
79 #include "types.h"
80 
81 
82 XMesaContext XMesa = NULL;
83 
84 
85 /*
86  * Lookup tables for HPCR pixel format:
87  */
88 static short hpcr_rTbl[256] = {
89  16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
90  24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
91  32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
92  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
93  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
94  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
95  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
96  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
97 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
98 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
99 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
100 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
101 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
102 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
103 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
104 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
105 };
106 
107 static short hpcr_gTbl[256] = {
108  16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
109  24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
110  32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
111  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
112  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
113  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
114  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
115  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
116 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
117 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
118 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
119 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
120 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
121 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
122 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
123 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
124 };
125 
126 static short hpcr_bTbl[256] = {
127  32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
128  40,  40,  41,  41,  42,  42,  43,  43,  44,  44,  45,  45,  46,  46,  47,  47,
129  48,  48,  49,  49,  50,  50,  51,  51,  52,  52,  53,  53,  54,  54,  55,  55,
130  56,  56,  57,  57,  58,  58,  59,  59,  60,  60,  61,  61,  62,  62,  63,  63,
131  64,  64,  65,  65,  66,  66,  67,  67,  68,  68,  69,  69,  70,  70,  71,  71,
132  72,  72,  73,  73,  74,  74,  75,  75,  76,  76,  77,  77,  78,  78,  79,  79,
133  80,  80,  81,  81,  82,  82,  83,  83,  84,  84,  85,  85,  86,  86,  87,  87,
134  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
135  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
136 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
137 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
138 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
139 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
140 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
141 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
142 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
143 };
144 
145 
146 
147 /**********************************************************************/
148 /*****                     X Utility Functions                    *****/
149 /**********************************************************************/
150 
151 
152 /*
153  * X/Mesa Error reporting function:
154  */
error(const char * msg)155 static void error( const char *msg )
156 {
157    fprintf( stderr, "X/Mesa error: %s\n", msg );
158 }
159 
160 
161 /*
162  * Return the host's byte order as LSBFirst or MSBFirst ala X.
163  */
host_byte_order(void)164 static int host_byte_order( void )
165 {
166    int i = 1;
167    char *cptr = (char *) &i;
168    return (*cptr==1) ? LSBFirst : MSBFirst;
169 }
170 
171 
172 
173 /*
174  * Error handling.
175  */
176 static int mesaXErrorFlag = 0;
177 
mesaHandleXError(Display * dpy,XErrorEvent * event)178 static int mesaHandleXError( Display *dpy, XErrorEvent *event )
179 {
180     mesaXErrorFlag = 1;
181     return 0;
182 }
183 
184 
185 /*
186  * Check if the X Shared Memory extension is available.
187  * Return:  0 = not available
188  *          1 = shared XImage support available
189  *          2 = shared Pixmap support available also
190  */
check_for_xshm(Display * display)191 static int check_for_xshm( Display *display )
192 {
193 #ifdef SHM
194    int major, minor, ignore;
195    Bool pixmaps;
196 
197    if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
198       if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
199 	 return (pixmaps==True) ? 2 : 1;
200       }
201       else {
202 	 return 0;
203       }
204    }
205    else {
206       return 0;
207    }
208 #else
209    /* Can't compile XSHM support */
210    return 0;
211 #endif
212 }
213 
214 
215 /*
216  * Return the width and height of the given drawable.
217  */
get_drawable_size(Display * dpy,Drawable d,unsigned int * width,unsigned int * height)218 static void get_drawable_size( Display *dpy, Drawable d,
219 			       unsigned int *width, unsigned int *height )
220 {
221    Window root;
222    int x, y;
223    unsigned int bw, depth;
224 
225    XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth );
226 }
227 
228 
229 
230 /*
231  * Apply gamma correction to an intensity value in [0..max].  Return the
232  * new intensity value.
233  */
gamma_adjust(GLfloat gamma,GLint value,GLint max)234 static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max )
235 {
236    double x = (double) value / (double) max;
237    return (GLint) ((GLfloat) max * pow( x, 1.0F/gamma ) );
238 }
239 
240 
241 
242 /*
243  * Return the true number of bits per pixel for XImages.
244  * For example, if we request a 24-bit deep visual we may actually
245  * get a 32-bit per pixel XImage.  This function gives us this information.
246  * Input:  dpy - the X display
247  *         visinfo - desribes the visual to be used for XImages
248  * Return:  true number of bits per pixel for XImages
249  */
bits_per_pixel(Display * dpy,XVisualInfo * visinfo)250 static int bits_per_pixel( Display *dpy, XVisualInfo *visinfo )
251 {
252    XImage *img;
253    int bitsPerPixel;
254    /* Create a temporary XImage */
255    img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
256                        ZPixmap, 0,           /*format, offset*/
257                        (char*) malloc(8),    /*data*/
258                        1, 1,                 /*width, height*/
259                        32,                   /*bitmap_pad*/
260                        0                     /*bytes_per_line*/
261                      );
262    assert(img);
263    /* grab the bits/pixel value */
264    bitsPerPixel = img->bits_per_pixel;
265    /* free the XImage */
266    free( img->data );
267    img->data = NULL;
268    XDestroyImage( img );
269    return bitsPerPixel;
270 }
271 
272 
273 
274 /**********************************************************************/
275 /*****                      Private Functions                     *****/
276 /**********************************************************************/
277 
278 
279 /*
280  * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
281  * Return:  GL_TRUE if success, GL_FALSE if error
282  */
alloc_shm_back_buffer(XMesaBuffer b)283 static GLboolean alloc_shm_back_buffer( XMesaBuffer b )
284 {
285 #ifdef SHM
286    /*
287     * We have to do a _lot_ of error checking here to be sure we can
288     * really use the XSHM extension.  It seems different servers trigger
289     * errors at different points if the extension won't work.  Therefore
290     * we have to be very careful...
291     */
292    GC gc;
293    int (*old_handler)( Display *, XErrorEvent * );
294 
295    b->backimage = XShmCreateImage( b->xm_visual->display,
296                                    b->xm_visual->visinfo->visual,
297                                    b->xm_visual->visinfo->depth,
298 				   ZPixmap, NULL, &b->shminfo,
299 				   b->width, b->height );
300    if (b->backimage == NULL) {
301       error( "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling." );
302       b->shm = 0;
303       return GL_FALSE;
304    }
305 
306    b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line
307 			     * b->backimage->height, IPC_CREAT|0777 );
308    if (b->shminfo.shmid < 0) {
309       perror("alloc_back_buffer");
310       XDestroyImage( b->backimage );
311       b->backimage = NULL;
312       error( "alloc_back_buffer: Shared memory error (shmget), disabling." );
313       b->shm = 0;
314       return GL_FALSE;
315    }
316 
317    b->shminfo.shmaddr = b->backimage->data
318                       = (char*)shmat( b->shminfo.shmid, 0, 0 );
319    if (b->shminfo.shmaddr == (char *) -1) {
320       perror("alloc_back_buffer");
321       XDestroyImage( b->backimage );
322       shmctl( b->shminfo.shmid, IPC_RMID, 0 );
323       b->backimage = NULL;
324       error("alloc_back_buffer: Shared memory error (shmat), disabling.");
325       b->shm = 0;
326       return GL_FALSE;
327    }
328 
329    b->shminfo.readOnly = False;
330    mesaXErrorFlag = 0;
331    old_handler = XSetErrorHandler( mesaHandleXError );
332    /* This may trigger the X protocol error we're ready to catch: */
333    XShmAttach( b->xm_visual->display, &b->shminfo );
334    XSync( b->xm_visual->display, False );
335 
336    if (mesaXErrorFlag) {
337       /* we are on a remote display, this error is normal, don't print it */
338       XFlush( b->xm_visual->display );
339       mesaXErrorFlag = 0;
340       XDestroyImage( b->backimage );
341       shmdt( b->shminfo.shmaddr );
342       shmctl( b->shminfo.shmid, IPC_RMID, 0 );
343       b->backimage = NULL;
344       b->shm = 0;
345       (void) XSetErrorHandler( old_handler );
346       return GL_FALSE;
347    }
348 
349    shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */
350 
351    /* Finally, try an XShmPutImage to be really sure the extension works */
352    gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL );
353    XShmPutImage( b->xm_visual->display, b->frontbuffer, gc,
354 		 b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False );
355    XSync( b->xm_visual->display, False );
356    XFreeGC( b->xm_visual->display, gc );
357    (void) XSetErrorHandler( old_handler );
358    if (mesaXErrorFlag) {
359       XFlush( b->xm_visual->display );
360       mesaXErrorFlag = 0;
361       XDestroyImage( b->backimage );
362       shmdt( b->shminfo.shmaddr );
363       shmctl( b->shminfo.shmid, IPC_RMID, 0 );
364       b->backimage = NULL;
365       b->shm = 0;
366       return GL_FALSE;
367    }
368 
369    return GL_TRUE;
370 #else
371    /* Can't compile XSHM support */
372    return GL_FALSE;
373 #endif
374 }
375 
376 
377 
378 /*
379  * Setup an off-screen pixmap or Ximage to use as the back buffer.
380  * Input:  b - the X/Mesa buffer
381  */
xmesa_alloc_back_buffer(XMesaBuffer b)382 void xmesa_alloc_back_buffer( XMesaBuffer b )
383 {
384    if (b->db_state==BACK_XIMAGE) {
385       /* Deallocate the old backimage, if any */
386       if (b->backimage) {
387 #ifdef SHM
388 	 if (b->shm) {
389 	    XShmDetach( b->xm_visual->display, &b->shminfo );
390 	    XDestroyImage( b->backimage );
391 	    shmdt( b->shminfo.shmaddr );
392 	 }
393 	 else
394 #endif
395 	   XDestroyImage( b->backimage );
396 	 b->backimage = NULL;
397       }
398 
399       /* Allocate new back buffer */
400       if (b->shm==0 || alloc_shm_back_buffer(b)==GL_FALSE) {
401 	 /* Allocate a regular XImage for the back buffer. */
402 	 b->backimage = XCreateImage( b->xm_visual->display,
403                                       b->xm_visual->visinfo->visual,
404                                       b->xm_visual->visinfo->depth,
405 				      ZPixmap, 0,   /* format, offset */
406 				      NULL, b->width, b->height,
407 				      8, 0 );  /* pad, bytes_per_line */
408 	 if (!b->backimage) {
409 	    error("alloc_back_buffer: XCreateImage failed.");
410 	 }
411          b->backimage->data = (char *) malloc( b->backimage->height
412                                              * b->backimage->bytes_per_line );
413          if (!b->backimage->data) {
414             error("alloc_back_buffer: malloc failed.");
415             XDestroyImage( b->backimage );
416             b->backimage = NULL;
417          }
418       }
419       b->backpixmap = None;
420    }
421    else if (b->db_state==BACK_PIXMAP) {
422       Pixmap old_pixmap = b->backpixmap;
423       /* Free the old back pixmap */
424       if (b->backpixmap) {
425 	 XFreePixmap( b->xm_visual->display, b->backpixmap );
426       }
427       /* Allocate new back pixmap */
428       b->backpixmap = XCreatePixmap( b->xm_visual->display, b->frontbuffer,
429 				     b->width, b->height,
430                                      b->xm_visual->visinfo->depth );
431       b->backimage = NULL;
432       /* update other references to backpixmap */
433       if (b->buffer==old_pixmap) {
434 	 b->buffer = b->backpixmap;
435       }
436    }
437 }
438 
439 
440 
441 /*
442  * A replacement for XAllocColor.  This function should never
443  * fail to allocate a color.  When XAllocColor fails, we return
444  * the nearest matching color.  If we have to allocate many colors
445  * this function isn't too efficient; the XQueryColors() could be
446  * done just once.
447  * Written by Michael Pichler, Brian Paul, Mark Kilgard
448  * Input:  dpy - X display
449  *         cmap - X colormap
450  *         cmapSize - size of colormap
451  * In/Out: color - the XColor struct
452  * Output:  exact - 1=exact color match, 0=closest match
453  */
454 static void
noFaultXAllocColor(Display * dpy,Colormap cmap,int cmapSize,XColor * color,int * exact)455 noFaultXAllocColor( Display *dpy, Colormap cmap, int cmapSize,
456                     XColor *color, int *exact )
457 {
458    XColor *ctable, subColor;
459    int i, bestmatch;
460    double mindist;       /* 3*2^16^2 exceeds long int precision. */
461 
462    /* First try just using XAllocColor. */
463    if (XAllocColor(dpy, cmap, color)) {
464       *exact = 1;
465       return;
466    }
467 
468    /* Alloc failed, search for closest match */
469 
470    /* Retrieve color table entries. */
471    /* XXX alloca candidate. */
472    ctable = (XColor *) malloc(cmapSize * sizeof(XColor));
473    for (i = 0; i < cmapSize; i++) {
474       ctable[i].pixel = i;
475    }
476    XQueryColors(dpy, cmap, ctable, cmapSize);
477 
478    /* Find best match. */
479    bestmatch = -1;
480    mindist = 0.0;
481    for (i = 0; i < cmapSize; i++) {
482       double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
483       double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
484       double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
485       double dist = dr * dr + dg * dg + db * db;
486       if (bestmatch < 0 || dist < mindist) {
487          bestmatch = i;
488          mindist = dist;
489       }
490    }
491 
492    /* Return result. */
493    subColor.red   = ctable[bestmatch].red;
494    subColor.green = ctable[bestmatch].green;
495    subColor.blue  = ctable[bestmatch].blue;
496    /* Try to allocate the closest match color.  This should only
497     * fail if the cell is read/write.  Otherwise, we're incrementing
498     * the cell's reference count.
499     */
500    if (!XAllocColor(dpy, cmap, &subColor)) {
501       /* do this to work around a problem reported by Frank Ortega */
502       subColor.pixel = (unsigned long) bestmatch;
503       subColor.red   = ctable[bestmatch].red;
504       subColor.green = ctable[bestmatch].green;
505       subColor.blue  = ctable[bestmatch].blue;
506       subColor.flags = DoRed | DoGreen | DoBlue;
507    }
508    free(ctable);
509    *color = subColor;
510    *exact = 0;
511 }
512 
513 
514 
515 /*
516  * Do setup for PF_GRAYSCALE pixel format.
517  * Note that buffer may be NULL.
518  */
setup_grayscale(XMesaVisual v,XMesaBuffer buffer,Colormap cmap)519 static GLboolean setup_grayscale( XMesaVisual v, XMesaBuffer buffer,
520                                   Colormap cmap )
521 {
522    int gray;
523    int colorsfailed = 0;
524    XColor xcol;
525 
526    if (v->visinfo->depth<4 || v->visinfo->depth>16) {
527       return GL_FALSE;
528    }
529 
530    if (buffer) {
531       if (!cmap) {
532          return GL_FALSE;
533       }
534 
535       /* Allocate 256 shades of gray */
536       for (gray=0;gray<256;gray++) {
537          GLint r = gamma_adjust( v->RedGamma,   gray, 255 );
538          GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
539          GLint b = gamma_adjust( v->BlueGamma,  gray, 255 );
540          int exact;
541 
542          xcol.red   = (r << 8) | r;
543          xcol.green = (g << 8) | g;
544          xcol.blue  = (b << 8) | b;
545          noFaultXAllocColor( v->display, cmap, v->visinfo->colormap_size,
546                              &xcol, &exact );
547          if (!exact) {
548             colorsfailed++;
549          }
550 
551          buffer->color_table[gray] = xcol.pixel;
552          buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
553          buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
554          buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
555       }
556 
557       if (colorsfailed && getenv("MESA_DEBUG")) {
558          fprintf( stderr,
559                   "Note: %d out of 256 needed colors do not match exactly.\n",
560                   colorsfailed );
561       }
562    }
563 
564 #define WEIGHT
565 #ifdef WEIGHT
566    v->rmult = 30 * 255 / 100;
567    v->gmult = 59 * 255 / 100;
568    v->bmult = 11 * 255 / 100;
569 #else
570    v->rmult = 255/3;
571    v->gmult = 255/3;
572    v->bmult = 255/3;
573 #endif
574    v->dithered_pf = PF_GRAYSCALE;
575    v->undithered_pf = PF_GRAYSCALE;
576    return GL_TRUE;
577 }
578 
579 
580 
581 /*
582  * Setup RGB rendering for a window with a PseudoColor, StaticColor,
583  * or 8-bit TrueColor visual visual.  We try to allocate a palette of 225
584  * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
585  * color.  While this function was originally designed just for 8-bit
586  * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
587  * Dithering code contributed by Bob Mercier.
588  */
setup_dithered_color(XMesaVisual v,XMesaBuffer buffer,Window window,Colormap cmap)589 static GLboolean setup_dithered_color( XMesaVisual v, XMesaBuffer buffer,
590                                        Window window, Colormap cmap )
591 {
592    int r, g, b, i;
593    int colorsfailed = 0;
594    XColor xcol;
595 
596    if (v->visinfo->depth<4 || v->visinfo->depth>16) {
597       return GL_FALSE;
598    }
599 
600    if (buffer) {
601       if (!cmap) {
602          return GL_FALSE;
603       }
604 
605       /* Allocate X colors and initialize color_table[], red_table[], etc */
606       for (r = 0; r < _R; r++) {
607          for (g = 0; g < _G; g++) {
608             for (b = 0; b < _B; b++) {
609                int exact;
610 
611                xcol.red   = gamma_adjust(v->RedGamma,   r*65535/(_R-1), 65535);
612                xcol.green = gamma_adjust(v->GreenGamma, g*65535/(_G-1), 65535);
613                xcol.blue  = gamma_adjust(v->BlueGamma,  b*65535/(_B-1), 65535);
614                noFaultXAllocColor( v->display, cmap, v->visinfo->colormap_size,
615                                    &xcol, &exact );
616                if (!exact) {
617                   colorsfailed++;
618                }
619 
620                i = _MIX( r, g, b );
621                buffer->color_table[i] = xcol.pixel;
622                buffer->pixel_to_r[xcol.pixel] = r * 255 / (_R-1);
623                buffer->pixel_to_g[xcol.pixel] = g * 255 / (_G-1);
624                buffer->pixel_to_b[xcol.pixel] = b * 255 / (_B-1);
625             }
626 	 }
627       }
628 
629       if (colorsfailed && getenv("MESA_DEBUG")) {
630          fprintf( stderr,
631                   "Note: %d out of %d needed colors do not match exactly.\n",
632                   colorsfailed, _R*_G*_B );
633       }
634    }
635 
636    v->rmult = 255;
637    v->gmult = 255;
638    v->bmult = 255;
639    v->dithered_pf = PF_DITHER;
640    v->undithered_pf = PF_LOOKUP;
641    return GL_TRUE;
642 }
643 
644 
645 
646 /*
647  * Setup for 8-bit TrueColor dithering.  Very similar to the
648  * setup_dithered_color() function.  We use the same color_table[]
649  * array and dithering algorithm and macros.
650  */
setup_8bit_truecolor(XMesaVisual v,XMesaBuffer buffer)651 static void setup_8bit_truecolor( XMesaVisual v, XMesaBuffer buffer )
652 {
653    int r, g, b, i;
654 
655    if (buffer) {
656       /* Initialize color_table[], red_table[], etc */
657       for (r = 0; r < _R; r++) {
658          for (g = 0; g < _G; g++) {
659             for (b = 0; b < _B; b++) {
660                int red, green, blue, pixel;
661 
662                /* compute gamma adjusted red,green,blue in [0,255] */
663                red   = gamma_adjust(v->RedGamma,   r*255/(_R-1), 255);
664                green = gamma_adjust(v->GreenGamma, g*255/(_G-1), 255);
665                blue  = gamma_adjust(v->BlueGamma,  b*255/(_B-1), 255);
666 
667                /* compute pixel value from red, green, blue */
668                red   = (red   * v->rmult / 255) << v->rshift;
669                green = (green * v->gmult / 255) << v->gshift;
670                blue  = (blue  * v->bmult / 255) << v->bshift;
671                pixel = red | green | blue;
672                assert( pixel < 256 );
673 
674                i = _MIX( r, g, b );
675                buffer->color_table[i] = pixel;
676                buffer->pixel_to_r[pixel] = r * 255 / (_R-1);
677                buffer->pixel_to_g[pixel] = g * 255 / (_G-1);
678                buffer->pixel_to_b[pixel] = b * 255 / (_B-1);
679             }
680 	 }
681       }
682    }
683 
684    v->rmult = 255;
685    v->gmult = 255;
686    v->bmult = 255;
687    v->dithered_pf = PF_DITHER;
688    v->undithered_pf = PF_LOOKUP;
689 }
690 
691 
692 
693 /*
694  * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
695  * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
696  * Special dithering tables have to be initialized.
697  */
setup_8bit_hpcr(XMesaVisual v)698 static void setup_8bit_hpcr( XMesaVisual v )
699 {
700    /* HP Color Recovery contributed by:  Alex De Bruyn (ad@lms.be)
701     * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
702     * on the root window AND the colormap obtainable by XGetRGBColormaps
703     * for that atom must be set on the window.  (see also tkInitWindow)
704     * If that colormap is not set, the output will look stripy.
705     */
706 
707    /* Setup color tables with gamma correction */
708    int i;
709    double g;
710 
711    g = 1.0 / v->RedGamma;
712    for (i=0; i<256; i++) {
713       GLint red = 255.0 * pow( hpcr_rTbl[i]/255.0, g ) + 0.5;
714       v->hpcr_rTbl[i] = CLAMP( red, 16, 239 );
715    }
716 
717    g = 1.0 / v->GreenGamma;
718    for (i=0; i<256; i++) {
719       GLint green = 255.0 * pow( hpcr_gTbl[i]/255.0, g ) + 0.5;
720       v->hpcr_gTbl[i] = CLAMP( green, 16, 239 );
721    }
722 
723    g = 1.0 / v->BlueGamma;
724    for (i=0; i<256; i++) {
725       GLint blue = 255.0 * pow( hpcr_bTbl[i]/255.0, g ) + 0.5;
726       v->hpcr_bTbl[i] = CLAMP( blue, 32, 223 );
727    }
728    v->rmult = 255;
729    v->gmult = 255;
730    v->bmult = 255;
731    v->undithered_pf = PF_HPCR;  /* can't really disable dithering for now */
732    v->dithered_pf = PF_HPCR;
733 }
734 
735 
736 /*
737  * Setup RGB rendering for a window with a True/DirectColor visual.
738  */
setup_truecolor(XMesaVisual v,XMesaBuffer buffer,Window window,Colormap cmap)739 static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer,
740                              Window window, Colormap cmap )
741 {
742    unsigned long rmask, gmask, bmask;
743    int bitsPerPixel;
744 
745    /* Compute red multiplier and bit shift */
746    v->rshift = 0;
747    rmask = v->visinfo->red_mask;
748    while ((rmask & 1)==0) {
749       v->rshift++;
750       rmask = rmask >> 1;
751    }
752    v->rmult = (GLint) rmask;
753 
754    /* Compute green multiplier and bit shift */
755    v->gshift = 0;
756    gmask = v->visinfo->green_mask;
757    while ((gmask & 1)==0) {
758       v->gshift++;
759       gmask = gmask >> 1;
760    }
761    v->gmult = (GLint) gmask;
762 
763    /* Compute blue multiplier and bit shift */
764    v->bshift = 0;
765    bmask = v->visinfo->blue_mask;
766    while ((bmask & 1)==0) {
767       v->bshift++;
768       bmask = bmask >> 1;
769    }
770    v->bmult = (GLint) bmask;
771 
772    bitsPerPixel = bits_per_pixel( v->display, v->visinfo );
773 
774    if (   v->visinfo->red_mask  ==0x0000ff
775        && v->visinfo->green_mask==0x00ff00
776        && v->visinfo->blue_mask ==0xff0000
777        && host_byte_order()==ImageByteOrder(v->display)
778        && bitsPerPixel==32
779        && sizeof(GLuint)==4
780        && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
781       /* common 24-bit config used on SGI, Sun */
782       v->undithered_pf = v->dithered_pf = PF_8A8B8G8R;
783    }
784    else if (v->visinfo->red_mask  ==0xff0000
785        &&   v->visinfo->green_mask==0x00ff00
786        &&   v->visinfo->blue_mask ==0x0000ff
787        && host_byte_order()==ImageByteOrder(v->display)
788        && bitsPerPixel==32
789        && sizeof(GLuint)==4
790        && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
791       /* common 24-bit config used on Linux, HP, IBM */
792       v->undithered_pf = v->dithered_pf = PF_8R8G8B;
793    }
794    else if (v->visinfo->red_mask  ==0xf800
795        &&   v->visinfo->green_mask==0x07e0
796        &&   v->visinfo->blue_mask ==0x001f
797        && host_byte_order()==ImageByteOrder(v->display)
798        && bitsPerPixel==16
799        && sizeof(GLushort)==2
800        && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
801       /* 5-6-5 color weight on common PC VGA boards */
802       v->undithered_pf = v->dithered_pf = PF_5R6G5B;
803    }
804    else if (v->visinfo->red_mask  ==0xe0
805        &&   v->visinfo->green_mask==0x1c
806        &&   v->visinfo->blue_mask ==0x03
807        && XInternAtom(v->display, "_HP_RGB_SMOOTH_MAP_LIST", True)) {
808       setup_8bit_hpcr( v );
809    }
810    else if (v->visinfo->depth==8) {
811       setup_8bit_truecolor( v, buffer );
812    }
813    else {
814       /* general case (i.e. 12-bit TrueColor, or any gamma correction) */
815       GLint i;
816       /* setup r,g,btable[] arrays with gamma correction */
817       for (i=0;i<=v->rmult;i++) {
818          v->r_to_pixel[i] = gamma_adjust(v->RedGamma,   i, v->rmult) << v->rshift;
819       }
820       for (i=0;i<=v->gmult;i++) {
821          v->g_to_pixel[i] = gamma_adjust(v->GreenGamma, i, v->gmult) << v->gshift;
822       }
823       for (i=0;i<=v->bmult;i++) {
824          v->b_to_pixel[i] = gamma_adjust(v->BlueGamma,  i, v->bmult) << v->bshift;
825       }
826       v->undithered_pf = v->dithered_pf = PF_TRUECOLOR;
827    }
828 }
829 
830 
831 
832 /*
833  * Setup RGB rendering for a window with a monochrome visual.
834  */
setup_monochrome(XMesaVisual v)835 static void setup_monochrome( XMesaVisual v )
836 {
837    v->rmult = 255;
838    v->gmult = 255;
839    v->bmult = 255;
840    v->dithered_pf = v->undithered_pf = PF_1BIT;
841 }
842 
843 
844 
845 /*
846  * When a context is "made current" for the first time, we can finally
847  * finish initializing the context's visual and buffer information.
848  * Input:  v - the XMesaVisual to initialize
849  *         b - the XMesaBuffer to initialize
850  *         rgb_flag - TRUE = RGBA mode, FALSE = color index mode
851  *         window - the window/pixmap we're rendering into
852  *         cmap - the colormap associated with the window/pixmap
853  * Return:  GL_TRUE=success, GL_FALSE=failure
854  */
initialize_visual_and_buffer(XMesaVisual v,XMesaBuffer b,GLboolean rgb_flag,Window window,Colormap cmap)855 static GLboolean initialize_visual_and_buffer( XMesaVisual v,
856                                                XMesaBuffer b,
857                                                GLboolean rgb_flag,
858                                                Window window,
859                                                Colormap cmap )
860 {
861    XGCValues gcvalues;
862 
863    if (rgb_flag==GL_FALSE) {
864       /* COLOR-INDEXED WINDOW:
865        * Even if the visual is TrueColor or DirectColor we treat it as
866        * being color indexed.  This is weird but might be useful to someone.
867        */
868       v->dithered_pf = v->undithered_pf = PF_INDEX;
869       v->rmult = v->gmult = v->bmult = 0;
870       v->index_bits = v->visinfo->depth;
871    }
872    else {
873       /* RGB WINDOW:
874        * We support RGB rendering into almost any kind of visual.
875        */
876       int xclass;
877 #if defined(__cplusplus) || defined(c_plusplus)
878       xclass = v->visinfo->c_class;
879 #else
880       xclass = v->visinfo->class;
881 #endif
882       if (xclass==TrueColor || xclass==DirectColor) {
883 	 setup_truecolor( v, b, window, cmap );
884       }
885       else if (xclass==StaticGray && v->visinfo->depth==1) {
886 	 setup_monochrome( v );
887       }
888       else if (xclass==GrayScale || xclass==StaticGray) {
889          if (!setup_grayscale( v, b, cmap )) {
890             return GL_FALSE;
891          }
892       }
893       else if ((xclass==PseudoColor || xclass==StaticColor)
894                && v->visinfo->depth>=4 && v->visinfo->depth<=16) {
895 	 if (!setup_dithered_color( v, b, window, cmap )) {
896             return GL_FALSE;
897          }
898       }
899       else {
900 	 error("XMesa: RGB mode rendering not supported in given visual.");
901 	 return GL_FALSE;
902       }
903       v->index_bits = 0;
904    }
905 
906    /*
907     * If MESA_INFO env var is set print out some debugging info
908     * which can help Brian figure out what's going on when a user
909     * reports bugs.
910     */
911    if (getenv("MESA_INFO")) {
912       printf("v = %p\n", v);
913       printf("dithered pf = %d\n", v->dithered_pf);
914       printf("undithered pf = %d\n", v->undithered_pf);
915       printf("level = %d\n", v->level);
916       printf("depth = %d\n", v->visinfo->depth);
917       printf("bits per pixel = %d\n", bits_per_pixel(v->display, v->visinfo));
918    }
919 
920    if (b && window) {
921       /* Do window-specific initializations */
922 
923       /* Window dimensions */
924       unsigned int w, h;
925       get_drawable_size( v->display, window, &w, &h );
926       b->width = w;
927       b->height = h;
928 
929       b->frontbuffer = window;
930 
931       assert( v->gl_visual );
932 
933       /* Setup for single/double buffering */
934       if (v->gl_visual->DBflag) {
935          /* Double buffered */
936          b->shm = check_for_xshm( v->display );
937          xmesa_alloc_back_buffer( b );
938          if (b->db_state==BACK_PIXMAP) {
939             b->buffer = b->backpixmap;
940          }
941          else {
942             b->buffer = XIMAGE;
943          }
944       }
945       else {
946          /* Single Buffered */
947          b->buffer = b->frontbuffer;
948       }
949 
950       /* X11 graphics contexts */
951       b->gc1 = XCreateGC( v->display, window, 0, NULL );
952       XSetFunction( v->display, b->gc1, GXcopy );
953       b->gc2 = XCreateGC( v->display, window, 0, NULL );
954       XSetFunction( v->display, b->gc2, GXcopy );
955       /*
956        * Don't generate Graphics Expose/NoExpose events in swapbuffers().
957        * Patch contributed by Michael Pichler May 15, 1995.
958        */
959       gcvalues.graphics_exposures = False;
960       b->cleargc = XCreateGC( v->display, window,
961                               GCGraphicsExposures, &gcvalues);
962       XSetFunction( v->display, b->cleargc, GXcopy );
963 
964       /* Initialize the row buffer XImage for use in write_color_span() */
965       b->rowimage = XCreateImage( v->display,
966                                   v->visinfo->visual,
967                                   v->visinfo->depth,
968                                   ZPixmap, 0,           /*format, offset*/
969                                   (char*) malloc(MAX_WIDTH*4),  /*data*/
970                                   MAX_WIDTH, 1,         /*width, height*/
971                                   32,                   /*bitmap_pad*/
972                                   0                     /*bytes_per_line*/ );
973    }
974 
975    return GL_TRUE;
976 }
977 
978 
979 
980 /*
981  * Convert an RGBA color to a pixel value.
982  */
xmesa_color_to_pixel(XMesaContext xmesa,GLubyte r,GLubyte g,GLubyte b,GLubyte a)983 unsigned long xmesa_color_to_pixel( XMesaContext xmesa,
984                                     GLubyte r, GLubyte g, GLubyte b, GLubyte a)
985 {
986    switch (xmesa->pixelformat) {
987       case PF_INDEX:
988          return 0;
989       case PF_TRUECOLOR:
990          return PACK_RGB( r, g, b );
991       case PF_8A8B8G8R:
992          return PACK_8A8B8G8R( r, g, b, a );
993       case PF_8R8G8B:
994          return PACK_8R8G8B( r, g, b );
995       case PF_5R6G5B:
996          return PACK_5R6G5B( r, g, b );
997       case PF_DITHER:
998          {
999             DITHER_SETUP;
1000             return DITHER( 1, 0, r, g, b );
1001          }
1002       case PF_1BIT:
1003          return (r+g+b) > 382U;   /* 382 = (3*255)/2 */
1004       case PF_HPCR:
1005          return DITHER_HPCR(1, 1, r, g, b);
1006       case PF_LOOKUP:
1007          {
1008             LOOKUP_SETUP;
1009             return LOOKUP( r, g, b );
1010          }
1011       case PF_GRAYSCALE:
1012          return GRAY_RGB( r, g, b );
1013       default:
1014          abort();
1015    }
1016    return 0;  /*never get here*/
1017 }
1018 
1019 
1020 /**********************************************************************/
1021 /*****                       Public Functions                     *****/
1022 /**********************************************************************/
1023 
1024 
1025 /*
1026  * When a context is "made current" for the first time, we can finally
1027  * finish initializing the context.
1028  * Input:  c - the XMesaContext to initialize
1029  *         window - the window/pixmap we're rendering into
1030  *         cmap - the colormap associated with the window/pixmap
1031  * Return:  GL_TRUE=success, GL_FALSE=failure
1032  */
XMesaCreateVisual(Display * display,XVisualInfo * visinfo,GLboolean rgb_flag,GLboolean alpha_flag,GLboolean db_flag,GLboolean ximage_flag,GLint depth_size,GLint stencil_size,GLint accum_size,GLint level)1033 XMesaVisual XMesaCreateVisual( Display *display,
1034                                XVisualInfo *visinfo,
1035                                GLboolean rgb_flag,
1036                                GLboolean alpha_flag,
1037                                GLboolean db_flag,
1038                                GLboolean ximage_flag,
1039                                GLint depth_size,
1040                                GLint stencil_size,
1041                                GLint accum_size,
1042                                GLint level )
1043 {
1044    char *gamma;
1045    XMesaVisual v;
1046    GLfloat red_scale, green_scale, blue_scale, alpha_scale;
1047 
1048    /* For debugging only */
1049    if (getenv("MESA_XSYNC")) {
1050       XSynchronize( display, 1 );    /* This makes debugging X easier */
1051    }
1052 
1053    v = (XMesaVisual) calloc( 1, sizeof(struct xmesa_visual) );
1054    if (!v) {
1055       return NULL;
1056    }
1057 
1058    v->display = display;
1059 
1060    /* Save a copy of the XVisualInfo struct because the user may XFree()
1061     * the struct but we me need some of the information contained in it
1062     * at a later time.
1063     */
1064    v->visinfo = malloc(sizeof(*visinfo));
1065    if(!v->visinfo) {
1066       free(v);
1067       return NULL;
1068    }
1069    MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
1070 
1071    /* Save a copy of the pointer now so we can find this visual again
1072     * if we need to search for it in find_glx_visual().
1073     */
1074    v->vishandle = visinfo;
1075 
1076    /* check for MESA_GAMMA environment variable */
1077    gamma = getenv("MESA_GAMMA");
1078    if (gamma) {
1079       v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
1080       sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
1081       if (v->RedGamma<=0.0)    v->RedGamma = 1.0;
1082       if (v->GreenGamma<=0.0)  v->GreenGamma = v->RedGamma;
1083       if (v->BlueGamma<=0.0)   v->BlueGamma = v->RedGamma;
1084    }
1085    else {
1086       v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
1087    }
1088 
1089    v->ximage_flag = ximage_flag;
1090    v->level = level;
1091 
1092    (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
1093 
1094    red_scale   = (GLfloat) v->rmult;
1095    green_scale = (GLfloat) v->gmult;
1096    blue_scale  = (GLfloat) v->bmult;
1097    alpha_scale = 255.0;
1098 
1099    v->gl_visual = gl_create_visual( rgb_flag, alpha_flag, db_flag,
1100                                     depth_size, stencil_size, accum_size,
1101                                     v->index_bits,
1102                                     red_scale, green_scale,
1103                                     blue_scale, alpha_scale );
1104    if (!v->gl_visual) {
1105       free(v->visinfo);
1106       free(v);
1107       return NULL;
1108    }
1109 
1110    return v;
1111 }
1112 
1113 
1114 
XMesaDestroyVisual(XMesaVisual v)1115 void XMesaDestroyVisual( XMesaVisual v )
1116 {
1117    gl_destroy_visual( v->gl_visual );
1118    free(v->visinfo);
1119    free(v);
1120 }
1121 
1122 
1123 
1124 /*
1125  * Create a new XMesaContext.
1126  * Input:  v - XMesaVisual
1127  *         share_list - another XMesaContext with which to share display
1128  *                      lists or NULL if no sharing is wanted.
1129  * Return:  an XMesaContext or NULL if error.
1130  */
XMesaCreateContext(XMesaVisual v,XMesaContext share_list)1131 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
1132 {
1133    XMesaContext c;
1134 
1135    c = (XMesaContext) calloc( 1, sizeof(struct xmesa_context) );
1136    if (!c) {
1137       return NULL;
1138    }
1139 
1140    c->gl_ctx = gl_create_context( v->gl_visual,
1141                                   share_list ? share_list->gl_ctx : NULL,
1142                                   (void *) c );
1143    if (!c->gl_ctx) {
1144       free(c);
1145       return NULL;
1146    }
1147 
1148    if (host_byte_order()==ImageByteOrder(v->display)) {
1149       c->swapbytes = GL_FALSE;
1150    }
1151    else {
1152       c->swapbytes = GL_TRUE;
1153    }
1154 
1155    c->xm_visual = v;
1156    c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
1157    c->display = v->display;
1158    c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
1159 
1160    return c;
1161 }
1162 
1163 
1164 
1165 
XMesaDestroyContext(XMesaContext c)1166 void XMesaDestroyContext( XMesaContext c )
1167 {
1168    if (c->gl_ctx)  gl_destroy_context( c->gl_ctx );
1169 
1170    free( c );
1171 }
1172 
1173 
1174 
1175 /*
1176  * Create a new XMesaBuffer from an X window.
1177  * Input:  v - the XMesaVisual
1178  *         W - the window
1179  * Return:  new XMesaBuffer or NULL if error
1180  */
XMesaCreateWindowBuffer(XMesaVisual v,Window w)1181 XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, Window w )
1182 {
1183    XWindowAttributes attr;
1184    XMesaBuffer b;
1185 
1186    b = (XMesaBuffer) calloc( 1, sizeof(struct xmesa_buffer) );
1187    if (!b) {
1188       return NULL;
1189    }
1190 
1191    XGetWindowAttributes( v->display, w, &attr );
1192 
1193    b->xm_visual = v;
1194    b->pixmap_flag = GL_FALSE;
1195    b->cmap = attr.colormap;
1196 
1197    /* determine back buffer implementation */
1198    if (v->gl_visual->DBflag) {
1199       if (v->ximage_flag) {
1200 	 b->db_state = BACK_XIMAGE;
1201       }
1202       else {
1203 	 b->db_state = BACK_PIXMAP;
1204       }
1205    }
1206    else {
1207       b->db_state = 0;
1208    }
1209 
1210    b->gl_buffer = gl_create_framebuffer( v->gl_visual );
1211    if (!b->gl_buffer) {
1212       free(b);
1213       return NULL;
1214    }
1215 
1216    if (!initialize_visual_and_buffer( v, b, v->gl_visual->RGBAflag,
1217                                       w, attr.colormap )) {
1218       gl_destroy_framebuffer( b->gl_buffer );
1219       free( b );
1220       return NULL;
1221    }
1222 
1223    return b;
1224 }
1225 
1226 
1227 
1228 /*
1229  * Create a new XMesaBuffer from an X pixmap.
1230  * Input:  v - the XMesaVisual
1231  *         p - the pixmap
1232  *         cmap - the colormap, may be 0 if using a TrueColor or DirectColor
1233  *                visual for the pixmap
1234  * Return:  new XMesaBuffer or NULL if error
1235  */
XMesaCreatePixmapBuffer(XMesaVisual v,Pixmap p,Colormap cmap)1236 XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, Pixmap p, Colormap cmap )
1237 {
1238    XMesaBuffer b;
1239 
1240    b = (XMesaBuffer) calloc( 1, sizeof(struct xmesa_buffer) );
1241    if (!b) {
1242       return NULL;
1243    }
1244 
1245    b->xm_visual = v;
1246    b->pixmap_flag = GL_TRUE;
1247    b->cmap = cmap;
1248 
1249    /* determine back buffer implementation */
1250    if (v->gl_visual->DBflag) {
1251       if (v->ximage_flag) {
1252 	 b->db_state = BACK_XIMAGE;
1253       }
1254       else {
1255 	 b->db_state = BACK_PIXMAP;
1256       }
1257    }
1258    else {
1259       b->db_state = 0;
1260    }
1261 
1262    b->gl_buffer = gl_create_framebuffer( v->gl_visual );
1263    if (!b->gl_buffer) {
1264       free(b);
1265       return NULL;
1266    }
1267 
1268    if (!initialize_visual_and_buffer(v, b, v->gl_visual->RGBAflag, p, cmap)) {
1269       gl_destroy_framebuffer( b->gl_buffer );
1270       free( b );
1271       return NULL;
1272    }
1273 
1274    return b;
1275 }
1276 
1277 
1278 
1279 /*
1280  * Deallocate an XMesaBuffer structure and all related info.
1281  */
XMesaDestroyBuffer(XMesaBuffer b)1282 void XMesaDestroyBuffer( XMesaBuffer b )
1283 {
1284    if (b->gc1)  XFreeGC( b->xm_visual->display, b->gc1 );
1285    if (b->gc2)  XFreeGC( b->xm_visual->display, b->gc2 );
1286    if (b->cleargc)  XFreeGC( b->xm_visual->display, b->cleargc );
1287 
1288    if (b->backimage) {
1289 #ifdef SHM
1290        if (b->shm) {
1291 	   XShmDetach( b->xm_visual->display, &b->shminfo );
1292 	   XDestroyImage( b->backimage );
1293 	   shmdt( b->shminfo.shmaddr );
1294        }
1295        else
1296 #endif
1297 	   XDestroyImage( b->backimage );
1298    }
1299    if (b->backpixmap) {
1300       XFreePixmap( b->xm_visual->display, b->backpixmap );
1301    }
1302    if (b->rowimage) {
1303       free( b->rowimage->data );
1304       b->rowimage->data = NULL;
1305       XDestroyImage( b->rowimage );
1306    }
1307 
1308    gl_destroy_framebuffer( b->gl_buffer );
1309    free(b);
1310 }
1311 
1312 
1313 
1314 /*
1315  * Bind buffer b to context c and make c the current rendering context.
1316  */
XMesaMakeCurrent(XMesaContext c,XMesaBuffer b)1317 GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
1318 {
1319    if ((c && !b) || (!c && b)) {
1320       return GL_FALSE;
1321    }
1322 
1323    if (c) {
1324       c->xm_buffer = b;
1325 
1326       gl_make_current( c->gl_ctx, b->gl_buffer );
1327       XMesa = c;
1328 
1329       xmesa_setup_DD_pointers( c->gl_ctx );
1330 
1331       if (c->gl_ctx->Viewport.Width==0) {
1332 	 /* initialize viewport to window size */
1333 	 gl_Viewport( c->gl_ctx, 0, 0, b->width, b->height );
1334 	 c->gl_ctx->Scissor.Width = b->width;
1335 	 c->gl_ctx->Scissor.Height = b->height;
1336       }
1337 
1338       if (c->xm_visual->gl_visual->RGBAflag) {
1339          /*
1340           * Must recompute and set these pixel values because colormap
1341           * can be different for different windows.
1342           */
1343          c->pixel = xmesa_color_to_pixel( c, c->red, c->green,
1344                                           c->blue, c->alpha );
1345          XSetForeground( c->display, c->xm_buffer->gc1, c->pixel );
1346          c->clearpixel = xmesa_color_to_pixel( c,
1347                                                c->clearcolor[0],
1348                                                c->clearcolor[1],
1349                                                c->clearcolor[2],
1350                                                c->clearcolor[3] );
1351          XSetForeground( c->display, c->xm_buffer->cleargc, c->clearpixel );
1352       }
1353 
1354    }
1355    else {
1356       /* Detach */
1357       gl_make_current( NULL, NULL );
1358       XMesa = NULL;
1359    }
1360    return GL_TRUE;
1361 }
1362 
1363 
1364 
XMesaGetCurrentContext(void)1365 XMesaContext XMesaGetCurrentContext( void )
1366 {
1367    return XMesa;
1368 }
1369 
1370 
1371 
XMesaGetCurrentBuffer(void)1372 XMesaBuffer XMesaGetCurrentBuffer( void )
1373 {
1374    if (XMesa) {
1375       return XMesa->xm_buffer;
1376    }
1377    else {
1378       return 0;
1379    }
1380 }
1381 
1382 
1383 
1384 /*
1385  * Copy the back buffer to the front buffer.  If there's no back buffer
1386  * this is a no-op.
1387  */
XMesaSwapBuffers(XMesaBuffer b)1388 void XMesaSwapBuffers( XMesaBuffer b )
1389 {
1390 #ifdef PROFILE
1391    GLdouble t0 = gl_time();
1392 #endif
1393    if (b->db_state) {
1394       if (b->backimage) {
1395 	 /* Copy Ximage from host's memory to server's window */
1396 #ifdef SHM
1397 	 if (b->shm) {
1398 	    XShmPutImage( b->xm_visual->display, b->frontbuffer,
1399 			  b->cleargc,
1400 			  b->backimage, 0, 0,
1401 			  0, 0, b->width, b->height, False );
1402 	    /* wait for finished event??? */
1403 	 }
1404 	 else
1405 #endif
1406          {
1407             XPutImage( b->xm_visual->display, b->frontbuffer,
1408                        b->cleargc,
1409                        b->backimage, 0, 0,
1410                        0, 0, b->width, b->height );
1411          }
1412       }
1413       else {
1414 	 /* Copy pixmap to window on server */
1415 	 XCopyArea( b->xm_visual->display,
1416 		    b->backpixmap,   /* source drawable */
1417 		    b->frontbuffer,  /* dest. drawable */
1418 		    b->cleargc,
1419 		    0, 0, b->width, b->height,  /* source region */
1420 		    0, 0                 /* dest region */
1421 		   );
1422       }
1423    }
1424    XSync( b->xm_visual->display, False );
1425 #ifdef PROFILE
1426    XMesa->gl_ctx->SwapCount++;
1427    XMesa->gl_ctx->SwapTime += gl_time() - t0;
1428 #endif
1429 }
1430 
1431 
1432 
1433 /*
1434  * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
1435  * is a way to get "under the hood" of X/Mesa so one can manipulate the
1436  * back buffer directly.
1437  * Output:  pixmap - pointer to back buffer's Pixmap, or 0
1438  *          ximage - pointer to back buffer's XImage, or NULL
1439  * Return:  GL_TRUE = context is double buffered
1440  *          GL_FALSE = context is single buffered
1441  */
XMesaGetBackBuffer(XMesaBuffer b,Pixmap * pixmap,XImage ** ximage)1442 GLboolean XMesaGetBackBuffer( XMesaBuffer b, Pixmap *pixmap, XImage **ximage )
1443 {
1444    if (b->db_state) {
1445       if (pixmap)  *pixmap = b->backpixmap;
1446       if (ximage)  *ximage = b->backimage;
1447       return GL_TRUE;
1448    }
1449    else {
1450       *pixmap = 0;
1451       *ximage = NULL;
1452       return GL_FALSE;
1453    }
1454 }
1455 
1456 
1457 
XMesaFlush(XMesaContext c)1458 void XMesaFlush( XMesaContext c )
1459 {
1460    XSync( c->xm_visual->display, False );
1461 }
1462 
1463 
1464 
XMesaGetString(XMesaContext c,int name)1465 const char *XMesaGetString( XMesaContext c, int name )
1466 {
1467    if (name==XMESA_VERSION) {
1468       return "2.0";
1469    }
1470    else if (name==XMESA_EXTENSIONS) {
1471       return "";
1472    }
1473    else {
1474       return NULL;
1475    }
1476 }
1477 
1478 #endif
1479