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