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