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