5bb7b05f86a56a88a16814ac2a3d0b07deaaf1b4
[mesa.git] / src / mesa / drivers / x11 / xm_api.c
1 /* $Id: xm_api.c,v 1.21 2001/04/27 21:18:25 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
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 USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
40 * in support for the MIT Shared Memory extension. If enabled, when you
41 * use an Ximage for the back buffer in double buffered mode, the "swap"
42 * operation will 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 #ifdef __CYGWIN__
62 #undef WIN32
63 #undef __WIN32__
64 #endif
65
66 #include "glxheader.h"
67 #include "GL/xmesa.h"
68 #include "xmesaP.h"
69 #include "context.h"
70 #include "extensions.h"
71 #include "glthread.h"
72 #include "matrix.h"
73 #include "mem.h"
74 #include "mmath.h"
75 #include "mtypes.h"
76 #ifdef HAVE_CONFIG_H
77 #include "conf.h"
78 #endif
79 #include "macros.h"
80 #include "swrast/swrast.h"
81 #include "swrast_setup/swrast_setup.h"
82 #include "array_cache/acache.h"
83 #include "tnl/tnl.h"
84
85 #ifndef GLX_NONE_EXT
86 #define GLX_NONE_EXT 0x8000
87 #endif
88
89
90 /*
91 * Global X driver lock
92 */
93 _glthread_Mutex _xmesa_lock;
94
95
96
97 /*
98 * Lookup tables for HPCR pixel format:
99 */
100 static short hpcr_rgbTbl[3][256] = {
101 {
102 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
103 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
104 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
105 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
106 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
107 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
108 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
109 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
110 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
111 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
112 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
113 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
114 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
115 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
116 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
117 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
118 },
119 {
120 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
121 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
122 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
123 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
124 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
125 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
126 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
127 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
128 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
129 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
130 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
131 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
132 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
133 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
134 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
135 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
136 },
137 {
138 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
139 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
140 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55,
141 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
142 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
143 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79,
144 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87,
145 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
146 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
147 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
148 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
149 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
150 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
151 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
152 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
153 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
154 }
155 };
156
157
158
159 /**********************************************************************/
160 /***** X Utility Functions *****/
161 /**********************************************************************/
162
163
164 /*
165 * X/Mesa error reporting function:
166 */
167 static void error( const char *msg )
168 {
169 if (getenv("MESA_DEBUG"))
170 fprintf( stderr, "X/Mesa error: %s\n", msg );
171 }
172
173
174 /*
175 * Return the host's byte order as LSBFirst or MSBFirst ala X.
176 */
177 #ifndef XFree86Server
178 static int host_byte_order( void )
179 {
180 int i = 1;
181 char *cptr = (char *) &i;
182 return (*cptr==1) ? LSBFirst : MSBFirst;
183 }
184 #endif
185
186
187 /*
188 * Error handling.
189 */
190 #ifndef XFree86Server
191 static int mesaXErrorFlag = 0;
192
193 static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event )
194 {
195 (void) dpy;
196 (void) event;
197 mesaXErrorFlag = 1;
198 return 0;
199 }
200 #endif
201
202
203 /*
204 * Check if the X Shared Memory extension is available.
205 * Return: 0 = not available
206 * 1 = shared XImage support available
207 * 2 = shared Pixmap support available also
208 */
209 #ifndef XFree86Server
210 static int check_for_xshm( XMesaDisplay *display )
211 {
212 #ifdef USE_XSHM
213 int major, minor, ignore;
214 Bool pixmaps;
215
216 if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
217 if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
218 return (pixmaps==True) ? 2 : 1;
219 }
220 else {
221 return 0;
222 }
223 }
224 else {
225 return 0;
226 }
227 #else
228 /* Can't compile XSHM support */
229 return 0;
230 #endif
231 }
232 #endif
233
234
235 /*
236 * Return the width and height of the given drawable.
237 */
238 static void get_drawable_size( XMesaDisplay *dpy, XMesaDrawable d,
239 unsigned int *width, unsigned int *height)
240 {
241 #ifdef XFree86Server
242 (void) dpy;
243 *width = d->width;
244 *height = d->height;
245 #else
246 Window root;
247 int x, y;
248 unsigned int bw, depth;
249
250 _glthread_LOCK_MUTEX(_xmesa_lock);
251 XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth );
252 _glthread_UNLOCK_MUTEX(_xmesa_lock);
253 #endif
254 }
255
256
257 /*
258 * Apply gamma correction to an intensity value in [0..max]. Return the
259 * new intensity value.
260 */
261 static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max )
262 {
263 if (gamma == 1.0) {
264 return value;
265 }
266 else {
267 double x = (double) value / (double) max;
268 return IROUND_POS((GLfloat) max * pow(x, 1.0F/gamma));
269 }
270 }
271
272
273
274 /*
275 * Return the true number of bits per pixel for XImages.
276 * For example, if we request a 24-bit deep visual we may actually need/get
277 * 32bpp XImages. This function returns the appropriate bpp.
278 * Input: dpy - the X display
279 * visinfo - desribes the visual to be used for XImages
280 * Return: true number of bits per pixel for XImages
281 */
282 #define GET_BITS_PER_PIXEL(xmv) bits_per_pixel(xmv)
283
284 #ifdef XFree86Server
285
286 static int bits_per_pixel( XMesaVisual xmv )
287 {
288 XMesaVisualInfo visinfo = xmv->visinfo;
289 const int depth = visinfo->nplanes;
290 int i;
291 for (i = 0; i < screenInfo.numPixmapFormats; i++) {
292 if (screenInfo.formats[i].depth == depth)
293 return screenInfo.formats[i].bitsPerPixel;
294 }
295 return depth; /* should never get here, but this should be safe */
296 }
297
298 #else
299
300 static int bits_per_pixel( XMesaVisual xmv )
301 {
302 XMesaDisplay *dpy = xmv->display;
303 XMesaVisualInfo visinfo = xmv->visinfo;
304 XMesaImage *img;
305 int bitsPerPixel;
306 /* Create a temporary XImage */
307 img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
308 ZPixmap, 0, /*format, offset*/
309 (char*) MALLOC(8), /*data*/
310 1, 1, /*width, height*/
311 32, /*bitmap_pad*/
312 0 /*bytes_per_line*/
313 );
314 assert(img);
315 /* grab the bits/pixel value */
316 bitsPerPixel = img->bits_per_pixel;
317 /* free the XImage */
318 FREE( img->data );
319 img->data = NULL;
320 XMesaDestroyImage( img );
321 return bitsPerPixel;
322 }
323 #endif
324
325
326
327 /*
328 * Determine if a given X window ID is valid (window exists).
329 * Do this by calling XGetWindowAttributes() for the window and
330 * checking if we catch an X error.
331 * Input: dpy - the display
332 * win - the window to check for existance
333 * Return: GL_TRUE - window exists
334 * GL_FALSE - window doesn't exist
335 */
336 #ifndef XFree86Server
337 static GLboolean WindowExistsFlag;
338
339 static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
340 {
341 (void) dpy;
342 if (xerr->error_code == BadWindow) {
343 WindowExistsFlag = GL_FALSE;
344 }
345 return 0;
346 }
347
348 static GLboolean window_exists( XMesaDisplay *dpy, Window win )
349 {
350 XWindowAttributes wa;
351 int (*old_handler)( XMesaDisplay*, XErrorEvent* );
352 WindowExistsFlag = GL_TRUE;
353 old_handler = XSetErrorHandler(window_exists_err_handler);
354 XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
355 XSetErrorHandler(old_handler);
356 return WindowExistsFlag;
357 }
358 #endif
359
360
361
362 /**********************************************************************/
363 /***** Linked list of XMesaBuffers *****/
364 /**********************************************************************/
365
366 static XMesaBuffer XMesaBufferList = NULL;
367
368
369 /* Allocate a new XMesaBuffer, add to linked list */
370 static XMesaBuffer alloc_xmesa_buffer(void)
371 {
372 XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
373 if (b) {
374 b->Next = XMesaBufferList;
375 XMesaBufferList = b;
376 }
377 return b;
378 }
379
380
381 /*
382 * Find an XMesaBuffer by matching X display and colormap but NOT matching
383 * the notThis buffer.
384 */
385 static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy,
386 XMesaColormap cmap,
387 XMesaBuffer notThis)
388 {
389 XMesaBuffer b;
390 for (b=XMesaBufferList; b; b=b->Next) {
391 if (b->display==dpy && b->cmap==cmap && b!=notThis) {
392 return b;
393 }
394 }
395 return NULL;
396 }
397
398
399 /*
400 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
401 * entries.
402 */
403 static void free_xmesa_buffer(int client, XMesaBuffer buffer)
404 {
405 XMesaBuffer prev = NULL, b;
406 (void) client;
407 for (b=XMesaBufferList; b; b=b->Next) {
408 if (b==buffer) {
409 /* unlink bufer from list */
410 if (prev)
411 prev->Next = buffer->Next;
412 else
413 XMesaBufferList = buffer->Next;
414 /* Check to free X colors */
415 if (buffer->num_alloced>0) {
416 /* If no other buffer uses this X colormap then free the colors. */
417 if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) {
418 #ifdef XFree86Server
419 (void)FreeColors(buffer->cmap, client,
420 buffer->num_alloced, buffer->alloced_colors,
421 0);
422 #else
423 XFreeColors(buffer->display, buffer->cmap,
424 buffer->alloced_colors, buffer->num_alloced, 0);
425 #endif
426 }
427 }
428
429 _mesa_free_framebuffer_data(&buffer->mesa_buffer);
430 FREE(buffer);
431
432 return;
433 }
434 /* continue search */
435 prev = b;
436 }
437 /* buffer not found in XMesaBufferList */
438 _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n");
439 }
440
441
442 /* Copy X color table stuff from one XMesaBuffer to another. */
443 static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src)
444 {
445 MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table));
446 MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r));
447 MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g));
448 MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b));
449 dst->num_alloced = src->num_alloced;
450 MEMCPY(dst->alloced_colors, src->alloced_colors,
451 sizeof(src->alloced_colors));
452 }
453
454
455
456 /**********************************************************************/
457 /***** Misc Private Functions *****/
458 /**********************************************************************/
459
460
461 /*
462 * Return number of bits set in n.
463 */
464 static int bitcount( unsigned long n )
465 {
466 int bits;
467 for (bits=0; n>0; n=n>>1) {
468 if (n&1) {
469 bits++;
470 }
471 }
472 return bits;
473 }
474
475
476
477 /*
478 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
479 * Return: GL_TRUE if success, GL_FALSE if error
480 */
481 #ifndef XFree86Server
482 static GLboolean alloc_shm_back_buffer( XMesaBuffer b )
483 {
484 #ifdef USE_XSHM
485 /*
486 * We have to do a _lot_ of error checking here to be sure we can
487 * really use the XSHM extension. It seems different servers trigger
488 * errors at different points if the extension won't work. Therefore
489 * we have to be very careful...
490 */
491 GC gc;
492 int (*old_handler)( XMesaDisplay *, XErrorEvent * );
493
494 b->backimage = XShmCreateImage( b->xm_visual->display,
495 b->xm_visual->visinfo->visual,
496 b->xm_visual->visinfo->depth,
497 ZPixmap, NULL, &b->shminfo,
498 b->width, b->height );
499 if (b->backimage == NULL) {
500 error("alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
501 b->shm = 0;
502 return GL_FALSE;
503 }
504
505 b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line
506 * b->backimage->height, IPC_CREAT|0777 );
507 if (b->shminfo.shmid < 0) {
508 if (getenv("MESA_DEBUG"))
509 perror("alloc_back_buffer");
510 XDestroyImage( b->backimage );
511 b->backimage = NULL;
512 error("alloc_back_buffer: Shared memory error (shmget), disabling.");
513 b->shm = 0;
514 return GL_FALSE;
515 }
516
517 b->shminfo.shmaddr = b->backimage->data
518 = (char*)shmat( b->shminfo.shmid, 0, 0 );
519 if (b->shminfo.shmaddr == (char *) -1) {
520 if (getenv("MESA_DEBUG"))
521 perror("alloc_back_buffer");
522 XDestroyImage( b->backimage );
523 shmctl( b->shminfo.shmid, IPC_RMID, 0 );
524 b->backimage = NULL;
525 error("alloc_back_buffer: Shared memory error (shmat), disabling.");
526 b->shm = 0;
527 return GL_FALSE;
528 }
529
530 b->shminfo.readOnly = False;
531 mesaXErrorFlag = 0;
532 old_handler = XSetErrorHandler( mesaHandleXError );
533 /* This may trigger the X protocol error we're ready to catch: */
534 XShmAttach( b->xm_visual->display, &b->shminfo );
535 XSync( b->xm_visual->display, False );
536
537 if (mesaXErrorFlag) {
538 /* we are on a remote display, this error is normal, don't print it */
539 XFlush( b->xm_visual->display );
540 mesaXErrorFlag = 0;
541 XDestroyImage( b->backimage );
542 shmdt( b->shminfo.shmaddr );
543 shmctl( b->shminfo.shmid, IPC_RMID, 0 );
544 b->backimage = NULL;
545 b->shm = 0;
546 (void) XSetErrorHandler( old_handler );
547 return GL_FALSE;
548 }
549
550 shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */
551
552 /* Finally, try an XShmPutImage to be really sure the extension works */
553 gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL );
554 XShmPutImage( b->xm_visual->display, b->frontbuffer, gc,
555 b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False );
556 XSync( b->xm_visual->display, False );
557 XFreeGC( b->xm_visual->display, gc );
558 (void) XSetErrorHandler( old_handler );
559 if (mesaXErrorFlag) {
560 XFlush( b->xm_visual->display );
561 mesaXErrorFlag = 0;
562 XDestroyImage( b->backimage );
563 shmdt( b->shminfo.shmaddr );
564 shmctl( b->shminfo.shmid, IPC_RMID, 0 );
565 b->backimage = NULL;
566 b->shm = 0;
567 return GL_FALSE;
568 }
569
570 if (b->backimage) {
571 int height = b->backimage->height;
572 /* Needed by PIXELADDR1 macro */
573 b->ximage_width1 = b->backimage->bytes_per_line;
574 b->ximage_origin1 = (GLubyte *) b->backimage->data
575 + b->ximage_width1 * (height-1);
576 /* Needed by PIXELADDR2 macro */
577 b->ximage_width2 = b->backimage->bytes_per_line / 2;
578 b->ximage_origin2 = (GLushort *) b->backimage->data
579 + b->ximage_width2 * (height-1);
580 /* Needed by PIXELADDR3 macro */
581 b->ximage_width3 = b->backimage->bytes_per_line;
582 b->ximage_origin3 = (GLubyte *) b->backimage->data
583 + b->ximage_width3 * (height-1);
584 /* Needed by PIXELADDR4 macro */
585 b->ximage_width4 = b->backimage->width;
586 b->ximage_origin4 = (GLuint *) b->backimage->data
587 + b->ximage_width4 * (height-1);
588 }
589
590 return GL_TRUE;
591 #else
592 /* Can't compile XSHM support */
593 return GL_FALSE;
594 #endif
595 }
596 #endif
597
598
599
600 /*
601 * Setup an off-screen pixmap or Ximage to use as the back buffer.
602 * Input: b - the X/Mesa buffer
603 */
604 void xmesa_alloc_back_buffer( XMesaBuffer b )
605 {
606 if (b->db_state==BACK_XIMAGE) {
607 /* Deallocate the old backimage, if any */
608 if (b->backimage) {
609 #if defined(USE_XSHM) && !defined(XFree86Server)
610 if (b->shm) {
611 XShmDetach( b->xm_visual->display, &b->shminfo );
612 XDestroyImage( b->backimage );
613 shmdt( b->shminfo.shmaddr );
614 }
615 else
616 #endif
617 XMesaDestroyImage( b->backimage );
618 b->backimage = NULL;
619 }
620
621 /* Allocate new back buffer */
622 #ifdef XFree86Server
623 {
624 /* Allocate a regular XImage for the back buffer. */
625 b->backimage = XMesaCreateImage(b->xm_visual->BitsPerPixel,
626 b->width, b->height, NULL);
627 #else
628 if (b->shm==0
629 || alloc_shm_back_buffer(b)==GL_FALSE
630 ) {
631 /* Allocate a regular XImage for the back buffer. */
632 b->backimage = XCreateImage( b->xm_visual->display,
633 b->xm_visual->visinfo->visual,
634 GET_VISUAL_DEPTH(b->xm_visual),
635 ZPixmap, 0, /* format, offset */
636 NULL, b->width, b->height,
637 8, 0 ); /* pad, bytes_per_line */
638 #endif
639 if (!b->backimage) {
640 error("alloc_back_buffer: XCreateImage failed.");
641 }
642 b->backimage->data = (char *) MALLOC( b->backimage->height
643 * b->backimage->bytes_per_line );
644 if (!b->backimage->data) {
645 error("alloc_back_buffer: MALLOC failed.");
646 XMesaDestroyImage( b->backimage );
647 b->backimage = NULL;
648 }
649 }
650 b->backpixmap = None;
651 }
652 else if (b->db_state==BACK_PIXMAP) {
653 XMesaPixmap old_pixmap = b->backpixmap;
654 /* Free the old back pixmap */
655 if (b->backpixmap) {
656 XMesaFreePixmap( b->xm_visual->display, b->backpixmap );
657 }
658 /* Allocate new back pixmap */
659 b->backpixmap = XMesaCreatePixmap( b->xm_visual->display, b->frontbuffer,
660 b->width, b->height,
661 GET_VISUAL_DEPTH(b->xm_visual) );
662 b->backimage = NULL;
663 /* update other references to backpixmap */
664 if (b->buffer==(XMesaDrawable)old_pixmap) {
665 b->buffer = (XMesaDrawable)b->backpixmap;
666 }
667 }
668 }
669
670
671
672 /*
673 * A replacement for XAllocColor. This function should never
674 * fail to allocate a color. When XAllocColor fails, we return
675 * the nearest matching color. If we have to allocate many colors
676 * this function isn't too efficient; the XQueryColors() could be
677 * done just once.
678 * Written by Michael Pichler, Brian Paul, Mark Kilgard
679 * Input: dpy - X display
680 * cmap - X colormap
681 * cmapSize - size of colormap
682 * In/Out: color - the XColor struct
683 * Output: exact - 1=exact color match, 0=closest match
684 * alloced - 1=XAlloc worked, 0=XAlloc failed
685 */
686 static void
687 noFaultXAllocColor( int client,
688 XMesaDisplay *dpy,
689 XMesaColormap cmap,
690 int cmapSize,
691 XMesaColor *color,
692 int *exact, int *alloced )
693 {
694 #ifdef XFree86Server
695 Pixel *ppixIn;
696 xrgb *ctable;
697 #else
698 /* we'll try to cache ctable for better remote display performance */
699 static Display *prevDisplay = NULL;
700 static XMesaColormap prevCmap = 0;
701 static int prevCmapSize = 0;
702 static XMesaColor *ctable = NULL;
703 #endif
704 XMesaColor subColor;
705 int i, bestmatch;
706 double mindist; /* 3*2^16^2 exceeds long int precision. */
707
708 (void) client;
709
710 /* First try just using XAllocColor. */
711 #ifdef XFree86Server
712 if (AllocColor(cmap,
713 &color->red, &color->green, &color->blue,
714 &color->pixel,
715 client) == Success) {
716 #else
717 if (XAllocColor(dpy, cmap, color)) {
718 #endif
719 *exact = 1;
720 *alloced = 1;
721 return;
722 }
723
724 /* Alloc failed, search for closest match */
725
726 /* Retrieve color table entries. */
727 /* XXX alloca candidate. */
728 #ifdef XFree86Server
729 ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel));
730 ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb));
731 for (i = 0; i < cmapSize; i++) {
732 ppixIn[i] = i;
733 }
734 QueryColors(cmap, cmapSize, ppixIn, ctable);
735 #else
736 if (prevDisplay != dpy || prevCmap != cmap
737 || prevCmapSize != cmapSize || !ctable) {
738 /* free previously cached color table */
739 if (ctable)
740 FREE(ctable);
741 /* Get the color table from X */
742 ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor));
743 assert(ctable);
744 for (i = 0; i < cmapSize; i++) {
745 ctable[i].pixel = i;
746 }
747 XQueryColors(dpy, cmap, ctable, cmapSize);
748 prevDisplay = dpy;
749 prevCmap = cmap;
750 prevCmapSize = cmapSize;
751 }
752 #endif
753
754 /* Find best match. */
755 bestmatch = -1;
756 mindist = 0.0;
757 for (i = 0; i < cmapSize; i++) {
758 double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
759 double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
760 double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
761 double dist = dr * dr + dg * dg + db * db;
762 if (bestmatch < 0 || dist < mindist) {
763 bestmatch = i;
764 mindist = dist;
765 }
766 }
767
768 /* Return result. */
769 subColor.red = ctable[bestmatch].red;
770 subColor.green = ctable[bestmatch].green;
771 subColor.blue = ctable[bestmatch].blue;
772 /* Try to allocate the closest match color. This should only
773 * fail if the cell is read/write. Otherwise, we're incrementing
774 * the cell's reference count.
775 */
776 #ifdef XFree86Server
777 if (AllocColor(cmap,
778 &subColor.red, &subColor.green, &subColor.blue,
779 &subColor.pixel,
780 client) == Success) {
781 #else
782 if (XAllocColor(dpy, cmap, &subColor)) {
783 #endif
784 *alloced = 1;
785 }
786 else {
787 /* do this to work around a problem reported by Frank Ortega */
788 subColor.pixel = (unsigned long) bestmatch;
789 subColor.red = ctable[bestmatch].red;
790 subColor.green = ctable[bestmatch].green;
791 subColor.blue = ctable[bestmatch].blue;
792 subColor.flags = DoRed | DoGreen | DoBlue;
793 *alloced = 0;
794 }
795 #ifdef XFree86Server
796 FREE(ppixIn);
797 FREE(ctable);
798 #else
799 /* don't free table, save it for next time */
800 #endif
801
802 *color = subColor;
803 *exact = 0;
804 }
805
806
807
808
809 /*
810 * Do setup for PF_GRAYSCALE pixel format.
811 * Note that buffer may be NULL.
812 */
813 static GLboolean setup_grayscale( int client, XMesaVisual v,
814 XMesaBuffer buffer, XMesaColormap cmap )
815 {
816 if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
817 return GL_FALSE;
818 }
819
820 if (buffer) {
821 XMesaBuffer prevBuffer;
822
823 if (!cmap) {
824 return GL_FALSE;
825 }
826
827 prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
828 if (prevBuffer &&
829 (buffer->xm_visual->mesa_visual.rgbMode ==
830 prevBuffer->xm_visual->mesa_visual.rgbMode)) {
831 /* Copy colormap stuff from previous XMesaBuffer which uses same
832 * X colormap. Do this to avoid time spent in noFaultXAllocColor.
833 */
834 copy_colortable_info(buffer, prevBuffer);
835 }
836 else {
837 /* Allocate 256 shades of gray */
838 int gray;
839 int colorsfailed = 0;
840 for (gray=0;gray<256;gray++) {
841 GLint r = gamma_adjust( v->RedGamma, gray, 255 );
842 GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
843 GLint b = gamma_adjust( v->BlueGamma, gray, 255 );
844 int exact, alloced;
845 XMesaColor xcol;
846 xcol.red = (r << 8) | r;
847 xcol.green = (g << 8) | g;
848 xcol.blue = (b << 8) | b;
849 noFaultXAllocColor( client, v->display,
850 cmap, GET_COLORMAP_SIZE(v),
851 &xcol, &exact, &alloced );
852 if (!exact) {
853 colorsfailed++;
854 }
855 if (alloced) {
856 assert(buffer->num_alloced<256);
857 buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
858 buffer->num_alloced++;
859 }
860
861 /*OLD
862 assert(gray < 576);
863 buffer->color_table[gray*3+0] = xcol.pixel;
864 buffer->color_table[gray*3+1] = xcol.pixel;
865 buffer->color_table[gray*3+2] = xcol.pixel;
866 assert(xcol.pixel < 65536);
867 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
868 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
869 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
870 */
871 buffer->color_table[gray] = xcol.pixel;
872 assert(xcol.pixel < 65536);
873 buffer->pixel_to_r[xcol.pixel] = gray;
874 buffer->pixel_to_g[xcol.pixel] = gray;
875 buffer->pixel_to_b[xcol.pixel] = gray;
876 }
877
878 if (colorsfailed && getenv("MESA_DEBUG")) {
879 fprintf( stderr,
880 "Note: %d out of 256 needed colors do not match exactly.\n",
881 colorsfailed );
882 }
883 }
884 }
885
886 v->dithered_pf = PF_GRAYSCALE;
887 v->undithered_pf = PF_GRAYSCALE;
888 return GL_TRUE;
889 }
890
891
892
893 /*
894 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
895 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
896 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
897 * color. While this function was originally designed just for 8-bit
898 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
899 * Dithering code contributed by Bob Mercier.
900 */
901 static GLboolean setup_dithered_color( int client, XMesaVisual v,
902 XMesaBuffer buffer, XMesaColormap cmap )
903 {
904 if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
905 return GL_FALSE;
906 }
907
908 if (buffer) {
909 XMesaBuffer prevBuffer;
910
911 if (!cmap) {
912 return GL_FALSE;
913 }
914
915 prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
916 if (prevBuffer &&
917 (buffer->xm_visual->mesa_visual.rgbMode ==
918 prevBuffer->xm_visual->mesa_visual.rgbMode)) {
919 /* Copy colormap stuff from previous, matching XMesaBuffer.
920 * Do this to avoid time spent in noFaultXAllocColor.
921 */
922 copy_colortable_info(buffer, prevBuffer);
923 }
924 else {
925 /* Allocate X colors and initialize color_table[], red_table[], etc */
926 int r, g, b, i;
927 int colorsfailed = 0;
928 for (r = 0; r < _R; r++) {
929 for (g = 0; g < _G; g++) {
930 for (b = 0; b < _B; b++) {
931 XMesaColor xcol;
932 int exact, alloced;
933 xcol.red =gamma_adjust(v->RedGamma, r*65535/(_R-1),65535);
934 xcol.green=gamma_adjust(v->GreenGamma, g*65535/(_G-1),65535);
935 xcol.blue =gamma_adjust(v->BlueGamma, b*65535/(_B-1),65535);
936 noFaultXAllocColor( client, v->display,
937 cmap, GET_COLORMAP_SIZE(v),
938 &xcol, &exact, &alloced );
939 if (!exact) {
940 colorsfailed++;
941 }
942 if (alloced) {
943 assert(buffer->num_alloced<256);
944 buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
945 buffer->num_alloced++;
946 }
947 i = _MIX( r, g, b );
948 assert(i < 576);
949 buffer->color_table[i] = xcol.pixel;
950 assert(xcol.pixel < 65536);
951 buffer->pixel_to_r[xcol.pixel] = r * 255 / (_R-1);
952 buffer->pixel_to_g[xcol.pixel] = g * 255 / (_G-1);
953 buffer->pixel_to_b[xcol.pixel] = b * 255 / (_B-1);
954 }
955 }
956 }
957
958 if (colorsfailed && getenv("MESA_DEBUG")) {
959 fprintf( stderr,
960 "Note: %d out of %d needed colors do not match exactly.\n",
961 colorsfailed, _R*_G*_B );
962 }
963 }
964 }
965
966 v->dithered_pf = PF_DITHER;
967 v->undithered_pf = PF_LOOKUP;
968 return GL_TRUE;
969 }
970
971
972 /*
973 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
974 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
975 * Special dithering tables have to be initialized.
976 */
977 static void setup_8bit_hpcr( XMesaVisual v )
978 {
979 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be)
980 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
981 * on the root window AND the colormap obtainable by XGetRGBColormaps
982 * for that atom must be set on the window. (see also tkInitWindow)
983 * If that colormap is not set, the output will look stripy.
984 */
985
986 /* Setup color tables with gamma correction */
987 int i;
988 double g;
989
990 g = 1.0 / v->RedGamma;
991 for (i=0; i<256; i++) {
992 GLint red = IROUND_POS(255.0 * pow( hpcr_rgbTbl[0][i]/255.0, g ));
993 v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 );
994 }
995
996 g = 1.0 / v->GreenGamma;
997 for (i=0; i<256; i++) {
998 GLint green = IROUND_POS(255.0 * pow( hpcr_rgbTbl[1][i]/255.0, g ));
999 v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 );
1000 }
1001
1002 g = 1.0 / v->BlueGamma;
1003 for (i=0; i<256; i++) {
1004 GLint blue = IROUND_POS(255.0 * pow( hpcr_rgbTbl[2][i]/255.0, g ));
1005 v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 );
1006 }
1007 v->undithered_pf = PF_HPCR; /* can't really disable dithering for now */
1008 v->dithered_pf = PF_HPCR;
1009
1010 /* which method should I use to clear */
1011 /* GL_FALSE: keep the ordinary method */
1012 /* GL_TRUE : clear with dither pattern */
1013 v->hpcr_clear_flag = getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE;
1014
1015 if (v->hpcr_clear_flag) {
1016 v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display,
1017 DefaultRootWindow(v->display),
1018 16, 2, 8);
1019 #ifndef XFree86Server
1020 v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap,
1021 0, 0, 16, 2, AllPlanes, ZPixmap);
1022 #endif
1023 }
1024 }
1025
1026
1027 /*
1028 * Setup RGB rendering for a window with a True/DirectColor visual.
1029 */
1030 static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer,
1031 XMesaWindow window, XMesaColormap cmap )
1032 {
1033 unsigned long rmask, gmask, bmask;
1034 (void) buffer;
1035 (void) window;
1036 (void) cmap;
1037
1038 /* Compute red multiplier (mask) and bit shift */
1039 v->rshift = 0;
1040 rmask = GET_REDMASK(v);
1041 while ((rmask & 1)==0) {
1042 v->rshift++;
1043 rmask = rmask >> 1;
1044 }
1045
1046 /* Compute green multiplier (mask) and bit shift */
1047 v->gshift = 0;
1048 gmask = GET_GREENMASK(v);
1049 while ((gmask & 1)==0) {
1050 v->gshift++;
1051 gmask = gmask >> 1;
1052 }
1053
1054 /* Compute blue multiplier (mask) and bit shift */
1055 v->bshift = 0;
1056 bmask = GET_BLUEMASK(v);
1057 while ((bmask & 1)==0) {
1058 v->bshift++;
1059 bmask = bmask >> 1;
1060 }
1061
1062 /*
1063 * Compute component-to-pixel lookup tables and dithering kernel
1064 */
1065 {
1066 static GLubyte kernel[16] = {
1067 0*16, 8*16, 2*16, 10*16,
1068 12*16, 4*16, 14*16, 6*16,
1069 3*16, 11*16, 1*16, 9*16,
1070 15*16, 7*16, 13*16, 5*16,
1071 };
1072 GLint rBits = bitcount(rmask);
1073 GLint gBits = bitcount(gmask);
1074 GLint bBits = bitcount(bmask);
1075 GLint maxBits;
1076 GLuint i;
1077
1078 /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1079 for (i=0; i<=rmask; i++)
1080 v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
1081 for (i=0; i<=gmask; i++)
1082 v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
1083 for (i=0; i<=bmask; i++)
1084 v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
1085
1086 /* convert RGB values from [0,255] to pixel components */
1087
1088 for (i=0;i<256;i++) {
1089 GLint r = gamma_adjust(v->RedGamma, i, 255);
1090 GLint g = gamma_adjust(v->GreenGamma, i, 255);
1091 GLint b = gamma_adjust(v->BlueGamma, i, 255);
1092 v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
1093 v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
1094 v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
1095 }
1096 /* overflow protection */
1097 for (i=256;i<512;i++) {
1098 v->RtoPixel[i] = v->RtoPixel[255];
1099 v->GtoPixel[i] = v->GtoPixel[255];
1100 v->BtoPixel[i] = v->BtoPixel[255];
1101 }
1102
1103 /* setup dithering kernel */
1104 maxBits = rBits;
1105 if (gBits > maxBits) maxBits = gBits;
1106 if (bBits > maxBits) maxBits = bBits;
1107 for (i=0;i<16;i++) {
1108 v->Kernel[i] = kernel[i] >> maxBits;
1109 }
1110
1111 v->undithered_pf = PF_TRUECOLOR;
1112 v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_TRUEDITHER : PF_TRUECOLOR;
1113 }
1114
1115 /*
1116 * Now check for TrueColor visuals which we can optimize.
1117 */
1118 if ( GET_REDMASK(v) ==0x0000ff
1119 && GET_GREENMASK(v)==0x00ff00
1120 && GET_BLUEMASK(v) ==0xff0000
1121 && CHECK_BYTE_ORDER(v)
1122 && v->BitsPerPixel==32
1123 && sizeof(GLuint)==4
1124 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1125 /* common 32 bpp config used on SGI, Sun */
1126 v->undithered_pf = v->dithered_pf = PF_8A8B8G8R;
1127 }
1128 else if (GET_REDMASK(v) ==0xff0000
1129 && GET_GREENMASK(v)==0x00ff00
1130 && GET_BLUEMASK(v) ==0x0000ff
1131 && CHECK_BYTE_ORDER(v)
1132 && v->BitsPerPixel==32
1133 && sizeof(GLuint)==4
1134 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1135 /* common 32 bpp config used on Linux, HP, IBM */
1136 v->undithered_pf = v->dithered_pf = PF_8R8G8B;
1137 }
1138 else if (GET_REDMASK(v) ==0xff0000
1139 && GET_GREENMASK(v)==0x00ff00
1140 && GET_BLUEMASK(v) ==0x0000ff
1141 && CHECK_BYTE_ORDER(v)
1142 && v->BitsPerPixel==24
1143 && sizeof(GLuint)==4
1144 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1145 /* common packed 24 bpp config used on Linux */
1146 v->undithered_pf = v->dithered_pf = PF_8R8G8B24;
1147 }
1148 else if (GET_REDMASK(v) ==0xf800
1149 && GET_GREENMASK(v)==0x07e0
1150 && GET_BLUEMASK(v) ==0x001f
1151 && CHECK_BYTE_ORDER(v)
1152 && v->BitsPerPixel==16
1153 && sizeof(GLushort)==2
1154 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1155 /* 5-6-5 color weight on common PC VGA boards */
1156 v->undithered_pf = PF_5R6G5B;
1157 v->dithered_pf = PF_DITHER_5R6G5B;
1158 }
1159 else if (GET_REDMASK(v) ==0xe0
1160 && GET_GREENMASK(v)==0x1c
1161 && GET_BLUEMASK(v) ==0x03
1162 && CHECK_FOR_HPCR(v)) {
1163 setup_8bit_hpcr( v );
1164 }
1165 }
1166
1167
1168
1169 /*
1170 * Setup RGB rendering for a window with a monochrome visual.
1171 */
1172 static void setup_monochrome( XMesaVisual v, XMesaBuffer b )
1173 {
1174 (void) b;
1175 v->dithered_pf = v->undithered_pf = PF_1BIT;
1176 /* if black=1 then we must flip pixel values */
1177 v->bitFlip = (GET_BLACK_PIXEL(v) != 0);
1178 }
1179
1180
1181
1182 /*
1183 * When a context is "made current" for the first time, we can finally
1184 * finish initializing the context's visual and buffer information.
1185 * Input: v - the XMesaVisual to initialize
1186 * b - the XMesaBuffer to initialize (may be NULL)
1187 * rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1188 * window - the window/pixmap we're rendering into
1189 * cmap - the colormap associated with the window/pixmap
1190 * Return: GL_TRUE=success, GL_FALSE=failure
1191 */
1192 static GLboolean initialize_visual_and_buffer( int client,
1193 XMesaVisual v,
1194 XMesaBuffer b,
1195 GLboolean rgb_flag,
1196 XMesaDrawable window,
1197 XMesaColormap cmap
1198 )
1199 {
1200 #ifndef XFree86Server
1201 XGCValues gcvalues;
1202 #endif
1203
1204 if (b) {
1205 assert(b->xm_visual == v);
1206 }
1207
1208 /* Save true bits/pixel */
1209 v->BitsPerPixel = GET_BITS_PER_PIXEL(v);
1210 assert(v->BitsPerPixel > 0);
1211
1212
1213 if (rgb_flag==GL_FALSE) {
1214 /* COLOR-INDEXED WINDOW:
1215 * Even if the visual is TrueColor or DirectColor we treat it as
1216 * being color indexed. This is weird but might be useful to someone.
1217 */
1218 v->dithered_pf = v->undithered_pf = PF_INDEX;
1219 v->index_bits = GET_VISUAL_DEPTH(v);
1220 }
1221 else {
1222 /* RGB WINDOW:
1223 * We support RGB rendering into almost any kind of visual.
1224 */
1225 int xclass;
1226 xclass = GET_VISUAL_CLASS(v);
1227 if (xclass==TrueColor || xclass==DirectColor) {
1228 setup_truecolor( v, b, (XMesaWindow)window, cmap );
1229 }
1230 else if (xclass==StaticGray && GET_VISUAL_DEPTH(v)==1) {
1231 setup_monochrome( v, b );
1232 }
1233 else if (xclass==GrayScale || xclass==StaticGray) {
1234 if (!setup_grayscale( client, v, b, cmap )) {
1235 return GL_FALSE;
1236 }
1237 }
1238 else if ((xclass==PseudoColor || xclass==StaticColor)
1239 && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
1240 if (!setup_dithered_color( client, v, b, cmap )) {
1241 return GL_FALSE;
1242 }
1243 }
1244 else {
1245 error("XMesa: RGB mode rendering not supported in given visual.");
1246 return GL_FALSE;
1247 }
1248 v->index_bits = 0;
1249
1250 if (getenv("MESA_NO_DITHER")) {
1251 v->dithered_pf = v->undithered_pf;
1252 }
1253 }
1254
1255
1256 /*
1257 * If MESA_INFO env var is set print out some debugging info
1258 * which can help Brian figure out what's going on when a user
1259 * reports bugs.
1260 */
1261 if (getenv("MESA_INFO")) {
1262 fprintf(stderr, "X/Mesa visual = %p\n", v);
1263 fprintf(stderr, "X/Mesa dithered pf = %u\n", v->dithered_pf);
1264 fprintf(stderr, "X/Mesa undithered pf = %u\n", v->undithered_pf);
1265 fprintf(stderr, "X/Mesa level = %d\n", v->level);
1266 fprintf(stderr, "X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
1267 fprintf(stderr, "X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
1268 }
1269
1270 if (b && window) {
1271 /* Do window-specific initializations */
1272
1273 /* Window dimensions */
1274 unsigned int w, h;
1275 get_drawable_size( v->display, window, &w, &h );
1276 b->width = w;
1277 b->height = h;
1278
1279 b->frontbuffer = window;
1280
1281 /* Setup for single/double buffering */
1282 if (v->mesa_visual.doubleBufferMode) {
1283 /* Double buffered */
1284 #ifndef XFree86Server
1285 b->shm = check_for_xshm( v->display );
1286 #endif
1287 xmesa_alloc_back_buffer( b );
1288 if (b->db_state==BACK_PIXMAP) {
1289 b->buffer = (XMesaDrawable)b->backpixmap;
1290 }
1291 else {
1292 b->buffer = XIMAGE;
1293 }
1294 }
1295 else {
1296 /* Single Buffered */
1297 b->buffer = b->frontbuffer;
1298 }
1299
1300 /* X11 graphics contexts */
1301 #ifdef XFree86Server
1302 b->gc = CreateScratchGC(v->display, window->depth);
1303 #else
1304 b->gc = XCreateGC( v->display, window, 0, NULL );
1305 #endif
1306 XMesaSetFunction( v->display, b->gc, GXcopy );
1307
1308 /*
1309 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1310 * Patch contributed by Michael Pichler May 15, 1995.
1311 */
1312 #ifdef XFree86Server
1313 b->cleargc = CreateScratchGC(v->display, window->depth);
1314 {
1315 CARD32 v[1];
1316 v[0] = FALSE;
1317 dixChangeGC(NullClient, b->cleargc, GCGraphicsExposures, v, NULL);
1318 }
1319 #else
1320 gcvalues.graphics_exposures = False;
1321 b->cleargc = XCreateGC( v->display, window,
1322 GCGraphicsExposures, &gcvalues);
1323 #endif
1324 XMesaSetFunction( v->display, b->cleargc, GXcopy );
1325 /*
1326 * Set fill style and tile pixmap once for all for HPCR stuff
1327 * (instead of doing it each time in clear_color_HPCR_pixmap())
1328 * Initialize whole stuff
1329 * Patch contributed by Jacques Leroy March 8, 1998.
1330 */
1331 if (v->hpcr_clear_flag && b->buffer!=XIMAGE) {
1332 int i;
1333 for (i=0; i<16; i++)
1334 {
1335 XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0);
1336 XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0);
1337 }
1338 XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap,
1339 b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
1340 XMesaSetFillStyle( v->display, b->cleargc, FillTiled);
1341 XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap );
1342 }
1343
1344 /* Initialize the row buffer XImage for use in write_color_span() */
1345 #ifdef XFree86Server
1346 b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1,
1347 (char *)MALLOC(MAX_WIDTH*4));
1348 #else
1349 b->rowimage = XCreateImage( v->display,
1350 v->visinfo->visual,
1351 v->visinfo->depth,
1352 ZPixmap, 0, /*format, offset*/
1353 (char*) MALLOC(MAX_WIDTH*4), /*data*/
1354 MAX_WIDTH, 1, /*width, height*/
1355 32, /*bitmap_pad*/
1356 0 /*bytes_per_line*/ );
1357 #endif
1358 }
1359
1360 return GL_TRUE;
1361 }
1362
1363
1364
1365 /*
1366 * Convert an RGBA color to a pixel value.
1367 */
1368 unsigned long
1369 xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a,
1370 GLuint pixelFormat)
1371 {
1372 switch (pixelFormat) {
1373 case PF_INDEX:
1374 return 0;
1375 case PF_TRUECOLOR:
1376 {
1377 unsigned long p;
1378 PACK_TRUECOLOR( p, r, g, b );
1379 return p;
1380 }
1381 case PF_8A8B8G8R:
1382 return PACK_8A8B8G8R( r, g, b, a );
1383 case PF_8R8G8B:
1384 /* fall through */
1385 case PF_8R8G8B24:
1386 return PACK_8R8G8B( r, g, b );
1387 case PF_5R6G5B:
1388 return PACK_5R6G5B( r, g, b );
1389 case PF_DITHER:
1390 {
1391 DITHER_SETUP;
1392 return DITHER( 1, 0, r, g, b );
1393 }
1394 case PF_1BIT:
1395 /* 382 = (3*255)/2 */
1396 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
1397 case PF_HPCR:
1398 return DITHER_HPCR(1, 1, r, g, b);
1399 case PF_LOOKUP:
1400 {
1401 LOOKUP_SETUP;
1402 return LOOKUP( r, g, b );
1403 }
1404 case PF_GRAYSCALE:
1405 return GRAY_RGB( r, g, b );
1406 case PF_TRUEDITHER:
1407 /* fall through */
1408 case PF_DITHER_5R6G5B:
1409 {
1410 unsigned long p;
1411 PACK_TRUEDITHER(p, 1, 0, r, g, b);
1412 return p;
1413 }
1414 default:
1415 _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel");
1416 }
1417 return 0;
1418 }
1419
1420
1421 /**********************************************************************/
1422 /***** Public Functions *****/
1423 /**********************************************************************/
1424
1425
1426 /*
1427 * Create a new X/Mesa visual.
1428 * Input: display - X11 display
1429 * visinfo - an XVisualInfo pointer
1430 * rgb_flag - GL_TRUE = RGB mode,
1431 * GL_FALSE = color index mode
1432 * alpha_flag - alpha buffer requested?
1433 * db_flag - GL_TRUE = double-buffered,
1434 * GL_FALSE = single buffered
1435 * stereo_flag - stereo visual?
1436 * ximage_flag - GL_TRUE = use an XImage for back buffer,
1437 * GL_FALSE = use an off-screen pixmap for back buffer
1438 * depth_size - requested bits/depth values, or zero
1439 * stencil_size - requested bits/stencil values, or zero
1440 * accum_red_size - requested bits/red accum values, or zero
1441 * accum_green_size - requested bits/green accum values, or zero
1442 * accum_blue_size - requested bits/blue accum values, or zero
1443 * accum_alpha_size - requested bits/alpha accum values, or zero
1444 * num_samples - number of samples/pixel if multisampling, or zero
1445 * level - visual level, usually 0
1446 * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT
1447 * Return; a new XMesaVisual or 0 if error.
1448 */
1449 XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
1450 XMesaVisualInfo visinfo,
1451 GLboolean rgb_flag,
1452 GLboolean alpha_flag,
1453 GLboolean db_flag,
1454 GLboolean stereo_flag,
1455 GLboolean ximage_flag,
1456 GLint depth_size,
1457 GLint stencil_size,
1458 GLint accum_red_size,
1459 GLint accum_green_size,
1460 GLint accum_blue_size,
1461 GLint accum_alpha_size,
1462 GLint num_samples,
1463 GLint level,
1464 GLint visualCaveat )
1465 {
1466 char *gamma;
1467 XMesaVisual v;
1468 GLint red_bits, green_bits, blue_bits, alpha_bits;
1469
1470 /* For debugging only */
1471 if (getenv("MESA_XSYNC")) {
1472 /* This makes debugging X easier.
1473 * In your debugger, set a breakpoint on _XError to stop when an
1474 * X protocol error is generated.
1475 */
1476 #ifdef XFree86Server
1477 /* NOT_NEEDED */
1478 #else
1479 XSynchronize( display, 1 );
1480 #endif
1481 }
1482
1483 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
1484 if (!v) {
1485 return NULL;
1486 }
1487
1488 /*
1489 * In the X server, NULL is passed in for the display. It will have
1490 * to be set before using this visual. See XMesaSetVisualDisplay()
1491 * below.
1492 */
1493 v->display = display;
1494
1495 /* Save a copy of the XVisualInfo struct because the user may XFREE()
1496 * the struct but we may need some of the information contained in it
1497 * at a later time.
1498 */
1499 #ifdef XFree86Server
1500 v->visinfo = visinfo;
1501 #else
1502 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
1503 if(!v->visinfo) {
1504 FREE(v);
1505 return NULL;
1506 }
1507 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
1508
1509 /* Save a copy of the pointer now so we can find this visual again
1510 * if we need to search for it in find_glx_visual().
1511 */
1512 v->vishandle = visinfo;
1513 #endif
1514
1515 #ifdef XFree86Server
1516 /* Initialize the depth of the screen */
1517 {
1518 PixmapFormatRec *format;
1519
1520 for (format = screenInfo.formats;
1521 format->depth != display->rootDepth;
1522 format++)
1523 ;
1524 v->screen_depth = format->bitsPerPixel;
1525 }
1526 #endif
1527
1528 /* check for MESA_GAMMA environment variable */
1529 gamma = getenv("MESA_GAMMA");
1530 if (gamma) {
1531 v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
1532 sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
1533 if (v->RedGamma<=0.0) v->RedGamma = 1.0;
1534 if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma;
1535 if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma;
1536 }
1537 else {
1538 v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
1539 }
1540
1541 v->ximage_flag = ximage_flag;
1542 v->level = level;
1543 v->VisualCaveat = visualCaveat;
1544
1545 (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 );
1546
1547 {
1548 int xclass;
1549 xclass = GET_VISUAL_CLASS(v);
1550 if (xclass==TrueColor || xclass==DirectColor) {
1551 red_bits = bitcount(GET_REDMASK(v));
1552 green_bits = bitcount(GET_GREENMASK(v));
1553 blue_bits = bitcount(GET_BLUEMASK(v));
1554 alpha_bits = 0;
1555 }
1556 else {
1557 /* this is an approximation */
1558 int depth;
1559 depth = GET_VISUAL_DEPTH(v);
1560 red_bits = depth / 3;
1561 depth -= red_bits;
1562 green_bits = depth / 2;
1563 depth -= green_bits;
1564 blue_bits = depth;
1565 alpha_bits = 0;
1566 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
1567 }
1568 }
1569
1570 if (alpha_flag && alpha_bits == 0)
1571 alpha_bits = 8;
1572
1573 _mesa_initialize_visual( &v->mesa_visual,
1574 rgb_flag, db_flag, stereo_flag,
1575 red_bits, green_bits,
1576 blue_bits, alpha_bits,
1577 v->index_bits,
1578 depth_size,
1579 stencil_size,
1580 accum_red_size, accum_green_size,
1581 accum_blue_size, accum_alpha_size,
1582 0 );
1583 return v;
1584 }
1585
1586
1587 void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v )
1588 {
1589 v->display = dpy;
1590 }
1591
1592
1593 void XMesaDestroyVisual( XMesaVisual v )
1594 {
1595 #ifndef XFree86Server
1596 FREE(v->visinfo);
1597 #endif
1598 FREE(v);
1599 }
1600
1601
1602
1603 /*
1604 * Create a new XMesaContext.
1605 * Input: v - XMesaVisual
1606 * share_list - another XMesaContext with which to share display
1607 * lists or NULL if no sharing is wanted.
1608 * Return: an XMesaContext or NULL if error.
1609 */
1610 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
1611 {
1612 XMesaContext c;
1613 GLcontext *ctx;
1614 GLboolean direct = GL_TRUE; /* XXXX */
1615 /* NOT_DONE: should this be GL_FALSE??? */
1616 static GLboolean firstTime = GL_TRUE;
1617
1618 if (firstTime) {
1619 _glthread_INIT_MUTEX(_xmesa_lock);
1620 firstTime = GL_FALSE;
1621 }
1622
1623 c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
1624 if (!c) {
1625 return NULL;
1626 }
1627
1628 ctx = c->gl_ctx = _mesa_create_context( &v->mesa_visual,
1629 share_list ? share_list->gl_ctx : (GLcontext *) NULL,
1630 (void *) c, direct );
1631 if (!c->gl_ctx) {
1632 FREE(c);
1633 return NULL;
1634 }
1635
1636 _mesa_enable_sw_extensions(ctx);
1637
1638 if (CHECK_BYTE_ORDER(v)) {
1639 c->swapbytes = GL_FALSE;
1640 }
1641 else {
1642 c->swapbytes = GL_TRUE;
1643 }
1644
1645 c->xm_visual = v;
1646 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
1647 c->display = v->display;
1648 c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */
1649
1650 ctx->Driver.UpdateState = xmesa_update_state;
1651
1652 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1653 c->driContextPriv = driContextPriv;
1654 #endif
1655
1656 /* Initialize the software rasterizer and helper modules.
1657 */
1658 _swrast_CreateContext( ctx );
1659 _ac_CreateContext( ctx );
1660 _tnl_CreateContext( ctx );
1661 _swsetup_CreateContext( ctx );
1662
1663 xmesa_register_swrast_functions( ctx );
1664
1665 /* Set up some constant pointers:
1666 */
1667 xmesa_init_pointers( ctx );
1668
1669
1670 /* Run the config file
1671 */
1672 _mesa_context_initialize( ctx );
1673
1674
1675 return c;
1676 }
1677
1678
1679
1680
1681 void XMesaDestroyContext( XMesaContext c )
1682 {
1683 #ifdef FX
1684 if (c->xm_buffer && c->xm_buffer->FXctx)
1685 fxMesaDestroyContext(c->xm_buffer->FXctx);
1686 #endif
1687 if (c->gl_ctx) {
1688 _swsetup_DestroyContext( c->gl_ctx );
1689 _swrast_DestroyContext( c->gl_ctx );
1690 _tnl_DestroyContext( c->gl_ctx );
1691 _ac_DestroyContext( c->gl_ctx );
1692 _mesa_destroy_context( c->gl_ctx );
1693 }
1694
1695 /* Disassociate old buffer with this context */
1696 if (c->xm_buffer)
1697 c->xm_buffer->xm_context = NULL;
1698
1699 /* Destroy any buffers which are using this context. If we don't
1700 * we may have dangling references. Hmm, maybe we should just
1701 * set the buffer's context pointer to NULL instead of deleting it?
1702 * Let's see if we get any bug reports...
1703 * This contributed by Doug Rabson <dfr@calcaphon.com>
1704 */
1705 {
1706 XMesaBuffer b, next;
1707 for (b = XMesaBufferList; b; b = next) {
1708 next = b->Next;
1709 if (!b->pixmap_flag) {
1710 #ifndef XFree86Server
1711 XSync(b->display, False);
1712 #endif
1713 if (b->xm_context == c) {
1714 /* found a context created for this context */
1715 XMesaDestroyBuffer( b );
1716 }
1717 }
1718 }
1719 }
1720
1721 FREE( c );
1722 }
1723
1724
1725
1726 /*
1727 * XXX this isn't a public function! It's a hack for the 3Dfx driver.
1728 * Create a new XMesaBuffer from an X window.
1729 * Input: v - the XMesaVisual
1730 * w - the window
1731 * c - the context
1732 * Return: new XMesaBuffer or NULL if error
1733 */
1734 XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w,
1735 XMesaContext c )
1736 {
1737 #ifndef XFree86Server
1738 XWindowAttributes attr;
1739 #endif
1740 #ifdef FX
1741 char *fxEnvVar;
1742 #endif
1743 int client = 0;
1744
1745 XMesaBuffer b = alloc_xmesa_buffer();
1746 if (!b) {
1747 return NULL;
1748 }
1749
1750 (void) c;
1751
1752 #ifdef XFree86Server
1753 client = CLIENT_ID(((XMesaDrawable)w)->id);
1754 #endif
1755
1756 assert(v);
1757
1758 #ifdef XFree86Server
1759 if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
1760 #else
1761 XGetWindowAttributes( v->display, w, &attr );
1762
1763 if (GET_VISUAL_DEPTH(v) != attr.depth) {
1764 #endif
1765 if (getenv("MESA_DEBUG")) {
1766 fprintf(stderr, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n");
1767 }
1768 return NULL;
1769 }
1770
1771 b->xm_context = NULL; /* Associate no context with this buffer */
1772
1773 b->xm_visual = v;
1774 b->pixmap_flag = GL_FALSE;
1775 b->display = v->display;
1776 #ifdef XFree86Server
1777 b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1778 #else
1779 if (attr.colormap) {
1780 b->cmap = attr.colormap;
1781 }
1782 else {
1783 if (getenv("MESA_DEBUG")) {
1784 fprintf(stderr, "Window %u has no colormap!\n", (unsigned int) w);
1785 }
1786 /* this is weird, a window w/out a colormap!? */
1787 /* OK, let's just allocate a new one and hope for the best */
1788 b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1789 }
1790 #endif
1791
1792 /* determine back buffer implementation */
1793 if (v->mesa_visual.doubleBufferMode) {
1794 if (v->ximage_flag) {
1795 b->db_state = BACK_XIMAGE;
1796 }
1797 else {
1798 b->db_state = BACK_PIXMAP;
1799 }
1800 }
1801 else {
1802 b->db_state = 0;
1803 }
1804
1805 _mesa_initialize_framebuffer(&b->mesa_buffer,
1806 &v->mesa_visual,
1807 v->mesa_visual.depthBits > 0,
1808 v->mesa_visual.stencilBits > 0,
1809 v->mesa_visual.accumRedBits > 0,
1810 v->mesa_visual.alphaBits > 0 );
1811
1812 if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
1813 (XMesaDrawable)w, b->cmap )) {
1814 free_xmesa_buffer(client, b);
1815 return NULL;
1816 }
1817
1818 #ifdef FX
1819 fxEnvVar = getenv("MESA_GLX_FX");
1820 if (fxEnvVar) {
1821 if (fxEnvVar[0]!='d') {
1822 int attribs[100];
1823 int numAttribs = 0;
1824 int hw;
1825 if (v->mesa_visual.depthBits > 0) {
1826 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
1827 attribs[numAttribs++] = 1;
1828 }
1829 if (v->mesa_visual.doubleBufferMode) {
1830 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
1831 }
1832 if (v->mesa_visual.accumRedBits > 0) {
1833 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
1834 attribs[numAttribs++] = v->mesa_visual.accumRedBits;
1835 }
1836 if (v->mesa_visual.stencilBits > 0) {
1837 attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
1838 attribs[numAttribs++] = v->mesa_visual.stencilBits;
1839 }
1840 if (v->mesa_visual.alphaBits > 0) {
1841 attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
1842 attribs[numAttribs++] = 1;
1843 }
1844 if (c->gl_ctx) {
1845 #define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with fxapi.c! */
1846 attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
1847 attribs[numAttribs++] = (int) c->gl_ctx;
1848 }
1849 attribs[numAttribs++] = FXMESA_NONE;
1850
1851 if ((hw = fxQueryHardware())==GR_SSTTYPE_VOODOO) {
1852 b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
1853 if ((v->undithered_pf!=PF_INDEX) && (b->backimage)) {
1854 b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
1855 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1856 b->FXwindowHack = b->FXctx ? GL_TRUE : GL_FALSE;
1857 else
1858 b->FXwindowHack = GL_FALSE;
1859 }
1860 }
1861 else {
1862 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1863 b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
1864 GR_REFRESH_75Hz, attribs);
1865 else
1866 b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
1867 b->FXisHackUsable = GL_FALSE;
1868 b->FXwindowHack = GL_FALSE;
1869 }
1870 /*
1871 fprintf(stderr,
1872 "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1873 hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
1874 */
1875 }
1876 }
1877 else {
1878 fprintf(stderr,"WARNING: This Mesa Library includes the Glide driver but\n");
1879 fprintf(stderr," you have not defined the MESA_GLX_FX env. var.\n");
1880 fprintf(stderr," (check the README.3DFX file for more information).\n\n");
1881 fprintf(stderr," you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1882 }
1883 #endif
1884
1885 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1886 b->driDrawPriv = driDrawPriv;
1887 #endif
1888
1889 return b;
1890 }
1891
1892
1893 XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w )
1894 {
1895 return XMesaCreateWindowBuffer2( v, w, NULL );
1896 }
1897
1898
1899 /*
1900 * Create a new XMesaBuffer from an X pixmap.
1901 * Input: v - the XMesaVisual
1902 * p - the pixmap
1903 * cmap - the colormap, may be 0 if using a TrueColor or DirectColor
1904 * visual for the pixmap
1905 * Return: new XMesaBuffer or NULL if error
1906 */
1907 XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v,
1908 XMesaPixmap p, XMesaColormap cmap )
1909 {
1910 int client = 0;
1911 XMesaBuffer b = alloc_xmesa_buffer();
1912 if (!b) {
1913 return NULL;
1914 }
1915
1916
1917 #ifdef XFree86Server
1918 client = CLIENT_ID(((XMesaDrawable)p)->id);
1919 #endif
1920
1921 assert(v);
1922
1923 b->xm_context = NULL; /* Associate no context with this buffer */
1924
1925 b->xm_visual = v;
1926 b->pixmap_flag = GL_TRUE;
1927 b->display = v->display;
1928 b->cmap = cmap;
1929
1930 /* determine back buffer implementation */
1931 if (v->mesa_visual.doubleBufferMode) {
1932 if (v->ximage_flag) {
1933 b->db_state = BACK_XIMAGE;
1934 }
1935 else {
1936 b->db_state = BACK_PIXMAP;
1937 }
1938 }
1939 else {
1940 b->db_state = 0;
1941 }
1942
1943 _mesa_initialize_framebuffer(&b->mesa_buffer,
1944 &v->mesa_visual,
1945 v->mesa_visual.depthBits > 0,
1946 v->mesa_visual.stencilBits > 0,
1947 v->mesa_visual.accumRedBits +
1948 v->mesa_visual.accumGreenBits +
1949 v->mesa_visual.accumBlueBits > 0,
1950 v->mesa_visual.alphaBits > 0 );
1951
1952 if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1953 (XMesaDrawable)p, cmap)) {
1954 free_xmesa_buffer(client, b);
1955 return NULL;
1956 }
1957
1958 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1959 b->driDrawPriv = driDrawPriv;
1960 #endif
1961
1962 return b;
1963 }
1964
1965
1966
1967 /*
1968 * Deallocate an XMesaBuffer structure and all related info.
1969 */
1970 void XMesaDestroyBuffer( XMesaBuffer b )
1971 {
1972 int client = 0;
1973
1974 #ifdef XFree86Server
1975 if (b->frontbuffer)
1976 client = CLIENT_ID(b->frontbuffer->id);
1977 #endif
1978
1979 if (b->gc) XMesaFreeGC( b->xm_visual->display, b->gc );
1980 if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc );
1981
1982 if (b->backimage) {
1983 #if defined(USE_XSHM) && !defined(XFree86Server)
1984 if (b->shm) {
1985 XShmDetach( b->xm_visual->display, &b->shminfo );
1986 XDestroyImage( b->backimage );
1987 shmdt( b->shminfo.shmaddr );
1988 }
1989 else
1990 #endif
1991 XMesaDestroyImage( b->backimage );
1992 }
1993 if (b->backpixmap) {
1994 XMesaFreePixmap( b->xm_visual->display, b->backpixmap );
1995 if (b->xm_visual->hpcr_clear_flag) {
1996 XMesaFreePixmap( b->xm_visual->display,
1997 b->xm_visual->hpcr_clear_pixmap );
1998 XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
1999 }
2000 }
2001 if (b->rowimage) {
2002 FREE( b->rowimage->data );
2003 b->rowimage->data = NULL;
2004 XMesaDestroyImage( b->rowimage );
2005 }
2006
2007 if (b->xm_context)
2008 b->xm_context->xm_buffer = NULL;
2009
2010 free_xmesa_buffer(client, b);
2011 }
2012
2013
2014
2015 /*
2016 * Bind buffer b to context c and make c the current rendering context.
2017 */
2018 GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
2019 {
2020 return XMesaMakeCurrent2( c, b, b );
2021 }
2022
2023
2024 /*
2025 * Bind buffer b to context c and make c the current rendering context.
2026 */
2027 GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
2028 XMesaBuffer readBuffer )
2029 {
2030 if (c) {
2031 if (!drawBuffer || !readBuffer)
2032 return GL_FALSE; /* must specify buffers! */
2033
2034 #ifdef FX
2035 if (drawBuffer->FXctx) {
2036 fxMesaMakeCurrent(drawBuffer->FXctx);
2037
2038 /* Disassociate old buffer from this context */
2039 if (c->xm_buffer)
2040 c->xm_buffer->xm_context = NULL;
2041
2042 /* Associate the context with this buffer */
2043 drawBuffer->xm_context = c;
2044
2045 c->xm_buffer = drawBuffer;
2046 c->xm_read_buffer = readBuffer;
2047 c->use_read_buffer = (drawBuffer != readBuffer);
2048
2049 return GL_TRUE;
2050 }
2051 #endif
2052 if (c->gl_ctx == _mesa_get_current_context()
2053 && c->xm_buffer == drawBuffer
2054 && c->xm_read_buffer == readBuffer
2055 && c->xm_buffer->wasCurrent) {
2056 /* same context and buffer, do nothing */
2057 return GL_TRUE;
2058 }
2059
2060 /* Disassociate old buffer with this context */
2061 if (c->xm_buffer)
2062 c->xm_buffer->xm_context = NULL;
2063 drawBuffer->xm_context = c; /* Associate the context with this buffer */
2064
2065 c->xm_buffer = drawBuffer;
2066 c->xm_read_buffer = readBuffer;
2067 c->use_read_buffer = (drawBuffer != readBuffer);
2068
2069 _mesa_make_current2(c->gl_ctx,
2070 &drawBuffer->mesa_buffer,
2071 &readBuffer->mesa_buffer);
2072
2073 if (c->gl_ctx->Viewport.Width == 0) {
2074 /* initialize viewport to window size */
2075 _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height );
2076 c->gl_ctx->Scissor.Width = drawBuffer->width;
2077 c->gl_ctx->Scissor.Height = drawBuffer->height;
2078 }
2079
2080 if (c->xm_visual->mesa_visual.rgbMode) {
2081 /*
2082 * Must recompute and set these pixel values because colormap
2083 * can be different for different windows.
2084 */
2085 c->clearpixel = xmesa_color_to_pixel( c,
2086 c->clearcolor[0],
2087 c->clearcolor[1],
2088 c->clearcolor[2],
2089 c->clearcolor[3],
2090 c->xm_visual->undithered_pf);
2091 XMesaSetForeground(c->display, c->xm_buffer->cleargc, c->clearpixel);
2092 }
2093
2094 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2095 c->xm_buffer->wasCurrent = GL_TRUE;
2096 }
2097 else {
2098 /* Detach */
2099 _mesa_make_current2( NULL, NULL, NULL );
2100 }
2101 return GL_TRUE;
2102 }
2103
2104
2105 /*
2106 * Unbind the context c from its buffer.
2107 */
2108 GLboolean XMesaUnbindContext( XMesaContext c )
2109 {
2110 /* A no-op for XFree86 integration purposes */
2111 return GL_TRUE;
2112 }
2113
2114
2115 XMesaContext XMesaGetCurrentContext( void )
2116 {
2117 GET_CURRENT_CONTEXT(ctx);
2118 if (ctx) {
2119 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2120 return xmesa;
2121 }
2122 else {
2123 return 0;
2124 }
2125 }
2126
2127
2128 XMesaBuffer XMesaGetCurrentBuffer( void )
2129 {
2130 GET_CURRENT_CONTEXT(ctx);
2131 if (ctx) {
2132 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2133 return xmesa->xm_buffer;
2134 }
2135 else {
2136 return 0;
2137 }
2138 }
2139
2140
2141 /* New in Mesa 3.1 */
2142 XMesaBuffer XMesaGetCurrentReadBuffer( void )
2143 {
2144 GET_CURRENT_CONTEXT(ctx);
2145 if (ctx) {
2146 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2147 return xmesa->xm_buffer;
2148 }
2149 else {
2150 return 0;
2151 }
2152 }
2153
2154
2155 GLboolean XMesaForceCurrent(XMesaContext c)
2156 {
2157 if (c) {
2158 if (c->gl_ctx != _mesa_get_current_context()) {
2159 _mesa_make_current(c->gl_ctx, &c->xm_buffer->mesa_buffer);
2160 }
2161 }
2162 else {
2163 _mesa_make_current(NULL, NULL);
2164 }
2165 return GL_TRUE;
2166 }
2167
2168
2169 GLboolean XMesaLoseCurrent(XMesaContext c)
2170 {
2171 (void) c;
2172 _mesa_make_current(NULL, NULL);
2173 return GL_TRUE;
2174 }
2175
2176
2177 /*
2178 * Switch 3Dfx support hack between window and full-screen mode.
2179 */
2180 GLboolean XMesaSetFXmode( GLint mode )
2181 {
2182 #ifdef FX
2183 const char *fx = getenv("MESA_GLX_FX");
2184 if (fx && fx[0] != 'd') {
2185 GET_CURRENT_CONTEXT(ctx);
2186 GrHwConfiguration hw;
2187 if (!FX_grSstQueryHardware(&hw)) {
2188 /*fprintf(stderr, "!grSstQueryHardware\n");*/
2189 return GL_FALSE;
2190 }
2191 if (hw.num_sst < 1) {
2192 /*fprintf(stderr, "hw.num_sst < 1\n");*/
2193 return GL_FALSE;
2194 }
2195 if (ctx) {
2196 XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2197 if (mode == XMESA_FX_WINDOW) {
2198 if (xmesa->xm_buffer->FXisHackUsable) {
2199 FX_grSstControl(GR_CONTROL_DEACTIVATE);
2200 xmesa->xm_buffer->FXwindowHack = GL_TRUE;
2201 return GL_TRUE;
2202 }
2203 }
2204 else if (mode == XMESA_FX_FULLSCREEN) {
2205 FX_grSstControl(GR_CONTROL_ACTIVATE);
2206 xmesa->xm_buffer->FXwindowHack = GL_FALSE;
2207 return GL_TRUE;
2208 }
2209 else {
2210 /* Error: Bad mode value */
2211 }
2212 }
2213 }
2214 /*fprintf(stderr, "fallthrough\n");*/
2215 #else
2216 (void) mode;
2217 #endif
2218 return GL_FALSE;
2219 }
2220
2221
2222
2223 #ifdef FX
2224 /*
2225 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2226 */
2227 static void FXgetImage( XMesaBuffer b )
2228 {
2229 static unsigned short pixbuf[MAX_WIDTH];
2230 GLuint x, y;
2231 int xpos, ypos;
2232 XMesaWindow root;
2233 unsigned int bw, depth, width, height;
2234 XMesaContext xmesa = (XMesaContext) b->xm_context->gl_ctx->DriverCtx;
2235
2236 assert(xmesa->xm_buffer->FXctx);
2237
2238 #ifdef XFree86Server
2239 x = b->frontbuffer->x;
2240 y = b->frontbuffer->y;
2241 width = b->frontbuffer->width;
2242 height = b->frontbuffer->height;
2243 depth = b->frontbuffer->depth;
2244 #else
2245 XGetGeometry( xmesa->xm_visual->display, b->frontbuffer,
2246 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2247 #endif
2248 if (b->width != width || b->height != height) {
2249 b->width = MIN2((int)width, xmesa->xm_buffer->FXctx->width);
2250 b->height = MIN2((int)height, xmesa->xm_buffer->FXctx->height);
2251 if (b->width & 1)
2252 b->width--; /* prevent odd width */
2253 xmesa_alloc_back_buffer( b );
2254 }
2255
2256 grLfbWriteColorFormat(GR_COLORFORMAT_ARGB);
2257 if (xmesa->xm_visual->undithered_pf==PF_5R6G5B) {
2258 /* Special case: 16bpp RGB */
2259 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */
2260 0, xmesa->xm_buffer->FXctx->height - b->height, /*pos*/
2261 b->width, b->height, /* size */
2262 b->width * sizeof(GLushort), /* stride */
2263 b->backimage->data); /* dest buffer */
2264 }
2265 else if (xmesa->xm_visual->dithered_pf==PF_DITHER
2266 && GET_VISUAL_DEPTH(xmesa->xm_visual)==8) {
2267 /* Special case: 8bpp RGB */
2268 for (y=0;y<b->height;y++) {
2269 GLubyte *ptr = (GLubyte*) xmesa->xm_buffer->backimage->data
2270 + xmesa->xm_buffer->backimage->bytes_per_line * y;
2271 XDITHER_SETUP(y);
2272
2273 /* read row from 3Dfx frame buffer */
2274 grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2275 0, xmesa->xm_buffer->FXctx->height-(b->height-y),
2276 b->width, 1,
2277 0,
2278 pixbuf );
2279
2280 /* write to XImage back buffer */
2281 for (x=0;x<b->width;x++) {
2282 GLubyte r = (pixbuf[x] & 0xf800) >> 8;
2283 GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
2284 GLubyte b = (pixbuf[x] & 0x001f) << 3;
2285 *ptr++ = XDITHER( x, r, g, b);
2286 }
2287 }
2288 }
2289 else {
2290 /* General case: slow! */
2291 for (y=0;y<b->height;y++) {
2292 /* read row from 3Dfx frame buffer */
2293 grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2294 0, xmesa->xm_buffer->FXctx->height-(b->height-y),
2295 b->width, 1,
2296 0,
2297 pixbuf );
2298
2299 /* write to XImage back buffer */
2300 for (x=0;x<b->width;x++) {
2301 XMesaPutPixel(b->backimage,x,y,
2302 xmesa_color_to_pixel(xmesa,
2303 (pixbuf[x] & 0xf800) >> 8,
2304 (pixbuf[x] & 0x07e0) >> 3,
2305 (pixbuf[x] & 0x001f) << 3,
2306 0xff, xmesa->pixelformat));
2307 }
2308 }
2309 }
2310 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR);
2311 }
2312 #endif
2313
2314
2315 /*
2316 * Copy the back buffer to the front buffer. If there's no back buffer
2317 * this is a no-op.
2318 */
2319 void XMesaSwapBuffers( XMesaBuffer b )
2320 {
2321 GET_CURRENT_CONTEXT(ctx);
2322
2323 /* If we're swapping the buffer associated with the current context
2324 * we have to flush any pending rendering commands first.
2325 */
2326 if (b->xm_context && b->xm_context->gl_ctx == ctx)
2327 _mesa_swapbuffers(ctx);
2328
2329 if (b->db_state) {
2330 #ifdef FX
2331 if (b->FXctx) {
2332 fxMesaSwapBuffers();
2333
2334 if (b->FXwindowHack)
2335 FXgetImage(b);
2336 else
2337 return;
2338 }
2339 #endif
2340 if (b->backimage) {
2341 /* Copy Ximage from host's memory to server's window */
2342 #if defined(USE_XSHM) && !defined(XFree86Server)
2343 if (b->shm) {
2344 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2345 XShmPutImage( b->xm_visual->display, b->frontbuffer,
2346 b->cleargc,
2347 b->backimage, 0, 0,
2348 0, 0, b->width, b->height, False );
2349 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2350 }
2351 else
2352 #endif
2353 {
2354 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
2355 XMesaDriSwapBuffers( b );
2356 #else
2357 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2358 XMesaPutImage( b->xm_visual->display, b->frontbuffer,
2359 b->cleargc,
2360 b->backimage, 0, 0,
2361 0, 0, b->width, b->height );
2362 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2363 #endif
2364 }
2365 }
2366 else {
2367 /* Copy pixmap to window on server */
2368 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2369 XMesaCopyArea( b->xm_visual->display,
2370 b->backpixmap, /* source drawable */
2371 b->frontbuffer, /* dest. drawable */
2372 b->cleargc,
2373 0, 0, b->width, b->height, /* source region */
2374 0, 0 /* dest region */
2375 );
2376 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2377 }
2378 }
2379 #if !defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
2380 XSync( b->xm_visual->display, False );
2381 #endif
2382 }
2383
2384
2385
2386 /*
2387 * Copy sub-region of back buffer to front buffer
2388 */
2389 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2390 {
2391 GET_CURRENT_CONTEXT(ctx);
2392
2393 /* If we're swapping the buffer associated with the current context
2394 * we have to flush any pending rendering commands first.
2395 */
2396 if (b->xm_context->gl_ctx == ctx)
2397 _mesa_swapbuffers(ctx);
2398
2399 if (b->db_state) {
2400 int yTop = b->height - y - height;
2401 #ifdef FX
2402 if (b->FXctx) {
2403 fxMesaSwapBuffers();
2404 if (b->FXwindowHack)
2405 FXgetImage(b);
2406 else
2407 return;
2408 }
2409 #endif
2410 if (b->backimage) {
2411 /* Copy Ximage from host's memory to server's window */
2412 #if defined(USE_XSHM) && !defined(XFree86Server)
2413 if (b->shm) {
2414 /* XXX assuming width and height aren't too large! */
2415 XShmPutImage( b->xm_visual->display, b->frontbuffer,
2416 b->cleargc,
2417 b->backimage, x, yTop,
2418 x, yTop, width, height, False );
2419 /* wait for finished event??? */
2420 }
2421 else
2422 #endif
2423 {
2424 /* XXX assuming width and height aren't too large! */
2425 XMesaPutImage( b->xm_visual->display, b->frontbuffer,
2426 b->cleargc,
2427 b->backimage, x, yTop,
2428 x, yTop, width, height );
2429 }
2430 }
2431 else {
2432 /* Copy pixmap to window on server */
2433 XMesaCopyArea( b->xm_visual->display,
2434 b->backpixmap, /* source drawable */
2435 b->frontbuffer, /* dest. drawable */
2436 b->cleargc,
2437 x, yTop, width, height, /* source region */
2438 x, yTop /* dest region */
2439 );
2440 }
2441 }
2442 }
2443
2444
2445 /*
2446 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
2447 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2448 * back buffer directly.
2449 * Output: pixmap - pointer to back buffer's Pixmap, or 0
2450 * ximage - pointer to back buffer's XImage, or NULL
2451 * Return: GL_TRUE = context is double buffered
2452 * GL_FALSE = context is single buffered
2453 */
2454 GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2455 XMesaPixmap *pixmap,
2456 XMesaImage **ximage )
2457 {
2458 if (b->db_state) {
2459 if (pixmap) *pixmap = b->backpixmap;
2460 if (ximage) *ximage = b->backimage;
2461 return GL_TRUE;
2462 }
2463 else {
2464 *pixmap = 0;
2465 *ximage = NULL;
2466 return GL_FALSE;
2467 }
2468 }
2469
2470
2471 /*
2472 * Return the depth buffer associated with an XMesaBuffer.
2473 * Input: b - the XMesa buffer handle
2474 * Output: width, height - size of buffer in pixels
2475 * bytesPerValue - bytes per depth value (2 or 4)
2476 * buffer - pointer to depth buffer values
2477 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
2478 */
2479 GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2480 GLint *bytesPerValue, void **buffer )
2481 {
2482 if (!b->mesa_buffer.DepthBuffer) {
2483 *width = 0;
2484 *height = 0;
2485 *bytesPerValue = 0;
2486 *buffer = 0;
2487 return GL_FALSE;
2488 }
2489 else {
2490 *width = b->mesa_buffer.Width;
2491 *height = b->mesa_buffer.Height;
2492 *bytesPerValue = sizeof(GLdepth);
2493 *buffer = b->mesa_buffer.DepthBuffer;
2494 return GL_TRUE;
2495 }
2496 }
2497
2498
2499 void XMesaFlush( XMesaContext c )
2500 {
2501 if (c && c->xm_visual) {
2502 #ifdef XFree86Server
2503 /* NOT_NEEDED */
2504 #else
2505 XSync( c->xm_visual->display, False );
2506 #endif
2507 }
2508 }
2509
2510
2511
2512 const char *XMesaGetString( XMesaContext c, int name )
2513 {
2514 (void) c;
2515 if (name==XMESA_VERSION) {
2516 return "3.1";
2517 }
2518 else if (name==XMESA_EXTENSIONS) {
2519 return "";
2520 }
2521 else {
2522 return NULL;
2523 }
2524 }
2525
2526
2527
2528 XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2529 {
2530 XMesaBuffer b;
2531 for (b=XMesaBufferList; b; b=b->Next) {
2532 if (b->frontbuffer==d && b->display==dpy) {
2533 return b;
2534 }
2535 }
2536 return NULL;
2537 }
2538
2539
2540
2541 /*
2542 * Look for XMesaBuffers whose X window has been destroyed.
2543 * Deallocate any such XMesaBuffers.
2544 */
2545 void XMesaGarbageCollect( void )
2546 {
2547 XMesaBuffer b, next;
2548 for (b=XMesaBufferList; b; b=next) {
2549 next = b->Next;
2550 if (!b->pixmap_flag) {
2551 #ifdef XFree86Server
2552 /* NOT_NEEDED */
2553 #else
2554 XSync(b->display, False);
2555 if (!window_exists( b->display, b->frontbuffer )) {
2556 /* found a dead window, free the ancillary info */
2557 XMesaDestroyBuffer( b );
2558 }
2559 #endif
2560 }
2561 }
2562 }
2563
2564
2565 void XMesaReset( void )
2566 {
2567 while (XMesaBufferList)
2568 XMesaDestroyBuffer(XMesaBufferList);
2569
2570 XMesaBufferList = NULL;
2571 }
2572
2573
2574 unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2575 GLfloat red, GLfloat green,
2576 GLfloat blue, GLfloat alpha )
2577 {
2578 GLint r = (GLint) (red * 255.0F);
2579 GLint g = (GLint) (green * 255.0F);
2580 GLint b = (GLint) (blue * 255.0F);
2581 GLint a = (GLint) (alpha * 255.0F);
2582
2583 switch (xmesa->pixelformat) {
2584 case PF_INDEX:
2585 return 0;
2586 case PF_TRUECOLOR:
2587 {
2588 unsigned long p;
2589 PACK_TRUECOLOR( p, r, g, b );
2590 return p;
2591 }
2592 case PF_8A8B8G8R:
2593 return PACK_8A8B8G8R( r, g, b, a );
2594 case PF_8R8G8B:
2595 return PACK_8R8G8B( r, g, b );
2596 case PF_5R6G5B:
2597 return PACK_5R6G5B( r, g, b );
2598 case PF_DITHER:
2599 {
2600 DITHER_SETUP;
2601 return DITHER( x, y, r, g, b );
2602 }
2603 case PF_1BIT:
2604 /* 382 = (3*255)/2 */
2605 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2606 case PF_HPCR:
2607 return DITHER_HPCR(x, y, r, g, b);
2608 case PF_LOOKUP:
2609 {
2610 LOOKUP_SETUP;
2611 return LOOKUP( r, g, b );
2612 }
2613 case PF_GRAYSCALE:
2614 return GRAY_RGB( r, g, b );
2615 case PF_DITHER_5R6G5B:
2616 /* fall through */
2617 case PF_TRUEDITHER:
2618 {
2619 unsigned long p;
2620 PACK_TRUEDITHER(p, x, y, r, g, b);
2621 return p;
2622 }
2623 default:
2624 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2625 }
2626 return 0;
2627 }
2628
2629