1 /* $Id: xm_api.c,v 1.21 2001/04/27 21:18:25 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * This file contains the implementations of all the XMesa* functions.
34 * The window coordinate system origin (0,0) is in the lower-left corner
35 * of the window. X11's window coordinate origin is in the upper-left
36 * corner of the window. Therefore, most drawing functions in this
37 * file have to flip Y coordinates.
39 * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
40 * in support for the MIT Shared Memory extension. If enabled, when you
41 * use an Ximage for the back buffer in double buffered mode, the "swap"
42 * operation will be faster. You must also link with -lXext.
44 * Byte swapping: If the Mesa host and the X display use a different
45 * byte order then there's some trickiness to be aware of when using
46 * XImages. The byte ordering used for the XImage is that of the X
47 * display, not the Mesa host.
48 * The color-to-pixel encoding for True/DirectColor must be done
49 * according to the display's visual red_mask, green_mask, and blue_mask.
50 * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
51 * do byte swapping if needed. If one wants to directly "poke" the pixel
52 * into the XImage's buffer then the pixel must be byte swapped first. In
53 * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
54 * and use XPutPixel everywhere except in the implementation of
55 * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so
56 * instead of using XPutPixel we "poke" our values after byte-swapping
57 * the clear pixel value if needed.
66 #include "glxheader.h"
70 #include "extensions.h"
80 #include "swrast/swrast.h"
81 #include "swrast_setup/swrast_setup.h"
82 #include "array_cache/acache.h"
86 #define GLX_NONE_EXT 0x8000
91 * Global X driver lock
93 _glthread_Mutex _xmesa_lock
;
98 * Lookup tables for HPCR pixel format:
100 static short hpcr_rgbTbl
[3][256] = {
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
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
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
159 /**********************************************************************/
160 /***** X Utility Functions *****/
161 /**********************************************************************/
165 * X/Mesa error reporting function:
167 static void error( const char *msg
)
169 if (getenv("MESA_DEBUG"))
170 fprintf( stderr
, "X/Mesa error: %s\n", msg
);
175 * Return the host's byte order as LSBFirst or MSBFirst ala X.
177 #ifndef XFree86Server
178 static int host_byte_order( void )
181 char *cptr
= (char *) &i
;
182 return (*cptr
==1) ? LSBFirst
: MSBFirst
;
190 #ifndef XFree86Server
191 static int mesaXErrorFlag
= 0;
193 static int mesaHandleXError( XMesaDisplay
*dpy
, XErrorEvent
*event
)
204 * Check if the X Shared Memory extension is available.
205 * Return: 0 = not available
206 * 1 = shared XImage support available
207 * 2 = shared Pixmap support available also
209 #ifndef XFree86Server
210 static int check_for_xshm( XMesaDisplay
*display
)
213 int major
, minor
, ignore
;
216 if (XQueryExtension( display
, "MIT-SHM", &ignore
, &ignore
, &ignore
)) {
217 if (XShmQueryVersion( display
, &major
, &minor
, &pixmaps
)==True
) {
218 return (pixmaps
==True
) ? 2 : 1;
228 /* Can't compile XSHM support */
236 * Return the width and height of the given drawable.
238 static void get_drawable_size( XMesaDisplay
*dpy
, XMesaDrawable d
,
239 unsigned int *width
, unsigned int *height
)
248 unsigned int bw
, depth
;
250 _glthread_LOCK_MUTEX(_xmesa_lock
);
251 XGetGeometry( dpy
, d
, &root
, &x
, &y
, width
, height
, &bw
, &depth
);
252 _glthread_UNLOCK_MUTEX(_xmesa_lock
);
258 * Apply gamma correction to an intensity value in [0..max]. Return the
259 * new intensity value.
261 static GLint
gamma_adjust( GLfloat gamma
, GLint value
, GLint max
)
267 double x
= (double) value
/ (double) max
;
268 return IROUND_POS((GLfloat
) max
* pow(x
, 1.0F
/gamma
));
275 * Return the true number of bits per pixel for XImages.
276 * For example, if we request a 24-bit deep visual we may actually need/get
277 * 32bpp XImages. This function returns the appropriate bpp.
278 * Input: dpy - the X display
279 * visinfo - desribes the visual to be used for XImages
280 * Return: true number of bits per pixel for XImages
282 #define GET_BITS_PER_PIXEL(xmv) bits_per_pixel(xmv)
286 static int bits_per_pixel( XMesaVisual xmv
)
288 XMesaVisualInfo visinfo
= xmv
->visinfo
;
289 const int depth
= visinfo
->nplanes
;
291 for (i
= 0; i
< screenInfo
.numPixmapFormats
; i
++) {
292 if (screenInfo
.formats
[i
].depth
== depth
)
293 return screenInfo
.formats
[i
].bitsPerPixel
;
295 return depth
; /* should never get here, but this should be safe */
300 static int bits_per_pixel( XMesaVisual xmv
)
302 XMesaDisplay
*dpy
= xmv
->display
;
303 XMesaVisualInfo visinfo
= xmv
->visinfo
;
306 /* Create a temporary XImage */
307 img
= XCreateImage( dpy
, visinfo
->visual
, visinfo
->depth
,
308 ZPixmap
, 0, /*format, offset*/
309 (char*) MALLOC(8), /*data*/
310 1, 1, /*width, height*/
315 /* grab the bits/pixel value */
316 bitsPerPixel
= img
->bits_per_pixel
;
317 /* free the XImage */
320 XMesaDestroyImage( img
);
328 * Determine if a given X window ID is valid (window exists).
329 * Do this by calling XGetWindowAttributes() for the window and
330 * checking if we catch an X error.
331 * Input: dpy - the display
332 * win - the window to check for existance
333 * Return: GL_TRUE - window exists
334 * GL_FALSE - window doesn't exist
336 #ifndef XFree86Server
337 static GLboolean WindowExistsFlag
;
339 static int window_exists_err_handler( XMesaDisplay
* dpy
, XErrorEvent
* xerr
)
342 if (xerr
->error_code
== BadWindow
) {
343 WindowExistsFlag
= GL_FALSE
;
348 static GLboolean
window_exists( XMesaDisplay
*dpy
, Window win
)
350 XWindowAttributes wa
;
351 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
352 WindowExistsFlag
= GL_TRUE
;
353 old_handler
= XSetErrorHandler(window_exists_err_handler
);
354 XGetWindowAttributes( dpy
, win
, &wa
); /* dummy request */
355 XSetErrorHandler(old_handler
);
356 return WindowExistsFlag
;
362 /**********************************************************************/
363 /***** Linked list of XMesaBuffers *****/
364 /**********************************************************************/
366 static XMesaBuffer XMesaBufferList
= NULL
;
369 /* Allocate a new XMesaBuffer, add to linked list */
370 static XMesaBuffer
alloc_xmesa_buffer(void)
372 XMesaBuffer b
= (XMesaBuffer
) CALLOC_STRUCT(xmesa_buffer
);
374 b
->Next
= XMesaBufferList
;
382 * Find an XMesaBuffer by matching X display and colormap but NOT matching
383 * the notThis buffer.
385 static XMesaBuffer
find_xmesa_buffer(XMesaDisplay
*dpy
,
390 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
391 if (b
->display
==dpy
&& b
->cmap
==cmap
&& b
!=notThis
) {
400 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
403 static void free_xmesa_buffer(int client
, XMesaBuffer buffer
)
405 XMesaBuffer prev
= NULL
, b
;
407 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
409 /* unlink bufer from list */
411 prev
->Next
= buffer
->Next
;
413 XMesaBufferList
= buffer
->Next
;
414 /* Check to free X colors */
415 if (buffer
->num_alloced
>0) {
416 /* If no other buffer uses this X colormap then free the colors. */
417 if (!find_xmesa_buffer(buffer
->display
, buffer
->cmap
, buffer
)) {
419 (void)FreeColors(buffer
->cmap
, client
,
420 buffer
->num_alloced
, buffer
->alloced_colors
,
423 XFreeColors(buffer
->display
, buffer
->cmap
,
424 buffer
->alloced_colors
, buffer
->num_alloced
, 0);
429 _mesa_free_framebuffer_data(&buffer
->mesa_buffer
);
434 /* continue search */
437 /* buffer not found in XMesaBufferList */
438 _mesa_problem(NULL
,"free_xmesa_buffer() - buffer not found\n");
442 /* Copy X color table stuff from one XMesaBuffer to another. */
443 static void copy_colortable_info(XMesaBuffer dst
, const XMesaBuffer src
)
445 MEMCPY(dst
->color_table
, src
->color_table
, sizeof(src
->color_table
));
446 MEMCPY(dst
->pixel_to_r
, src
->pixel_to_r
, sizeof(src
->pixel_to_r
));
447 MEMCPY(dst
->pixel_to_g
, src
->pixel_to_g
, sizeof(src
->pixel_to_g
));
448 MEMCPY(dst
->pixel_to_b
, src
->pixel_to_b
, sizeof(src
->pixel_to_b
));
449 dst
->num_alloced
= src
->num_alloced
;
450 MEMCPY(dst
->alloced_colors
, src
->alloced_colors
,
451 sizeof(src
->alloced_colors
));
456 /**********************************************************************/
457 /***** Misc Private Functions *****/
458 /**********************************************************************/
462 * Return number of bits set in n.
464 static int bitcount( unsigned long n
)
467 for (bits
=0; n
>0; n
=n
>>1) {
478 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
479 * Return: GL_TRUE if success, GL_FALSE if error
481 #ifndef XFree86Server
482 static GLboolean
alloc_shm_back_buffer( XMesaBuffer b
)
486 * We have to do a _lot_ of error checking here to be sure we can
487 * really use the XSHM extension. It seems different servers trigger
488 * errors at different points if the extension won't work. Therefore
489 * we have to be very careful...
492 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
494 b
->backimage
= XShmCreateImage( b
->xm_visual
->display
,
495 b
->xm_visual
->visinfo
->visual
,
496 b
->xm_visual
->visinfo
->depth
,
497 ZPixmap
, NULL
, &b
->shminfo
,
498 b
->width
, b
->height
);
499 if (b
->backimage
== NULL
) {
500 error("alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
505 b
->shminfo
.shmid
= shmget( IPC_PRIVATE
, b
->backimage
->bytes_per_line
506 * b
->backimage
->height
, IPC_CREAT
|0777 );
507 if (b
->shminfo
.shmid
< 0) {
508 if (getenv("MESA_DEBUG"))
509 perror("alloc_back_buffer");
510 XDestroyImage( b
->backimage
);
512 error("alloc_back_buffer: Shared memory error (shmget), disabling.");
517 b
->shminfo
.shmaddr
= b
->backimage
->data
518 = (char*)shmat( b
->shminfo
.shmid
, 0, 0 );
519 if (b
->shminfo
.shmaddr
== (char *) -1) {
520 if (getenv("MESA_DEBUG"))
521 perror("alloc_back_buffer");
522 XDestroyImage( b
->backimage
);
523 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
525 error("alloc_back_buffer: Shared memory error (shmat), disabling.");
530 b
->shminfo
.readOnly
= False
;
532 old_handler
= XSetErrorHandler( mesaHandleXError
);
533 /* This may trigger the X protocol error we're ready to catch: */
534 XShmAttach( b
->xm_visual
->display
, &b
->shminfo
);
535 XSync( b
->xm_visual
->display
, False
);
537 if (mesaXErrorFlag
) {
538 /* we are on a remote display, this error is normal, don't print it */
539 XFlush( b
->xm_visual
->display
);
541 XDestroyImage( b
->backimage
);
542 shmdt( b
->shminfo
.shmaddr
);
543 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
546 (void) XSetErrorHandler( old_handler
);
550 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 ); /* nobody else needs it */
552 /* Finally, try an XShmPutImage to be really sure the extension works */
553 gc
= XCreateGC( b
->xm_visual
->display
, b
->frontbuffer
, 0, NULL
);
554 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
, gc
,
555 b
->backimage
, 0, 0, 0, 0, 1, 1 /*one pixel*/, False
);
556 XSync( b
->xm_visual
->display
, False
);
557 XFreeGC( b
->xm_visual
->display
, gc
);
558 (void) XSetErrorHandler( old_handler
);
559 if (mesaXErrorFlag
) {
560 XFlush( b
->xm_visual
->display
);
562 XDestroyImage( b
->backimage
);
563 shmdt( b
->shminfo
.shmaddr
);
564 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
571 int height
= b
->backimage
->height
;
572 /* Needed by PIXELADDR1 macro */
573 b
->ximage_width1
= b
->backimage
->bytes_per_line
;
574 b
->ximage_origin1
= (GLubyte
*) b
->backimage
->data
575 + b
->ximage_width1
* (height
-1);
576 /* Needed by PIXELADDR2 macro */
577 b
->ximage_width2
= b
->backimage
->bytes_per_line
/ 2;
578 b
->ximage_origin2
= (GLushort
*) b
->backimage
->data
579 + b
->ximage_width2
* (height
-1);
580 /* Needed by PIXELADDR3 macro */
581 b
->ximage_width3
= b
->backimage
->bytes_per_line
;
582 b
->ximage_origin3
= (GLubyte
*) b
->backimage
->data
583 + b
->ximage_width3
* (height
-1);
584 /* Needed by PIXELADDR4 macro */
585 b
->ximage_width4
= b
->backimage
->width
;
586 b
->ximage_origin4
= (GLuint
*) b
->backimage
->data
587 + b
->ximage_width4
* (height
-1);
592 /* Can't compile XSHM support */
601 * Setup an off-screen pixmap or Ximage to use as the back buffer.
602 * Input: b - the X/Mesa buffer
604 void xmesa_alloc_back_buffer( XMesaBuffer b
)
606 if (b
->db_state
==BACK_XIMAGE
) {
607 /* Deallocate the old backimage, if any */
609 #if defined(USE_XSHM) && !defined(XFree86Server)
611 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
612 XDestroyImage( b
->backimage
);
613 shmdt( b
->shminfo
.shmaddr
);
617 XMesaDestroyImage( b
->backimage
);
621 /* Allocate new back buffer */
624 /* Allocate a regular XImage for the back buffer. */
625 b
->backimage
= XMesaCreateImage(b
->xm_visual
->BitsPerPixel
,
626 b
->width
, b
->height
, NULL
);
629 || alloc_shm_back_buffer(b
)==GL_FALSE
631 /* Allocate a regular XImage for the back buffer. */
632 b
->backimage
= XCreateImage( b
->xm_visual
->display
,
633 b
->xm_visual
->visinfo
->visual
,
634 GET_VISUAL_DEPTH(b
->xm_visual
),
635 ZPixmap
, 0, /* format, offset */
636 NULL
, b
->width
, b
->height
,
637 8, 0 ); /* pad, bytes_per_line */
640 error("alloc_back_buffer: XCreateImage failed.");
642 b
->backimage
->data
= (char *) MALLOC( b
->backimage
->height
643 * b
->backimage
->bytes_per_line
);
644 if (!b
->backimage
->data
) {
645 error("alloc_back_buffer: MALLOC failed.");
646 XMesaDestroyImage( b
->backimage
);
650 b
->backpixmap
= None
;
652 else if (b
->db_state
==BACK_PIXMAP
) {
653 XMesaPixmap old_pixmap
= b
->backpixmap
;
654 /* Free the old back pixmap */
656 XMesaFreePixmap( b
->xm_visual
->display
, b
->backpixmap
);
658 /* Allocate new back pixmap */
659 b
->backpixmap
= XMesaCreatePixmap( b
->xm_visual
->display
, b
->frontbuffer
,
661 GET_VISUAL_DEPTH(b
->xm_visual
) );
663 /* update other references to backpixmap */
664 if (b
->buffer
==(XMesaDrawable
)old_pixmap
) {
665 b
->buffer
= (XMesaDrawable
)b
->backpixmap
;
673 * A replacement for XAllocColor. This function should never
674 * fail to allocate a color. When XAllocColor fails, we return
675 * the nearest matching color. If we have to allocate many colors
676 * this function isn't too efficient; the XQueryColors() could be
678 * Written by Michael Pichler, Brian Paul, Mark Kilgard
679 * Input: dpy - X display
681 * cmapSize - size of colormap
682 * In/Out: color - the XColor struct
683 * Output: exact - 1=exact color match, 0=closest match
684 * alloced - 1=XAlloc worked, 0=XAlloc failed
687 noFaultXAllocColor( int client
,
692 int *exact
, int *alloced
)
698 /* we'll try to cache ctable for better remote display performance */
699 static Display
*prevDisplay
= NULL
;
700 static XMesaColormap prevCmap
= 0;
701 static int prevCmapSize
= 0;
702 static XMesaColor
*ctable
= NULL
;
706 double mindist
; /* 3*2^16^2 exceeds long int precision. */
710 /* First try just using XAllocColor. */
713 &color
->red
, &color
->green
, &color
->blue
,
715 client
) == Success
) {
717 if (XAllocColor(dpy
, cmap
, color
)) {
724 /* Alloc failed, search for closest match */
726 /* Retrieve color table entries. */
727 /* XXX alloca candidate. */
729 ppixIn
= (Pixel
*) MALLOC(cmapSize
* sizeof(Pixel
));
730 ctable
= (xrgb
*) MALLOC(cmapSize
* sizeof(xrgb
));
731 for (i
= 0; i
< cmapSize
; i
++) {
734 QueryColors(cmap
, cmapSize
, ppixIn
, ctable
);
736 if (prevDisplay
!= dpy
|| prevCmap
!= cmap
737 || prevCmapSize
!= cmapSize
|| !ctable
) {
738 /* free previously cached color table */
741 /* Get the color table from X */
742 ctable
= (XMesaColor
*) MALLOC(cmapSize
* sizeof(XMesaColor
));
744 for (i
= 0; i
< cmapSize
; i
++) {
747 XQueryColors(dpy
, cmap
, ctable
, cmapSize
);
750 prevCmapSize
= cmapSize
;
754 /* Find best match. */
757 for (i
= 0; i
< cmapSize
; i
++) {
758 double dr
= 0.30 * ((double) color
->red
- (double) ctable
[i
].red
);
759 double dg
= 0.59 * ((double) color
->green
- (double) ctable
[i
].green
);
760 double db
= 0.11 * ((double) color
->blue
- (double) ctable
[i
].blue
);
761 double dist
= dr
* dr
+ dg
* dg
+ db
* db
;
762 if (bestmatch
< 0 || dist
< mindist
) {
769 subColor
.red
= ctable
[bestmatch
].red
;
770 subColor
.green
= ctable
[bestmatch
].green
;
771 subColor
.blue
= ctable
[bestmatch
].blue
;
772 /* Try to allocate the closest match color. This should only
773 * fail if the cell is read/write. Otherwise, we're incrementing
774 * the cell's reference count.
778 &subColor
.red
, &subColor
.green
, &subColor
.blue
,
780 client
) == Success
) {
782 if (XAllocColor(dpy
, cmap
, &subColor
)) {
787 /* do this to work around a problem reported by Frank Ortega */
788 subColor
.pixel
= (unsigned long) bestmatch
;
789 subColor
.red
= ctable
[bestmatch
].red
;
790 subColor
.green
= ctable
[bestmatch
].green
;
791 subColor
.blue
= ctable
[bestmatch
].blue
;
792 subColor
.flags
= DoRed
| DoGreen
| DoBlue
;
799 /* don't free table, save it for next time */
810 * Do setup for PF_GRAYSCALE pixel format.
811 * Note that buffer may be NULL.
813 static GLboolean
setup_grayscale( int client
, XMesaVisual v
,
814 XMesaBuffer buffer
, XMesaColormap cmap
)
816 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
821 XMesaBuffer prevBuffer
;
827 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
829 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
830 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
831 /* Copy colormap stuff from previous XMesaBuffer which uses same
832 * X colormap. Do this to avoid time spent in noFaultXAllocColor.
834 copy_colortable_info(buffer
, prevBuffer
);
837 /* Allocate 256 shades of gray */
839 int colorsfailed
= 0;
840 for (gray
=0;gray
<256;gray
++) {
841 GLint r
= gamma_adjust( v
->RedGamma
, gray
, 255 );
842 GLint g
= gamma_adjust( v
->GreenGamma
, gray
, 255 );
843 GLint b
= gamma_adjust( v
->BlueGamma
, gray
, 255 );
846 xcol
.red
= (r
<< 8) | r
;
847 xcol
.green
= (g
<< 8) | g
;
848 xcol
.blue
= (b
<< 8) | b
;
849 noFaultXAllocColor( client
, v
->display
,
850 cmap
, GET_COLORMAP_SIZE(v
),
851 &xcol
, &exact
, &alloced
);
856 assert(buffer
->num_alloced
<256);
857 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
858 buffer
->num_alloced
++;
863 buffer->color_table[gray*3+0] = xcol.pixel;
864 buffer->color_table[gray*3+1] = xcol.pixel;
865 buffer->color_table[gray*3+2] = xcol.pixel;
866 assert(xcol.pixel < 65536);
867 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
868 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
869 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
871 buffer
->color_table
[gray
] = xcol
.pixel
;
872 assert(xcol
.pixel
< 65536);
873 buffer
->pixel_to_r
[xcol
.pixel
] = gray
;
874 buffer
->pixel_to_g
[xcol
.pixel
] = gray
;
875 buffer
->pixel_to_b
[xcol
.pixel
] = gray
;
878 if (colorsfailed
&& getenv("MESA_DEBUG")) {
880 "Note: %d out of 256 needed colors do not match exactly.\n",
886 v
->dithered_pf
= PF_GRAYSCALE
;
887 v
->undithered_pf
= PF_GRAYSCALE
;
894 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
895 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
896 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
897 * color. While this function was originally designed just for 8-bit
898 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
899 * Dithering code contributed by Bob Mercier.
901 static GLboolean
setup_dithered_color( int client
, XMesaVisual v
,
902 XMesaBuffer buffer
, XMesaColormap cmap
)
904 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
909 XMesaBuffer prevBuffer
;
915 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
917 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
918 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
919 /* Copy colormap stuff from previous, matching XMesaBuffer.
920 * Do this to avoid time spent in noFaultXAllocColor.
922 copy_colortable_info(buffer
, prevBuffer
);
925 /* Allocate X colors and initialize color_table[], red_table[], etc */
927 int colorsfailed
= 0;
928 for (r
= 0; r
< _R
; r
++) {
929 for (g
= 0; g
< _G
; g
++) {
930 for (b
= 0; b
< _B
; b
++) {
933 xcol
.red
=gamma_adjust(v
->RedGamma
, r
*65535/(_R
-1),65535);
934 xcol
.green
=gamma_adjust(v
->GreenGamma
, g
*65535/(_G
-1),65535);
935 xcol
.blue
=gamma_adjust(v
->BlueGamma
, b
*65535/(_B
-1),65535);
936 noFaultXAllocColor( client
, v
->display
,
937 cmap
, GET_COLORMAP_SIZE(v
),
938 &xcol
, &exact
, &alloced
);
943 assert(buffer
->num_alloced
<256);
944 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
945 buffer
->num_alloced
++;
949 buffer
->color_table
[i
] = xcol
.pixel
;
950 assert(xcol
.pixel
< 65536);
951 buffer
->pixel_to_r
[xcol
.pixel
] = r
* 255 / (_R
-1);
952 buffer
->pixel_to_g
[xcol
.pixel
] = g
* 255 / (_G
-1);
953 buffer
->pixel_to_b
[xcol
.pixel
] = b
* 255 / (_B
-1);
958 if (colorsfailed
&& getenv("MESA_DEBUG")) {
960 "Note: %d out of %d needed colors do not match exactly.\n",
961 colorsfailed
, _R
*_G
*_B
);
966 v
->dithered_pf
= PF_DITHER
;
967 v
->undithered_pf
= PF_LOOKUP
;
973 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
974 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
975 * Special dithering tables have to be initialized.
977 static void setup_8bit_hpcr( XMesaVisual v
)
979 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be)
980 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
981 * on the root window AND the colormap obtainable by XGetRGBColormaps
982 * for that atom must be set on the window. (see also tkInitWindow)
983 * If that colormap is not set, the output will look stripy.
986 /* Setup color tables with gamma correction */
990 g
= 1.0 / v
->RedGamma
;
991 for (i
=0; i
<256; i
++) {
992 GLint red
= IROUND_POS(255.0 * pow( hpcr_rgbTbl
[0][i
]/255.0, g
));
993 v
->hpcr_rgbTbl
[0][i
] = CLAMP( red
, 16, 239 );
996 g
= 1.0 / v
->GreenGamma
;
997 for (i
=0; i
<256; i
++) {
998 GLint green
= IROUND_POS(255.0 * pow( hpcr_rgbTbl
[1][i
]/255.0, g
));
999 v
->hpcr_rgbTbl
[1][i
] = CLAMP( green
, 16, 239 );
1002 g
= 1.0 / v
->BlueGamma
;
1003 for (i
=0; i
<256; i
++) {
1004 GLint blue
= IROUND_POS(255.0 * pow( hpcr_rgbTbl
[2][i
]/255.0, g
));
1005 v
->hpcr_rgbTbl
[2][i
] = CLAMP( blue
, 32, 223 );
1007 v
->undithered_pf
= PF_HPCR
; /* can't really disable dithering for now */
1008 v
->dithered_pf
= PF_HPCR
;
1010 /* which method should I use to clear */
1011 /* GL_FALSE: keep the ordinary method */
1012 /* GL_TRUE : clear with dither pattern */
1013 v
->hpcr_clear_flag
= getenv("MESA_HPCR_CLEAR") ? GL_TRUE
: GL_FALSE
;
1015 if (v
->hpcr_clear_flag
) {
1016 v
->hpcr_clear_pixmap
= XMesaCreatePixmap(v
->display
,
1017 DefaultRootWindow(v
->display
),
1019 #ifndef XFree86Server
1020 v
->hpcr_clear_ximage
= XGetImage(v
->display
, v
->hpcr_clear_pixmap
,
1021 0, 0, 16, 2, AllPlanes
, ZPixmap
);
1028 * Setup RGB rendering for a window with a True/DirectColor visual.
1030 static void setup_truecolor( XMesaVisual v
, XMesaBuffer buffer
,
1031 XMesaWindow window
, XMesaColormap cmap
)
1033 unsigned long rmask
, gmask
, bmask
;
1038 /* Compute red multiplier (mask) and bit shift */
1040 rmask
= GET_REDMASK(v
);
1041 while ((rmask
& 1)==0) {
1046 /* Compute green multiplier (mask) and bit shift */
1048 gmask
= GET_GREENMASK(v
);
1049 while ((gmask
& 1)==0) {
1054 /* Compute blue multiplier (mask) and bit shift */
1056 bmask
= GET_BLUEMASK(v
);
1057 while ((bmask
& 1)==0) {
1063 * Compute component-to-pixel lookup tables and dithering kernel
1066 static GLubyte kernel
[16] = {
1067 0*16, 8*16, 2*16, 10*16,
1068 12*16, 4*16, 14*16, 6*16,
1069 3*16, 11*16, 1*16, 9*16,
1070 15*16, 7*16, 13*16, 5*16,
1072 GLint rBits
= bitcount(rmask
);
1073 GLint gBits
= bitcount(gmask
);
1074 GLint bBits
= bitcount(bmask
);
1078 /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1079 for (i
=0; i
<=rmask
; i
++)
1080 v
->PixelToR
[i
] = (unsigned char) ((i
* 255) / rmask
);
1081 for (i
=0; i
<=gmask
; i
++)
1082 v
->PixelToG
[i
] = (unsigned char) ((i
* 255) / gmask
);
1083 for (i
=0; i
<=bmask
; i
++)
1084 v
->PixelToB
[i
] = (unsigned char) ((i
* 255) / bmask
);
1086 /* convert RGB values from [0,255] to pixel components */
1088 for (i
=0;i
<256;i
++) {
1089 GLint r
= gamma_adjust(v
->RedGamma
, i
, 255);
1090 GLint g
= gamma_adjust(v
->GreenGamma
, i
, 255);
1091 GLint b
= gamma_adjust(v
->BlueGamma
, i
, 255);
1092 v
->RtoPixel
[i
] = (r
>> (8-rBits
)) << v
->rshift
;
1093 v
->GtoPixel
[i
] = (g
>> (8-gBits
)) << v
->gshift
;
1094 v
->BtoPixel
[i
] = (b
>> (8-bBits
)) << v
->bshift
;
1096 /* overflow protection */
1097 for (i
=256;i
<512;i
++) {
1098 v
->RtoPixel
[i
] = v
->RtoPixel
[255];
1099 v
->GtoPixel
[i
] = v
->GtoPixel
[255];
1100 v
->BtoPixel
[i
] = v
->BtoPixel
[255];
1103 /* setup dithering kernel */
1105 if (gBits
> maxBits
) maxBits
= gBits
;
1106 if (bBits
> maxBits
) maxBits
= bBits
;
1107 for (i
=0;i
<16;i
++) {
1108 v
->Kernel
[i
] = kernel
[i
] >> maxBits
;
1111 v
->undithered_pf
= PF_TRUECOLOR
;
1112 v
->dithered_pf
= (GET_VISUAL_DEPTH(v
)<24) ? PF_TRUEDITHER
: PF_TRUECOLOR
;
1116 * Now check for TrueColor visuals which we can optimize.
1118 if ( GET_REDMASK(v
) ==0x0000ff
1119 && GET_GREENMASK(v
)==0x00ff00
1120 && GET_BLUEMASK(v
) ==0xff0000
1121 && CHECK_BYTE_ORDER(v
)
1122 && v
->BitsPerPixel
==32
1123 && sizeof(GLuint
)==4
1124 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1125 /* common 32 bpp config used on SGI, Sun */
1126 v
->undithered_pf
= v
->dithered_pf
= PF_8A8B8G8R
;
1128 else if (GET_REDMASK(v
) ==0xff0000
1129 && GET_GREENMASK(v
)==0x00ff00
1130 && GET_BLUEMASK(v
) ==0x0000ff
1131 && CHECK_BYTE_ORDER(v
)
1132 && v
->BitsPerPixel
==32
1133 && sizeof(GLuint
)==4
1134 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1135 /* common 32 bpp config used on Linux, HP, IBM */
1136 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B
;
1138 else if (GET_REDMASK(v
) ==0xff0000
1139 && GET_GREENMASK(v
)==0x00ff00
1140 && GET_BLUEMASK(v
) ==0x0000ff
1141 && CHECK_BYTE_ORDER(v
)
1142 && v
->BitsPerPixel
==24
1143 && sizeof(GLuint
)==4
1144 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1145 /* common packed 24 bpp config used on Linux */
1146 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B24
;
1148 else if (GET_REDMASK(v
) ==0xf800
1149 && GET_GREENMASK(v
)==0x07e0
1150 && GET_BLUEMASK(v
) ==0x001f
1151 && CHECK_BYTE_ORDER(v
)
1152 && v
->BitsPerPixel
==16
1153 && sizeof(GLushort
)==2
1154 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1155 /* 5-6-5 color weight on common PC VGA boards */
1156 v
->undithered_pf
= PF_5R6G5B
;
1157 v
->dithered_pf
= PF_DITHER_5R6G5B
;
1159 else if (GET_REDMASK(v
) ==0xe0
1160 && GET_GREENMASK(v
)==0x1c
1161 && GET_BLUEMASK(v
) ==0x03
1162 && CHECK_FOR_HPCR(v
)) {
1163 setup_8bit_hpcr( v
);
1170 * Setup RGB rendering for a window with a monochrome visual.
1172 static void setup_monochrome( XMesaVisual v
, XMesaBuffer b
)
1175 v
->dithered_pf
= v
->undithered_pf
= PF_1BIT
;
1176 /* if black=1 then we must flip pixel values */
1177 v
->bitFlip
= (GET_BLACK_PIXEL(v
) != 0);
1183 * When a context is "made current" for the first time, we can finally
1184 * finish initializing the context's visual and buffer information.
1185 * Input: v - the XMesaVisual to initialize
1186 * b - the XMesaBuffer to initialize (may be NULL)
1187 * rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1188 * window - the window/pixmap we're rendering into
1189 * cmap - the colormap associated with the window/pixmap
1190 * Return: GL_TRUE=success, GL_FALSE=failure
1192 static GLboolean
initialize_visual_and_buffer( int client
,
1196 XMesaDrawable window
,
1200 #ifndef XFree86Server
1205 assert(b
->xm_visual
== v
);
1208 /* Save true bits/pixel */
1209 v
->BitsPerPixel
= GET_BITS_PER_PIXEL(v
);
1210 assert(v
->BitsPerPixel
> 0);
1213 if (rgb_flag
==GL_FALSE
) {
1214 /* COLOR-INDEXED WINDOW:
1215 * Even if the visual is TrueColor or DirectColor we treat it as
1216 * being color indexed. This is weird but might be useful to someone.
1218 v
->dithered_pf
= v
->undithered_pf
= PF_INDEX
;
1219 v
->index_bits
= GET_VISUAL_DEPTH(v
);
1223 * We support RGB rendering into almost any kind of visual.
1226 xclass
= GET_VISUAL_CLASS(v
);
1227 if (xclass
==TrueColor
|| xclass
==DirectColor
) {
1228 setup_truecolor( v
, b
, (XMesaWindow
)window
, cmap
);
1230 else if (xclass
==StaticGray
&& GET_VISUAL_DEPTH(v
)==1) {
1231 setup_monochrome( v
, b
);
1233 else if (xclass
==GrayScale
|| xclass
==StaticGray
) {
1234 if (!setup_grayscale( client
, v
, b
, cmap
)) {
1238 else if ((xclass
==PseudoColor
|| xclass
==StaticColor
)
1239 && GET_VISUAL_DEPTH(v
)>=4 && GET_VISUAL_DEPTH(v
)<=16) {
1240 if (!setup_dithered_color( client
, v
, b
, cmap
)) {
1245 error("XMesa: RGB mode rendering not supported in given visual.");
1250 if (getenv("MESA_NO_DITHER")) {
1251 v
->dithered_pf
= v
->undithered_pf
;
1257 * If MESA_INFO env var is set print out some debugging info
1258 * which can help Brian figure out what's going on when a user
1261 if (getenv("MESA_INFO")) {
1262 fprintf(stderr
, "X/Mesa visual = %p\n", v
);
1263 fprintf(stderr
, "X/Mesa dithered pf = %u\n", v
->dithered_pf
);
1264 fprintf(stderr
, "X/Mesa undithered pf = %u\n", v
->undithered_pf
);
1265 fprintf(stderr
, "X/Mesa level = %d\n", v
->level
);
1266 fprintf(stderr
, "X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v
));
1267 fprintf(stderr
, "X/Mesa bits per pixel = %d\n", v
->BitsPerPixel
);
1271 /* Do window-specific initializations */
1273 /* Window dimensions */
1275 get_drawable_size( v
->display
, window
, &w
, &h
);
1279 b
->frontbuffer
= window
;
1281 /* Setup for single/double buffering */
1282 if (v
->mesa_visual
.doubleBufferMode
) {
1283 /* Double buffered */
1284 #ifndef XFree86Server
1285 b
->shm
= check_for_xshm( v
->display
);
1287 xmesa_alloc_back_buffer( b
);
1288 if (b
->db_state
==BACK_PIXMAP
) {
1289 b
->buffer
= (XMesaDrawable
)b
->backpixmap
;
1296 /* Single Buffered */
1297 b
->buffer
= b
->frontbuffer
;
1300 /* X11 graphics contexts */
1301 #ifdef XFree86Server
1302 b
->gc
= CreateScratchGC(v
->display
, window
->depth
);
1304 b
->gc
= XCreateGC( v
->display
, window
, 0, NULL
);
1306 XMesaSetFunction( v
->display
, b
->gc
, GXcopy
);
1309 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1310 * Patch contributed by Michael Pichler May 15, 1995.
1312 #ifdef XFree86Server
1313 b
->cleargc
= CreateScratchGC(v
->display
, window
->depth
);
1317 dixChangeGC(NullClient
, b
->cleargc
, GCGraphicsExposures
, v
, NULL
);
1320 gcvalues
.graphics_exposures
= False
;
1321 b
->cleargc
= XCreateGC( v
->display
, window
,
1322 GCGraphicsExposures
, &gcvalues
);
1324 XMesaSetFunction( v
->display
, b
->cleargc
, GXcopy
);
1326 * Set fill style and tile pixmap once for all for HPCR stuff
1327 * (instead of doing it each time in clear_color_HPCR_pixmap())
1328 * Initialize whole stuff
1329 * Patch contributed by Jacques Leroy March 8, 1998.
1331 if (v
->hpcr_clear_flag
&& b
->buffer
!=XIMAGE
) {
1333 for (i
=0; i
<16; i
++)
1335 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 0, 0);
1336 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 1, 0);
1338 XMesaPutImage(b
->display
, (XMesaDrawable
)v
->hpcr_clear_pixmap
,
1339 b
->cleargc
, v
->hpcr_clear_ximage
, 0, 0, 0, 0, 16, 2);
1340 XMesaSetFillStyle( v
->display
, b
->cleargc
, FillTiled
);
1341 XMesaSetTile( v
->display
, b
->cleargc
, v
->hpcr_clear_pixmap
);
1344 /* Initialize the row buffer XImage for use in write_color_span() */
1345 #ifdef XFree86Server
1346 b
->rowimage
= XMesaCreateImage(GET_VISUAL_DEPTH(v
), MAX_WIDTH
, 1,
1347 (char *)MALLOC(MAX_WIDTH
*4));
1349 b
->rowimage
= XCreateImage( v
->display
,
1352 ZPixmap
, 0, /*format, offset*/
1353 (char*) MALLOC(MAX_WIDTH
*4), /*data*/
1354 MAX_WIDTH
, 1, /*width, height*/
1356 0 /*bytes_per_line*/ );
1366 * Convert an RGBA color to a pixel value.
1369 xmesa_color_to_pixel( XMesaContext xmesa
, GLubyte r
, GLubyte g
, GLubyte b
, GLubyte a
,
1372 switch (pixelFormat
) {
1378 PACK_TRUECOLOR( p
, r
, g
, b
);
1382 return PACK_8A8B8G8R( r
, g
, b
, a
);
1386 return PACK_8R8G8B( r
, g
, b
);
1388 return PACK_5R6G5B( r
, g
, b
);
1392 return DITHER( 1, 0, r
, g
, b
);
1395 /* 382 = (3*255)/2 */
1396 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
1398 return DITHER_HPCR(1, 1, r
, g
, b
);
1402 return LOOKUP( r
, g
, b
);
1405 return GRAY_RGB( r
, g
, b
);
1408 case PF_DITHER_5R6G5B
:
1411 PACK_TRUEDITHER(p
, 1, 0, r
, g
, b
);
1415 _mesa_problem(NULL
, "Bad pixel format in xmesa_color_to_pixel");
1421 /**********************************************************************/
1422 /***** Public Functions *****/
1423 /**********************************************************************/
1427 * Create a new X/Mesa visual.
1428 * Input: display - X11 display
1429 * visinfo - an XVisualInfo pointer
1430 * rgb_flag - GL_TRUE = RGB mode,
1431 * GL_FALSE = color index mode
1432 * alpha_flag - alpha buffer requested?
1433 * db_flag - GL_TRUE = double-buffered,
1434 * GL_FALSE = single buffered
1435 * stereo_flag - stereo visual?
1436 * ximage_flag - GL_TRUE = use an XImage for back buffer,
1437 * GL_FALSE = use an off-screen pixmap for back buffer
1438 * depth_size - requested bits/depth values, or zero
1439 * stencil_size - requested bits/stencil values, or zero
1440 * accum_red_size - requested bits/red accum values, or zero
1441 * accum_green_size - requested bits/green accum values, or zero
1442 * accum_blue_size - requested bits/blue accum values, or zero
1443 * accum_alpha_size - requested bits/alpha accum values, or zero
1444 * num_samples - number of samples/pixel if multisampling, or zero
1445 * level - visual level, usually 0
1446 * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT
1447 * Return; a new XMesaVisual or 0 if error.
1449 XMesaVisual
XMesaCreateVisual( XMesaDisplay
*display
,
1450 XMesaVisualInfo visinfo
,
1452 GLboolean alpha_flag
,
1454 GLboolean stereo_flag
,
1455 GLboolean ximage_flag
,
1458 GLint accum_red_size
,
1459 GLint accum_green_size
,
1460 GLint accum_blue_size
,
1461 GLint accum_alpha_size
,
1464 GLint visualCaveat
)
1468 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1470 /* For debugging only */
1471 if (getenv("MESA_XSYNC")) {
1472 /* This makes debugging X easier.
1473 * In your debugger, set a breakpoint on _XError to stop when an
1474 * X protocol error is generated.
1476 #ifdef XFree86Server
1479 XSynchronize( display
, 1 );
1483 v
= (XMesaVisual
) CALLOC_STRUCT(xmesa_visual
);
1489 * In the X server, NULL is passed in for the display. It will have
1490 * to be set before using this visual. See XMesaSetVisualDisplay()
1493 v
->display
= display
;
1495 /* Save a copy of the XVisualInfo struct because the user may XFREE()
1496 * the struct but we may need some of the information contained in it
1499 #ifdef XFree86Server
1500 v
->visinfo
= visinfo
;
1502 v
->visinfo
= (XVisualInfo
*) MALLOC(sizeof(*visinfo
));
1507 MEMCPY(v
->visinfo
, visinfo
, sizeof(*visinfo
));
1509 /* Save a copy of the pointer now so we can find this visual again
1510 * if we need to search for it in find_glx_visual().
1512 v
->vishandle
= visinfo
;
1515 #ifdef XFree86Server
1516 /* Initialize the depth of the screen */
1518 PixmapFormatRec
*format
;
1520 for (format
= screenInfo
.formats
;
1521 format
->depth
!= display
->rootDepth
;
1524 v
->screen_depth
= format
->bitsPerPixel
;
1528 /* check for MESA_GAMMA environment variable */
1529 gamma
= getenv("MESA_GAMMA");
1531 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 0.0;
1532 sscanf( gamma
, "%f %f %f", &v
->RedGamma
, &v
->GreenGamma
, &v
->BlueGamma
);
1533 if (v
->RedGamma
<=0.0) v
->RedGamma
= 1.0;
1534 if (v
->GreenGamma
<=0.0) v
->GreenGamma
= v
->RedGamma
;
1535 if (v
->BlueGamma
<=0.0) v
->BlueGamma
= v
->RedGamma
;
1538 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 1.0;
1541 v
->ximage_flag
= ximage_flag
;
1543 v
->VisualCaveat
= visualCaveat
;
1545 (void) initialize_visual_and_buffer( 0, v
, NULL
, rgb_flag
, 0, 0 );
1549 xclass
= GET_VISUAL_CLASS(v
);
1550 if (xclass
==TrueColor
|| xclass
==DirectColor
) {
1551 red_bits
= bitcount(GET_REDMASK(v
));
1552 green_bits
= bitcount(GET_GREENMASK(v
));
1553 blue_bits
= bitcount(GET_BLUEMASK(v
));
1557 /* this is an approximation */
1559 depth
= GET_VISUAL_DEPTH(v
);
1560 red_bits
= depth
/ 3;
1562 green_bits
= depth
/ 2;
1563 depth
-= green_bits
;
1566 assert( red_bits
+ green_bits
+ blue_bits
== GET_VISUAL_DEPTH(v
) );
1570 if (alpha_flag
&& alpha_bits
== 0)
1573 _mesa_initialize_visual( &v
->mesa_visual
,
1574 rgb_flag
, db_flag
, stereo_flag
,
1575 red_bits
, green_bits
,
1576 blue_bits
, alpha_bits
,
1580 accum_red_size
, accum_green_size
,
1581 accum_blue_size
, accum_alpha_size
,
1587 void XMesaSetVisualDisplay( XMesaDisplay
*dpy
, XMesaVisual v
)
1593 void XMesaDestroyVisual( XMesaVisual v
)
1595 #ifndef XFree86Server
1604 * Create a new XMesaContext.
1605 * Input: v - XMesaVisual
1606 * share_list - another XMesaContext with which to share display
1607 * lists or NULL if no sharing is wanted.
1608 * Return: an XMesaContext or NULL if error.
1610 XMesaContext
XMesaCreateContext( XMesaVisual v
, XMesaContext share_list
)
1614 GLboolean direct
= GL_TRUE
; /* XXXX */
1615 /* NOT_DONE: should this be GL_FALSE??? */
1616 static GLboolean firstTime
= GL_TRUE
;
1619 _glthread_INIT_MUTEX(_xmesa_lock
);
1620 firstTime
= GL_FALSE
;
1623 c
= (XMesaContext
) CALLOC_STRUCT(xmesa_context
);
1628 ctx
= c
->gl_ctx
= _mesa_create_context( &v
->mesa_visual
,
1629 share_list
? share_list
->gl_ctx
: (GLcontext
*) NULL
,
1630 (void *) c
, direct
);
1636 _mesa_enable_sw_extensions(ctx
);
1638 if (CHECK_BYTE_ORDER(v
)) {
1639 c
->swapbytes
= GL_FALSE
;
1642 c
->swapbytes
= GL_TRUE
;
1646 c
->xm_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1647 c
->display
= v
->display
;
1648 c
->pixelformat
= v
->dithered_pf
; /* Dithering is enabled by default */
1650 ctx
->Driver
.UpdateState
= xmesa_update_state
;
1652 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1653 c
->driContextPriv
= driContextPriv
;
1656 /* Initialize the software rasterizer and helper modules.
1658 _swrast_CreateContext( ctx
);
1659 _ac_CreateContext( ctx
);
1660 _tnl_CreateContext( ctx
);
1661 _swsetup_CreateContext( ctx
);
1663 xmesa_register_swrast_functions( ctx
);
1665 /* Set up some constant pointers:
1667 xmesa_init_pointers( ctx
);
1670 /* Run the config file
1672 _mesa_context_initialize( ctx
);
1681 void XMesaDestroyContext( XMesaContext c
)
1684 if (c
->xm_buffer
&& c
->xm_buffer
->FXctx
)
1685 fxMesaDestroyContext(c
->xm_buffer
->FXctx
);
1688 _swsetup_DestroyContext( c
->gl_ctx
);
1689 _swrast_DestroyContext( c
->gl_ctx
);
1690 _tnl_DestroyContext( c
->gl_ctx
);
1691 _ac_DestroyContext( c
->gl_ctx
);
1692 _mesa_destroy_context( c
->gl_ctx
);
1695 /* Disassociate old buffer with this context */
1697 c
->xm_buffer
->xm_context
= NULL
;
1699 /* Destroy any buffers which are using this context. If we don't
1700 * we may have dangling references. Hmm, maybe we should just
1701 * set the buffer's context pointer to NULL instead of deleting it?
1702 * Let's see if we get any bug reports...
1703 * This contributed by Doug Rabson <dfr@calcaphon.com>
1706 XMesaBuffer b
, next
;
1707 for (b
= XMesaBufferList
; b
; b
= next
) {
1709 if (!b
->pixmap_flag
) {
1710 #ifndef XFree86Server
1711 XSync(b
->display
, False
);
1713 if (b
->xm_context
== c
) {
1714 /* found a context created for this context */
1715 XMesaDestroyBuffer( b
);
1727 * XXX this isn't a public function! It's a hack for the 3Dfx driver.
1728 * Create a new XMesaBuffer from an X window.
1729 * Input: v - the XMesaVisual
1732 * Return: new XMesaBuffer or NULL if error
1734 XMesaBuffer
XMesaCreateWindowBuffer2( XMesaVisual v
, XMesaWindow w
,
1737 #ifndef XFree86Server
1738 XWindowAttributes attr
;
1745 XMesaBuffer b
= alloc_xmesa_buffer();
1752 #ifdef XFree86Server
1753 client
= CLIENT_ID(((XMesaDrawable
)w
)->id
);
1758 #ifdef XFree86Server
1759 if (GET_VISUAL_DEPTH(v
) != ((XMesaDrawable
)w
)->depth
) {
1761 XGetWindowAttributes( v
->display
, w
, &attr
);
1763 if (GET_VISUAL_DEPTH(v
) != attr
.depth
) {
1765 if (getenv("MESA_DEBUG")) {
1766 fprintf(stderr
, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n");
1771 b
->xm_context
= NULL
; /* Associate no context with this buffer */
1774 b
->pixmap_flag
= GL_FALSE
;
1775 b
->display
= v
->display
;
1776 #ifdef XFree86Server
1777 b
->cmap
= (ColormapPtr
)LookupIDByType(wColormap(w
), RT_COLORMAP
);
1779 if (attr
.colormap
) {
1780 b
->cmap
= attr
.colormap
;
1783 if (getenv("MESA_DEBUG")) {
1784 fprintf(stderr
, "Window %u has no colormap!\n", (unsigned int) w
);
1786 /* this is weird, a window w/out a colormap!? */
1787 /* OK, let's just allocate a new one and hope for the best */
1788 b
->cmap
= XCreateColormap(v
->display
, w
, attr
.visual
, AllocNone
);
1792 /* determine back buffer implementation */
1793 if (v
->mesa_visual
.doubleBufferMode
) {
1794 if (v
->ximage_flag
) {
1795 b
->db_state
= BACK_XIMAGE
;
1798 b
->db_state
= BACK_PIXMAP
;
1805 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
1807 v
->mesa_visual
.depthBits
> 0,
1808 v
->mesa_visual
.stencilBits
> 0,
1809 v
->mesa_visual
.accumRedBits
> 0,
1810 v
->mesa_visual
.alphaBits
> 0 );
1812 if (!initialize_visual_and_buffer( client
, v
, b
, v
->mesa_visual
.rgbMode
,
1813 (XMesaDrawable
)w
, b
->cmap
)) {
1814 free_xmesa_buffer(client
, b
);
1819 fxEnvVar
= getenv("MESA_GLX_FX");
1821 if (fxEnvVar
[0]!='d') {
1825 if (v
->mesa_visual
.depthBits
> 0) {
1826 attribs
[numAttribs
++] = FXMESA_DEPTH_SIZE
;
1827 attribs
[numAttribs
++] = 1;
1829 if (v
->mesa_visual
.doubleBufferMode
) {
1830 attribs
[numAttribs
++] = FXMESA_DOUBLEBUFFER
;
1832 if (v
->mesa_visual
.accumRedBits
> 0) {
1833 attribs
[numAttribs
++] = FXMESA_ACCUM_SIZE
;
1834 attribs
[numAttribs
++] = v
->mesa_visual
.accumRedBits
;
1836 if (v
->mesa_visual
.stencilBits
> 0) {
1837 attribs
[numAttribs
++] = FXMESA_STENCIL_SIZE
;
1838 attribs
[numAttribs
++] = v
->mesa_visual
.stencilBits
;
1840 if (v
->mesa_visual
.alphaBits
> 0) {
1841 attribs
[numAttribs
++] = FXMESA_ALPHA_SIZE
;
1842 attribs
[numAttribs
++] = 1;
1845 #define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with fxapi.c! */
1846 attribs
[numAttribs
++] = FXMESA_SHARE_CONTEXT
;
1847 attribs
[numAttribs
++] = (int) c
->gl_ctx
;
1849 attribs
[numAttribs
++] = FXMESA_NONE
;
1851 if ((hw
= fxQueryHardware())==GR_SSTTYPE_VOODOO
) {
1852 b
->FXctx
= fxMesaCreateBestContext(0, b
->width
, b
->height
, attribs
);
1853 if ((v
->undithered_pf
!=PF_INDEX
) && (b
->backimage
)) {
1854 b
->FXisHackUsable
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1855 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1856 b
->FXwindowHack
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1858 b
->FXwindowHack
= GL_FALSE
;
1862 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1863 b
->FXctx
= fxMesaCreateContext(w
, GR_RESOLUTION_NONE
,
1864 GR_REFRESH_75Hz
, attribs
);
1866 b
->FXctx
= fxMesaCreateBestContext(0, b
->width
, b
->height
, attribs
);
1867 b
->FXisHackUsable
= GL_FALSE
;
1868 b
->FXwindowHack
= GL_FALSE
;
1872 "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1873 hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
1878 fprintf(stderr
,"WARNING: This Mesa Library includes the Glide driver but\n");
1879 fprintf(stderr
," you have not defined the MESA_GLX_FX env. var.\n");
1880 fprintf(stderr
," (check the README.3DFX file for more information).\n\n");
1881 fprintf(stderr
," you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1885 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1886 b
->driDrawPriv
= driDrawPriv
;
1893 XMesaBuffer
XMesaCreateWindowBuffer( XMesaVisual v
, XMesaWindow w
)
1895 return XMesaCreateWindowBuffer2( v
, w
, NULL
);
1900 * Create a new XMesaBuffer from an X pixmap.
1901 * Input: v - the XMesaVisual
1903 * cmap - the colormap, may be 0 if using a TrueColor or DirectColor
1904 * visual for the pixmap
1905 * Return: new XMesaBuffer or NULL if error
1907 XMesaBuffer
XMesaCreatePixmapBuffer( XMesaVisual v
,
1908 XMesaPixmap p
, XMesaColormap cmap
)
1911 XMesaBuffer b
= alloc_xmesa_buffer();
1917 #ifdef XFree86Server
1918 client
= CLIENT_ID(((XMesaDrawable
)p
)->id
);
1923 b
->xm_context
= NULL
; /* Associate no context with this buffer */
1926 b
->pixmap_flag
= GL_TRUE
;
1927 b
->display
= v
->display
;
1930 /* determine back buffer implementation */
1931 if (v
->mesa_visual
.doubleBufferMode
) {
1932 if (v
->ximage_flag
) {
1933 b
->db_state
= BACK_XIMAGE
;
1936 b
->db_state
= BACK_PIXMAP
;
1943 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
1945 v
->mesa_visual
.depthBits
> 0,
1946 v
->mesa_visual
.stencilBits
> 0,
1947 v
->mesa_visual
.accumRedBits
+
1948 v
->mesa_visual
.accumGreenBits
+
1949 v
->mesa_visual
.accumBlueBits
> 0,
1950 v
->mesa_visual
.alphaBits
> 0 );
1952 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1953 (XMesaDrawable
)p
, cmap
)) {
1954 free_xmesa_buffer(client
, b
);
1958 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1959 b
->driDrawPriv
= driDrawPriv
;
1968 * Deallocate an XMesaBuffer structure and all related info.
1970 void XMesaDestroyBuffer( XMesaBuffer b
)
1974 #ifdef XFree86Server
1976 client
= CLIENT_ID(b
->frontbuffer
->id
);
1979 if (b
->gc
) XMesaFreeGC( b
->xm_visual
->display
, b
->gc
);
1980 if (b
->cleargc
) XMesaFreeGC( b
->xm_visual
->display
, b
->cleargc
);
1983 #if defined(USE_XSHM) && !defined(XFree86Server)
1985 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
1986 XDestroyImage( b
->backimage
);
1987 shmdt( b
->shminfo
.shmaddr
);
1991 XMesaDestroyImage( b
->backimage
);
1993 if (b
->backpixmap
) {
1994 XMesaFreePixmap( b
->xm_visual
->display
, b
->backpixmap
);
1995 if (b
->xm_visual
->hpcr_clear_flag
) {
1996 XMesaFreePixmap( b
->xm_visual
->display
,
1997 b
->xm_visual
->hpcr_clear_pixmap
);
1998 XMesaDestroyImage( b
->xm_visual
->hpcr_clear_ximage
);
2002 FREE( b
->rowimage
->data
);
2003 b
->rowimage
->data
= NULL
;
2004 XMesaDestroyImage( b
->rowimage
);
2008 b
->xm_context
->xm_buffer
= NULL
;
2010 free_xmesa_buffer(client
, b
);
2016 * Bind buffer b to context c and make c the current rendering context.
2018 GLboolean
XMesaMakeCurrent( XMesaContext c
, XMesaBuffer b
)
2020 return XMesaMakeCurrent2( c
, b
, b
);
2025 * Bind buffer b to context c and make c the current rendering context.
2027 GLboolean
XMesaMakeCurrent2( XMesaContext c
, XMesaBuffer drawBuffer
,
2028 XMesaBuffer readBuffer
)
2031 if (!drawBuffer
|| !readBuffer
)
2032 return GL_FALSE
; /* must specify buffers! */
2035 if (drawBuffer
->FXctx
) {
2036 fxMesaMakeCurrent(drawBuffer
->FXctx
);
2038 /* Disassociate old buffer from this context */
2040 c
->xm_buffer
->xm_context
= NULL
;
2042 /* Associate the context with this buffer */
2043 drawBuffer
->xm_context
= c
;
2045 c
->xm_buffer
= drawBuffer
;
2046 c
->xm_read_buffer
= readBuffer
;
2047 c
->use_read_buffer
= (drawBuffer
!= readBuffer
);
2052 if (c
->gl_ctx
== _mesa_get_current_context()
2053 && c
->xm_buffer
== drawBuffer
2054 && c
->xm_read_buffer
== readBuffer
2055 && c
->xm_buffer
->wasCurrent
) {
2056 /* same context and buffer, do nothing */
2060 /* Disassociate old buffer with this context */
2062 c
->xm_buffer
->xm_context
= NULL
;
2063 drawBuffer
->xm_context
= c
; /* Associate the context with this buffer */
2065 c
->xm_buffer
= drawBuffer
;
2066 c
->xm_read_buffer
= readBuffer
;
2067 c
->use_read_buffer
= (drawBuffer
!= readBuffer
);
2069 _mesa_make_current2(c
->gl_ctx
,
2070 &drawBuffer
->mesa_buffer
,
2071 &readBuffer
->mesa_buffer
);
2073 if (c
->gl_ctx
->Viewport
.Width
== 0) {
2074 /* initialize viewport to window size */
2075 _mesa_Viewport( 0, 0, drawBuffer
->width
, drawBuffer
->height
);
2076 c
->gl_ctx
->Scissor
.Width
= drawBuffer
->width
;
2077 c
->gl_ctx
->Scissor
.Height
= drawBuffer
->height
;
2080 if (c
->xm_visual
->mesa_visual
.rgbMode
) {
2082 * Must recompute and set these pixel values because colormap
2083 * can be different for different windows.
2085 c
->clearpixel
= xmesa_color_to_pixel( c
,
2090 c
->xm_visual
->undithered_pf
);
2091 XMesaSetForeground(c
->display
, c
->xm_buffer
->cleargc
, c
->clearpixel
);
2094 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2095 c
->xm_buffer
->wasCurrent
= GL_TRUE
;
2099 _mesa_make_current2( NULL
, NULL
, NULL
);
2106 * Unbind the context c from its buffer.
2108 GLboolean
XMesaUnbindContext( XMesaContext c
)
2110 /* A no-op for XFree86 integration purposes */
2115 XMesaContext
XMesaGetCurrentContext( void )
2117 GET_CURRENT_CONTEXT(ctx
);
2119 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2128 XMesaBuffer
XMesaGetCurrentBuffer( void )
2130 GET_CURRENT_CONTEXT(ctx
);
2132 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2133 return xmesa
->xm_buffer
;
2141 /* New in Mesa 3.1 */
2142 XMesaBuffer
XMesaGetCurrentReadBuffer( void )
2144 GET_CURRENT_CONTEXT(ctx
);
2146 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2147 return xmesa
->xm_buffer
;
2155 GLboolean
XMesaForceCurrent(XMesaContext c
)
2158 if (c
->gl_ctx
!= _mesa_get_current_context()) {
2159 _mesa_make_current(c
->gl_ctx
, &c
->xm_buffer
->mesa_buffer
);
2163 _mesa_make_current(NULL
, NULL
);
2169 GLboolean
XMesaLoseCurrent(XMesaContext c
)
2172 _mesa_make_current(NULL
, NULL
);
2178 * Switch 3Dfx support hack between window and full-screen mode.
2180 GLboolean
XMesaSetFXmode( GLint mode
)
2183 const char *fx
= getenv("MESA_GLX_FX");
2184 if (fx
&& fx
[0] != 'd') {
2185 GET_CURRENT_CONTEXT(ctx
);
2186 GrHwConfiguration hw
;
2187 if (!FX_grSstQueryHardware(&hw
)) {
2188 /*fprintf(stderr, "!grSstQueryHardware\n");*/
2191 if (hw
.num_sst
< 1) {
2192 /*fprintf(stderr, "hw.num_sst < 1\n");*/
2196 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2197 if (mode
== XMESA_FX_WINDOW
) {
2198 if (xmesa
->xm_buffer
->FXisHackUsable
) {
2199 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
2200 xmesa
->xm_buffer
->FXwindowHack
= GL_TRUE
;
2204 else if (mode
== XMESA_FX_FULLSCREEN
) {
2205 FX_grSstControl(GR_CONTROL_ACTIVATE
);
2206 xmesa
->xm_buffer
->FXwindowHack
= GL_FALSE
;
2210 /* Error: Bad mode value */
2214 /*fprintf(stderr, "fallthrough\n");*/
2225 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2227 static void FXgetImage( XMesaBuffer b
)
2229 static unsigned short pixbuf
[MAX_WIDTH
];
2233 unsigned int bw
, depth
, width
, height
;
2234 XMesaContext xmesa
= (XMesaContext
) b
->xm_context
->gl_ctx
->DriverCtx
;
2236 assert(xmesa
->xm_buffer
->FXctx
);
2238 #ifdef XFree86Server
2239 x
= b
->frontbuffer
->x
;
2240 y
= b
->frontbuffer
->y
;
2241 width
= b
->frontbuffer
->width
;
2242 height
= b
->frontbuffer
->height
;
2243 depth
= b
->frontbuffer
->depth
;
2245 XGetGeometry( xmesa
->xm_visual
->display
, b
->frontbuffer
,
2246 &root
, &xpos
, &ypos
, &width
, &height
, &bw
, &depth
);
2248 if (b
->width
!= width
|| b
->height
!= height
) {
2249 b
->width
= MIN2((int)width
, xmesa
->xm_buffer
->FXctx
->width
);
2250 b
->height
= MIN2((int)height
, xmesa
->xm_buffer
->FXctx
->height
);
2252 b
->width
--; /* prevent odd width */
2253 xmesa_alloc_back_buffer( b
);
2256 grLfbWriteColorFormat(GR_COLORFORMAT_ARGB
);
2257 if (xmesa
->xm_visual
->undithered_pf
==PF_5R6G5B
) {
2258 /* Special case: 16bpp RGB */
2259 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
, /* src buffer */
2260 0, xmesa
->xm_buffer
->FXctx
->height
- b
->height
, /*pos*/
2261 b
->width
, b
->height
, /* size */
2262 b
->width
* sizeof(GLushort
), /* stride */
2263 b
->backimage
->data
); /* dest buffer */
2265 else if (xmesa
->xm_visual
->dithered_pf
==PF_DITHER
2266 && GET_VISUAL_DEPTH(xmesa
->xm_visual
)==8) {
2267 /* Special case: 8bpp RGB */
2268 for (y
=0;y
<b
->height
;y
++) {
2269 GLubyte
*ptr
= (GLubyte
*) xmesa
->xm_buffer
->backimage
->data
2270 + xmesa
->xm_buffer
->backimage
->bytes_per_line
* y
;
2273 /* read row from 3Dfx frame buffer */
2274 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
,
2275 0, xmesa
->xm_buffer
->FXctx
->height
-(b
->height
-y
),
2280 /* write to XImage back buffer */
2281 for (x
=0;x
<b
->width
;x
++) {
2282 GLubyte r
= (pixbuf
[x
] & 0xf800) >> 8;
2283 GLubyte g
= (pixbuf
[x
] & 0x07e0) >> 3;
2284 GLubyte b
= (pixbuf
[x
] & 0x001f) << 3;
2285 *ptr
++ = XDITHER( x
, r
, g
, b
);
2290 /* General case: slow! */
2291 for (y
=0;y
<b
->height
;y
++) {
2292 /* read row from 3Dfx frame buffer */
2293 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
,
2294 0, xmesa
->xm_buffer
->FXctx
->height
-(b
->height
-y
),
2299 /* write to XImage back buffer */
2300 for (x
=0;x
<b
->width
;x
++) {
2301 XMesaPutPixel(b
->backimage
,x
,y
,
2302 xmesa_color_to_pixel(xmesa
,
2303 (pixbuf
[x
] & 0xf800) >> 8,
2304 (pixbuf
[x
] & 0x07e0) >> 3,
2305 (pixbuf
[x
] & 0x001f) << 3,
2306 0xff, xmesa
->pixelformat
));
2310 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR
);
2316 * Copy the back buffer to the front buffer. If there's no back buffer
2319 void XMesaSwapBuffers( XMesaBuffer b
)
2321 GET_CURRENT_CONTEXT(ctx
);
2323 /* If we're swapping the buffer associated with the current context
2324 * we have to flush any pending rendering commands first.
2326 if (b
->xm_context
&& b
->xm_context
->gl_ctx
== ctx
)
2327 _mesa_swapbuffers(ctx
);
2332 fxMesaSwapBuffers();
2334 if (b
->FXwindowHack
)
2341 /* Copy Ximage from host's memory to server's window */
2342 #if defined(USE_XSHM) && !defined(XFree86Server)
2344 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2345 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2348 0, 0, b
->width
, b
->height
, False
);
2349 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2354 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
2355 XMesaDriSwapBuffers( b
);
2357 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2358 XMesaPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2361 0, 0, b
->width
, b
->height
);
2362 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2367 /* Copy pixmap to window on server */
2368 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2369 XMesaCopyArea( b
->xm_visual
->display
,
2370 b
->backpixmap
, /* source drawable */
2371 b
->frontbuffer
, /* dest. drawable */
2373 0, 0, b
->width
, b
->height
, /* source region */
2374 0, 0 /* dest region */
2376 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2379 #if !defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
2380 XSync( b
->xm_visual
->display
, False
);
2387 * Copy sub-region of back buffer to front buffer
2389 void XMesaCopySubBuffer( XMesaBuffer b
, int x
, int y
, int width
, int height
)
2391 GET_CURRENT_CONTEXT(ctx
);
2393 /* If we're swapping the buffer associated with the current context
2394 * we have to flush any pending rendering commands first.
2396 if (b
->xm_context
->gl_ctx
== ctx
)
2397 _mesa_swapbuffers(ctx
);
2400 int yTop
= b
->height
- y
- height
;
2403 fxMesaSwapBuffers();
2404 if (b
->FXwindowHack
)
2411 /* Copy Ximage from host's memory to server's window */
2412 #if defined(USE_XSHM) && !defined(XFree86Server)
2414 /* XXX assuming width and height aren't too large! */
2415 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2417 b
->backimage
, x
, yTop
,
2418 x
, yTop
, width
, height
, False
);
2419 /* wait for finished event??? */
2424 /* XXX assuming width and height aren't too large! */
2425 XMesaPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2427 b
->backimage
, x
, yTop
,
2428 x
, yTop
, width
, height
);
2432 /* Copy pixmap to window on server */
2433 XMesaCopyArea( b
->xm_visual
->display
,
2434 b
->backpixmap
, /* source drawable */
2435 b
->frontbuffer
, /* dest. drawable */
2437 x
, yTop
, width
, height
, /* source region */
2438 x
, yTop
/* dest region */
2446 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
2447 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2448 * back buffer directly.
2449 * Output: pixmap - pointer to back buffer's Pixmap, or 0
2450 * ximage - pointer to back buffer's XImage, or NULL
2451 * Return: GL_TRUE = context is double buffered
2452 * GL_FALSE = context is single buffered
2454 GLboolean
XMesaGetBackBuffer( XMesaBuffer b
,
2455 XMesaPixmap
*pixmap
,
2456 XMesaImage
**ximage
)
2459 if (pixmap
) *pixmap
= b
->backpixmap
;
2460 if (ximage
) *ximage
= b
->backimage
;
2472 * Return the depth buffer associated with an XMesaBuffer.
2473 * Input: b - the XMesa buffer handle
2474 * Output: width, height - size of buffer in pixels
2475 * bytesPerValue - bytes per depth value (2 or 4)
2476 * buffer - pointer to depth buffer values
2477 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
2479 GLboolean
XMesaGetDepthBuffer( XMesaBuffer b
, GLint
*width
, GLint
*height
,
2480 GLint
*bytesPerValue
, void **buffer
)
2482 if (!b
->mesa_buffer
.DepthBuffer
) {
2490 *width
= b
->mesa_buffer
.Width
;
2491 *height
= b
->mesa_buffer
.Height
;
2492 *bytesPerValue
= sizeof(GLdepth
);
2493 *buffer
= b
->mesa_buffer
.DepthBuffer
;
2499 void XMesaFlush( XMesaContext c
)
2501 if (c
&& c
->xm_visual
) {
2502 #ifdef XFree86Server
2505 XSync( c
->xm_visual
->display
, False
);
2512 const char *XMesaGetString( XMesaContext c
, int name
)
2515 if (name
==XMESA_VERSION
) {
2518 else if (name
==XMESA_EXTENSIONS
) {
2528 XMesaBuffer
XMesaFindBuffer( XMesaDisplay
*dpy
, XMesaDrawable d
)
2531 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
2532 if (b
->frontbuffer
==d
&& b
->display
==dpy
) {
2542 * Look for XMesaBuffers whose X window has been destroyed.
2543 * Deallocate any such XMesaBuffers.
2545 void XMesaGarbageCollect( void )
2547 XMesaBuffer b
, next
;
2548 for (b
=XMesaBufferList
; b
; b
=next
) {
2550 if (!b
->pixmap_flag
) {
2551 #ifdef XFree86Server
2554 XSync(b
->display
, False
);
2555 if (!window_exists( b
->display
, b
->frontbuffer
)) {
2556 /* found a dead window, free the ancillary info */
2557 XMesaDestroyBuffer( b
);
2565 void XMesaReset( void )
2567 while (XMesaBufferList
)
2568 XMesaDestroyBuffer(XMesaBufferList
);
2570 XMesaBufferList
= NULL
;
2574 unsigned long XMesaDitherColor( XMesaContext xmesa
, GLint x
, GLint y
,
2575 GLfloat red
, GLfloat green
,
2576 GLfloat blue
, GLfloat alpha
)
2578 GLint r
= (GLint
) (red
* 255.0F
);
2579 GLint g
= (GLint
) (green
* 255.0F
);
2580 GLint b
= (GLint
) (blue
* 255.0F
);
2581 GLint a
= (GLint
) (alpha
* 255.0F
);
2583 switch (xmesa
->pixelformat
) {
2589 PACK_TRUECOLOR( p
, r
, g
, b
);
2593 return PACK_8A8B8G8R( r
, g
, b
, a
);
2595 return PACK_8R8G8B( r
, g
, b
);
2597 return PACK_5R6G5B( r
, g
, b
);
2601 return DITHER( x
, y
, r
, g
, b
);
2604 /* 382 = (3*255)/2 */
2605 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
2607 return DITHER_HPCR(x
, y
, r
, g
, b
);
2611 return LOOKUP( r
, g
, b
);
2614 return GRAY_RGB( r
, g
, b
);
2615 case PF_DITHER_5R6G5B
:
2620 PACK_TRUEDITHER(p
, x
, y
, r
, g
, b
);
2624 _mesa_problem(NULL
, "Bad pixel format in XMesaDitherColor");