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