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