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