1 /* $Id: xm_api.c,v 1.49 2002/10/29 23:53:22 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 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.
26 /* $XFree86: xc/extras/Mesa/src/X/xm_api.c,v 1.2 2002/02/26 23:37:31 tsi Exp $ */
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"
77 #include "texformat.h"
79 #include "swrast/swrast.h"
80 #include "swrast_setup/swrast_setup.h"
81 #include "array_cache/acache.h"
85 #define GLX_NONE_EXT 0x8000
90 * Global X driver lock
92 _glthread_Mutex _xmesa_lock
;
97 * Lookup tables for HPCR pixel format:
99 static short hpcr_rgbTbl
[3][256] = {
101 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
102 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
103 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
104 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
105 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
106 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
107 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
108 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
109 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
110 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
111 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
112 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
113 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
114 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
115 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
116 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
119 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
120 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
121 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
122 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
123 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
124 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
125 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
126 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
127 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
128 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
129 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
130 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
131 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
132 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
133 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
134 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
137 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
138 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
139 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55,
140 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
141 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
142 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79,
143 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87,
144 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
145 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
146 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
147 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
148 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
149 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
150 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
151 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
152 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
158 /**********************************************************************/
159 /***** X Utility Functions *****/
160 /**********************************************************************/
164 * X/Mesa error reporting function:
166 static void error( const char *msg
)
168 (void)DitherValues
; /* Muffle compiler */
170 if (_mesa_getenv("MESA_DEBUG"))
171 fprintf( stderr
, "X/Mesa error: %s\n", msg
);
176 * Return the host's byte order as LSBFirst or MSBFirst ala X.
178 #ifndef XFree86Server
179 static int host_byte_order( void )
182 char *cptr
= (char *) &i
;
183 return (*cptr
==1) ? LSBFirst
: MSBFirst
;
191 #ifndef XFree86Server
192 static int mesaXErrorFlag
= 0;
194 static int mesaHandleXError( XMesaDisplay
*dpy
, XErrorEvent
*event
)
205 * Check if the X Shared Memory extension is available.
206 * Return: 0 = not available
207 * 1 = shared XImage support available
208 * 2 = shared Pixmap support available also
210 #ifndef XFree86Server
211 static int check_for_xshm( XMesaDisplay
*display
)
214 int major
, minor
, ignore
;
217 if (XQueryExtension( display
, "MIT-SHM", &ignore
, &ignore
, &ignore
)) {
218 if (XShmQueryVersion( display
, &major
, &minor
, &pixmaps
)==True
) {
219 return (pixmaps
==True
) ? 2 : 1;
229 /* Can't compile XSHM support */
237 * Return the width and height of the given drawable.
239 static void get_drawable_size( XMesaDisplay
*dpy
, XMesaDrawable d
,
240 unsigned int *width
, unsigned int *height
)
249 unsigned int bw
, depth
;
251 _glthread_LOCK_MUTEX(_xmesa_lock
);
252 XGetGeometry( dpy
, d
, &root
, &x
, &y
, width
, height
, &bw
, &depth
);
253 _glthread_UNLOCK_MUTEX(_xmesa_lock
);
259 * Apply gamma correction to an intensity value in [0..max]. Return the
260 * new intensity value.
262 static GLint
gamma_adjust( GLfloat gamma
, GLint value
, GLint max
)
268 double x
= (double) value
/ (double) max
;
269 return IROUND_POS((GLfloat
) max
* _mesa_pow(x
, 1.0F
/gamma
));
276 * Return the true number of bits per pixel for XImages.
277 * For example, if we request a 24-bit deep visual we may actually need/get
278 * 32bpp XImages. This function returns the appropriate bpp.
279 * Input: dpy - the X display
280 * visinfo - desribes the visual to be used for XImages
281 * Return: true number of bits per pixel for XImages
285 static int bits_per_pixel( XMesaVisual xmv
)
287 XMesaVisualInfo visinfo
= xmv
->visinfo
;
288 const int depth
= visinfo
->nplanes
;
290 for (i
= 0; i
< screenInfo
.numPixmapFormats
; i
++) {
291 if (screenInfo
.formats
[i
].depth
== depth
)
292 return screenInfo
.formats
[i
].bitsPerPixel
;
294 return depth
; /* should never get here, but this should be safe */
299 static int bits_per_pixel( XMesaVisual xmv
)
301 XMesaDisplay
*dpy
= xmv
->display
;
302 XMesaVisualInfo visinfo
= xmv
->visinfo
;
305 /* Create a temporary XImage */
306 img
= XCreateImage( dpy
, visinfo
->visual
, visinfo
->depth
,
307 ZPixmap
, 0, /*format, offset*/
308 (char*) MALLOC(8), /*data*/
309 1, 1, /*width, height*/
314 /* grab the bits/pixel value */
315 bitsPerPixel
= img
->bits_per_pixel
;
316 /* free the XImage */
319 XMesaDestroyImage( img
);
327 * Determine if a given X window ID is valid (window exists).
328 * Do this by calling XGetWindowAttributes() for the window and
329 * checking if we catch an X error.
330 * Input: dpy - the display
331 * win - the window to check for existance
332 * Return: GL_TRUE - window exists
333 * GL_FALSE - window doesn't exist
335 #ifndef XFree86Server
336 static GLboolean WindowExistsFlag
;
338 static int window_exists_err_handler( XMesaDisplay
* dpy
, XErrorEvent
* xerr
)
341 if (xerr
->error_code
== BadWindow
) {
342 WindowExistsFlag
= GL_FALSE
;
347 static GLboolean
window_exists( XMesaDisplay
*dpy
, Window win
)
349 XWindowAttributes wa
;
350 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
351 WindowExistsFlag
= GL_TRUE
;
352 old_handler
= XSetErrorHandler(window_exists_err_handler
);
353 XGetWindowAttributes( dpy
, win
, &wa
); /* dummy request */
354 XSetErrorHandler(old_handler
);
355 return WindowExistsFlag
;
361 /**********************************************************************/
362 /***** Linked list of XMesaBuffers *****/
363 /**********************************************************************/
365 static XMesaBuffer XMesaBufferList
= NULL
;
368 /* Allocate a new XMesaBuffer, add to linked list */
369 static XMesaBuffer
alloc_xmesa_buffer(void)
371 XMesaBuffer b
= (XMesaBuffer
) CALLOC_STRUCT(xmesa_buffer
);
373 b
->Next
= XMesaBufferList
;
381 * Find an XMesaBuffer by matching X display and colormap but NOT matching
382 * the notThis buffer.
384 static XMesaBuffer
find_xmesa_buffer(XMesaDisplay
*dpy
,
389 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
390 if (b
->display
==dpy
&& b
->cmap
==cmap
&& b
!=notThis
) {
399 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
402 static void free_xmesa_buffer(int client
, XMesaBuffer buffer
)
404 XMesaBuffer prev
= NULL
, b
;
406 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
408 /* unlink bufer from list */
410 prev
->Next
= buffer
->Next
;
412 XMesaBufferList
= buffer
->Next
;
413 /* Check to free X colors */
414 if (buffer
->num_alloced
>0) {
415 /* If no other buffer uses this X colormap then free the colors. */
416 if (!find_xmesa_buffer(buffer
->display
, buffer
->cmap
, buffer
)) {
418 (void)FreeColors(buffer
->cmap
, client
,
419 buffer
->num_alloced
, buffer
->alloced_colors
,
422 XFreeColors(buffer
->display
, buffer
->cmap
,
423 buffer
->alloced_colors
, buffer
->num_alloced
, 0);
428 _mesa_free_framebuffer_data(&buffer
->mesa_buffer
);
433 /* continue search */
436 /* buffer not found in XMesaBufferList */
437 _mesa_problem(NULL
,"free_xmesa_buffer() - buffer not found\n");
441 /* Copy X color table stuff from one XMesaBuffer to another. */
442 static void copy_colortable_info(XMesaBuffer dst
, const XMesaBuffer src
)
444 MEMCPY(dst
->color_table
, src
->color_table
, sizeof(src
->color_table
));
445 MEMCPY(dst
->pixel_to_r
, src
->pixel_to_r
, sizeof(src
->pixel_to_r
));
446 MEMCPY(dst
->pixel_to_g
, src
->pixel_to_g
, sizeof(src
->pixel_to_g
));
447 MEMCPY(dst
->pixel_to_b
, src
->pixel_to_b
, sizeof(src
->pixel_to_b
));
448 dst
->num_alloced
= src
->num_alloced
;
449 MEMCPY(dst
->alloced_colors
, src
->alloced_colors
,
450 sizeof(src
->alloced_colors
));
455 /**********************************************************************/
456 /***** Misc Private Functions *****/
457 /**********************************************************************/
461 * Return number of bits set in n.
463 static int bitcount( unsigned long n
)
466 for (bits
=0; n
>0; n
=n
>>1) {
477 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
478 * Return: GL_TRUE if success, GL_FALSE if error
480 #ifndef XFree86Server
481 static GLboolean
alloc_shm_back_buffer( XMesaBuffer b
)
485 * We have to do a _lot_ of error checking here to be sure we can
486 * really use the XSHM extension. It seems different servers trigger
487 * errors at different points if the extension won't work. Therefore
488 * we have to be very careful...
491 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
493 b
->backimage
= XShmCreateImage( b
->xm_visual
->display
,
494 b
->xm_visual
->visinfo
->visual
,
495 b
->xm_visual
->visinfo
->depth
,
496 ZPixmap
, NULL
, &b
->shminfo
,
497 b
->width
, b
->height
);
498 if (b
->backimage
== NULL
) {
499 error("alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
504 b
->shminfo
.shmid
= shmget( IPC_PRIVATE
, b
->backimage
->bytes_per_line
505 * b
->backimage
->height
, IPC_CREAT
|0777 );
506 if (b
->shminfo
.shmid
< 0) {
507 if (_mesa_getenv("MESA_DEBUG"))
508 perror("alloc_back_buffer");
509 XDestroyImage( b
->backimage
);
511 error("alloc_back_buffer: Shared memory error (shmget), disabling.");
516 b
->shminfo
.shmaddr
= b
->backimage
->data
517 = (char*)shmat( b
->shminfo
.shmid
, 0, 0 );
518 if (b
->shminfo
.shmaddr
== (char *) -1) {
519 if (_mesa_getenv("MESA_DEBUG"))
520 perror("alloc_back_buffer");
521 XDestroyImage( b
->backimage
);
522 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
524 error("alloc_back_buffer: Shared memory error (shmat), disabling.");
529 b
->shminfo
.readOnly
= False
;
531 old_handler
= XSetErrorHandler( mesaHandleXError
);
532 /* This may trigger the X protocol error we're ready to catch: */
533 XShmAttach( b
->xm_visual
->display
, &b
->shminfo
);
534 XSync( b
->xm_visual
->display
, False
);
536 if (mesaXErrorFlag
) {
537 /* we are on a remote display, this error is normal, don't print it */
538 XFlush( b
->xm_visual
->display
);
540 XDestroyImage( b
->backimage
);
541 shmdt( b
->shminfo
.shmaddr
);
542 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
545 (void) XSetErrorHandler( old_handler
);
549 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 ); /* nobody else needs it */
551 /* Finally, try an XShmPutImage to be really sure the extension works */
552 gc
= XCreateGC( b
->xm_visual
->display
, b
->frontbuffer
, 0, NULL
);
553 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
, gc
,
554 b
->backimage
, 0, 0, 0, 0, 1, 1 /*one pixel*/, False
);
555 XSync( b
->xm_visual
->display
, False
);
556 XFreeGC( b
->xm_visual
->display
, gc
);
557 (void) XSetErrorHandler( old_handler
);
558 if (mesaXErrorFlag
) {
559 XFlush( b
->xm_visual
->display
);
561 XDestroyImage( b
->backimage
);
562 shmdt( b
->shminfo
.shmaddr
);
563 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
570 int height
= b
->backimage
->height
;
571 /* Needed by PIXELADDR1 macro */
572 b
->ximage_width1
= b
->backimage
->bytes_per_line
;
573 b
->ximage_origin1
= (GLubyte
*) b
->backimage
->data
574 + b
->ximage_width1
* (height
-1);
575 /* Needed by PIXELADDR2 macro */
576 b
->ximage_width2
= b
->backimage
->bytes_per_line
/ 2;
577 b
->ximage_origin2
= (GLushort
*) b
->backimage
->data
578 + b
->ximage_width2
* (height
-1);
579 /* Needed by PIXELADDR3 macro */
580 b
->ximage_width3
= b
->backimage
->bytes_per_line
;
581 b
->ximage_origin3
= (GLubyte
*) b
->backimage
->data
582 + b
->ximage_width3
* (height
-1);
583 /* Needed by PIXELADDR4 macro */
584 b
->ximage_width4
= b
->backimage
->width
;
585 b
->ximage_origin4
= (GLuint
*) b
->backimage
->data
586 + b
->ximage_width4
* (height
-1);
591 /* Can't compile XSHM support */
600 * Setup an off-screen pixmap or Ximage to use as the back buffer.
601 * Input: b - the X/Mesa buffer
603 void xmesa_alloc_back_buffer( XMesaBuffer b
)
605 if (b
->db_state
==BACK_XIMAGE
) {
606 /* Deallocate the old backimage, if any */
608 #if defined(USE_XSHM) && !defined(XFree86Server)
610 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
611 XDestroyImage( b
->backimage
);
612 shmdt( b
->shminfo
.shmaddr
);
616 XMesaDestroyImage( b
->backimage
);
620 /* Allocate new back buffer */
623 /* Allocate a regular XImage for the back buffer. */
624 b
->backimage
= XMesaCreateImage(b
->xm_visual
->BitsPerPixel
,
625 b
->width
, b
->height
, NULL
);
627 if (b
->shm
==0 || alloc_shm_back_buffer(b
)==GL_FALSE
) {
628 /* Allocate a regular XImage for the back buffer. */
629 b
->backimage
= XCreateImage( b
->xm_visual
->display
,
630 b
->xm_visual
->visinfo
->visual
,
631 GET_VISUAL_DEPTH(b
->xm_visual
),
632 ZPixmap
, 0, /* format, offset */
633 NULL
, b
->width
, b
->height
,
634 8, 0 ); /* pad, bytes_per_line */
637 error("alloc_back_buffer: XCreateImage failed.");
639 b
->backimage
->data
= (char *) MALLOC( b
->backimage
->height
640 * b
->backimage
->bytes_per_line
);
641 if (!b
->backimage
->data
) {
642 error("alloc_back_buffer: MALLOC failed.");
643 XMesaDestroyImage( b
->backimage
);
647 b
->backpixmap
= None
;
649 else if (b
->db_state
==BACK_PIXMAP
) {
650 XMesaPixmap old_pixmap
= b
->backpixmap
;
651 /* Free the old back pixmap */
653 XMesaFreePixmap( b
->xm_visual
->display
, b
->backpixmap
);
655 /* Allocate new back pixmap */
656 b
->backpixmap
= XMesaCreatePixmap( b
->xm_visual
->display
, b
->frontbuffer
,
658 GET_VISUAL_DEPTH(b
->xm_visual
) );
660 /* update other references to backpixmap */
661 if (b
->buffer
==(XMesaDrawable
)old_pixmap
) {
662 b
->buffer
= (XMesaDrawable
)b
->backpixmap
;
670 * A replacement for XAllocColor. This function should never
671 * fail to allocate a color. When XAllocColor fails, we return
672 * the nearest matching color. If we have to allocate many colors
673 * this function isn't too efficient; the XQueryColors() could be
675 * Written by Michael Pichler, Brian Paul, Mark Kilgard
676 * Input: dpy - X display
678 * cmapSize - size of colormap
679 * In/Out: color - the XColor struct
680 * Output: exact - 1=exact color match, 0=closest match
681 * alloced - 1=XAlloc worked, 0=XAlloc failed
684 noFaultXAllocColor( int client
,
689 int *exact
, int *alloced
)
695 /* we'll try to cache ctable for better remote display performance */
696 static Display
*prevDisplay
= NULL
;
697 static XMesaColormap prevCmap
= 0;
698 static int prevCmapSize
= 0;
699 static XMesaColor
*ctable
= NULL
;
703 double mindist
; /* 3*2^16^2 exceeds long int precision. */
707 /* First try just using XAllocColor. */
710 &color
->red
, &color
->green
, &color
->blue
,
712 client
) == Success
) {
714 if (XAllocColor(dpy
, cmap
, color
)) {
721 /* Alloc failed, search for closest match */
723 /* Retrieve color table entries. */
724 /* XXX alloca candidate. */
726 ppixIn
= (Pixel
*) MALLOC(cmapSize
* sizeof(Pixel
));
727 ctable
= (xrgb
*) MALLOC(cmapSize
* sizeof(xrgb
));
728 for (i
= 0; i
< cmapSize
; i
++) {
731 QueryColors(cmap
, cmapSize
, ppixIn
, ctable
);
733 if (prevDisplay
!= dpy
|| prevCmap
!= cmap
734 || prevCmapSize
!= cmapSize
|| !ctable
) {
735 /* free previously cached color table */
738 /* Get the color table from X */
739 ctable
= (XMesaColor
*) MALLOC(cmapSize
* sizeof(XMesaColor
));
741 for (i
= 0; i
< cmapSize
; i
++) {
744 XQueryColors(dpy
, cmap
, ctable
, cmapSize
);
747 prevCmapSize
= cmapSize
;
751 /* Find best match. */
754 for (i
= 0; i
< cmapSize
; i
++) {
755 double dr
= 0.30 * ((double) color
->red
- (double) ctable
[i
].red
);
756 double dg
= 0.59 * ((double) color
->green
- (double) ctable
[i
].green
);
757 double db
= 0.11 * ((double) color
->blue
- (double) ctable
[i
].blue
);
758 double dist
= dr
* dr
+ dg
* dg
+ db
* db
;
759 if (bestmatch
< 0 || dist
< mindist
) {
766 subColor
.red
= ctable
[bestmatch
].red
;
767 subColor
.green
= ctable
[bestmatch
].green
;
768 subColor
.blue
= ctable
[bestmatch
].blue
;
769 /* Try to allocate the closest match color. This should only
770 * fail if the cell is read/write. Otherwise, we're incrementing
771 * the cell's reference count.
775 &subColor
.red
, &subColor
.green
, &subColor
.blue
,
777 client
) == Success
) {
779 if (XAllocColor(dpy
, cmap
, &subColor
)) {
784 /* do this to work around a problem reported by Frank Ortega */
785 subColor
.pixel
= (unsigned long) bestmatch
;
786 subColor
.red
= ctable
[bestmatch
].red
;
787 subColor
.green
= ctable
[bestmatch
].green
;
788 subColor
.blue
= ctable
[bestmatch
].blue
;
789 subColor
.flags
= DoRed
| DoGreen
| DoBlue
;
796 /* don't free table, save it for next time */
807 * Do setup for PF_GRAYSCALE pixel format.
808 * Note that buffer may be NULL.
810 static GLboolean
setup_grayscale( int client
, XMesaVisual v
,
811 XMesaBuffer buffer
, XMesaColormap cmap
)
813 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
818 XMesaBuffer prevBuffer
;
824 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
826 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
827 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
828 /* Copy colormap stuff from previous XMesaBuffer which uses same
829 * X colormap. Do this to avoid time spent in noFaultXAllocColor.
831 copy_colortable_info(buffer
, prevBuffer
);
834 /* Allocate 256 shades of gray */
836 int colorsfailed
= 0;
837 for (gray
=0;gray
<256;gray
++) {
838 GLint r
= gamma_adjust( v
->RedGamma
, gray
, 255 );
839 GLint g
= gamma_adjust( v
->GreenGamma
, gray
, 255 );
840 GLint b
= gamma_adjust( v
->BlueGamma
, gray
, 255 );
843 xcol
.red
= (r
<< 8) | r
;
844 xcol
.green
= (g
<< 8) | g
;
845 xcol
.blue
= (b
<< 8) | b
;
846 noFaultXAllocColor( client
, v
->display
,
847 cmap
, GET_COLORMAP_SIZE(v
),
848 &xcol
, &exact
, &alloced
);
853 assert(buffer
->num_alloced
<256);
854 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
855 buffer
->num_alloced
++;
860 buffer->color_table[gray*3+0] = xcol.pixel;
861 buffer->color_table[gray*3+1] = xcol.pixel;
862 buffer->color_table[gray*3+2] = xcol.pixel;
863 assert(xcol.pixel < 65536);
864 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
865 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
866 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
868 buffer
->color_table
[gray
] = xcol
.pixel
;
869 assert(xcol
.pixel
< 65536);
870 buffer
->pixel_to_r
[xcol
.pixel
] = gray
;
871 buffer
->pixel_to_g
[xcol
.pixel
] = gray
;
872 buffer
->pixel_to_b
[xcol
.pixel
] = gray
;
875 if (colorsfailed
&& _mesa_getenv("MESA_DEBUG")) {
877 "Note: %d out of 256 needed colors do not match exactly.\n",
883 v
->dithered_pf
= PF_GRAYSCALE
;
884 v
->undithered_pf
= PF_GRAYSCALE
;
891 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
892 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
893 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
894 * color. While this function was originally designed just for 8-bit
895 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
896 * Dithering code contributed by Bob Mercier.
898 static GLboolean
setup_dithered_color( int client
, XMesaVisual v
,
899 XMesaBuffer buffer
, XMesaColormap cmap
)
901 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
906 XMesaBuffer prevBuffer
;
912 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
914 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
915 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
916 /* Copy colormap stuff from previous, matching XMesaBuffer.
917 * Do this to avoid time spent in noFaultXAllocColor.
919 copy_colortable_info(buffer
, prevBuffer
);
922 /* Allocate X colors and initialize color_table[], red_table[], etc */
924 int colorsfailed
= 0;
925 for (r
= 0; r
< _R
; r
++) {
926 for (g
= 0; g
< _G
; g
++) {
927 for (b
= 0; b
< _B
; b
++) {
930 xcol
.red
=gamma_adjust(v
->RedGamma
, r
*65535/(_R
-1),65535);
931 xcol
.green
=gamma_adjust(v
->GreenGamma
, g
*65535/(_G
-1),65535);
932 xcol
.blue
=gamma_adjust(v
->BlueGamma
, b
*65535/(_B
-1),65535);
933 noFaultXAllocColor( client
, v
->display
,
934 cmap
, GET_COLORMAP_SIZE(v
),
935 &xcol
, &exact
, &alloced
);
940 assert(buffer
->num_alloced
<256);
941 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
942 buffer
->num_alloced
++;
946 buffer
->color_table
[i
] = xcol
.pixel
;
947 assert(xcol
.pixel
< 65536);
948 buffer
->pixel_to_r
[xcol
.pixel
] = r
* 255 / (_R
-1);
949 buffer
->pixel_to_g
[xcol
.pixel
] = g
* 255 / (_G
-1);
950 buffer
->pixel_to_b
[xcol
.pixel
] = b
* 255 / (_B
-1);
955 if (colorsfailed
&& _mesa_getenv("MESA_DEBUG")) {
957 "Note: %d out of %d needed colors do not match exactly.\n",
958 colorsfailed
, _R
*_G
*_B
);
963 v
->dithered_pf
= PF_DITHER
;
964 v
->undithered_pf
= PF_LOOKUP
;
970 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
971 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
972 * Special dithering tables have to be initialized.
974 static void setup_8bit_hpcr( XMesaVisual v
)
976 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be)
977 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
978 * on the root window AND the colormap obtainable by XGetRGBColormaps
979 * for that atom must be set on the window. (see also tkInitWindow)
980 * If that colormap is not set, the output will look stripy.
983 /* Setup color tables with gamma correction */
987 g
= 1.0 / v
->RedGamma
;
988 for (i
=0; i
<256; i
++) {
989 GLint red
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[0][i
]/255.0, g
));
990 v
->hpcr_rgbTbl
[0][i
] = CLAMP( red
, 16, 239 );
993 g
= 1.0 / v
->GreenGamma
;
994 for (i
=0; i
<256; i
++) {
995 GLint green
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[1][i
]/255.0, g
));
996 v
->hpcr_rgbTbl
[1][i
] = CLAMP( green
, 16, 239 );
999 g
= 1.0 / v
->BlueGamma
;
1000 for (i
=0; i
<256; i
++) {
1001 GLint blue
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[2][i
]/255.0, g
));
1002 v
->hpcr_rgbTbl
[2][i
] = CLAMP( blue
, 32, 223 );
1004 v
->undithered_pf
= PF_HPCR
; /* can't really disable dithering for now */
1005 v
->dithered_pf
= PF_HPCR
;
1007 /* which method should I use to clear */
1008 /* GL_FALSE: keep the ordinary method */
1009 /* GL_TRUE : clear with dither pattern */
1010 v
->hpcr_clear_flag
= _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE
: GL_FALSE
;
1012 if (v
->hpcr_clear_flag
) {
1013 v
->hpcr_clear_pixmap
= XMesaCreatePixmap(v
->display
,
1014 DefaultRootWindow(v
->display
),
1016 #ifndef XFree86Server
1017 v
->hpcr_clear_ximage
= XGetImage(v
->display
, v
->hpcr_clear_pixmap
,
1018 0, 0, 16, 2, AllPlanes
, ZPixmap
);
1025 * Setup RGB rendering for a window with a True/DirectColor visual.
1027 static void setup_truecolor( XMesaVisual v
, XMesaBuffer buffer
,
1028 XMesaColormap cmap
)
1030 unsigned long rmask
, gmask
, bmask
;
1034 /* Compute red multiplier (mask) and bit shift */
1036 rmask
= GET_REDMASK(v
);
1037 while ((rmask
& 1)==0) {
1042 /* Compute green multiplier (mask) and bit shift */
1044 gmask
= GET_GREENMASK(v
);
1045 while ((gmask
& 1)==0) {
1050 /* Compute blue multiplier (mask) and bit shift */
1052 bmask
= GET_BLUEMASK(v
);
1053 while ((bmask
& 1)==0) {
1059 * Compute component-to-pixel lookup tables and dithering kernel
1062 static GLubyte kernel
[16] = {
1063 0*16, 8*16, 2*16, 10*16,
1064 12*16, 4*16, 14*16, 6*16,
1065 3*16, 11*16, 1*16, 9*16,
1066 15*16, 7*16, 13*16, 5*16,
1068 GLint rBits
= bitcount(rmask
);
1069 GLint gBits
= bitcount(gmask
);
1070 GLint bBits
= bitcount(bmask
);
1074 /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1075 for (i
=0; i
<=rmask
; i
++)
1076 v
->PixelToR
[i
] = (unsigned char) ((i
* 255) / rmask
);
1077 for (i
=0; i
<=gmask
; i
++)
1078 v
->PixelToG
[i
] = (unsigned char) ((i
* 255) / gmask
);
1079 for (i
=0; i
<=bmask
; i
++)
1080 v
->PixelToB
[i
] = (unsigned char) ((i
* 255) / bmask
);
1082 /* convert RGB values from [0,255] to pixel components */
1084 for (i
=0;i
<256;i
++) {
1085 GLint r
= gamma_adjust(v
->RedGamma
, i
, 255);
1086 GLint g
= gamma_adjust(v
->GreenGamma
, i
, 255);
1087 GLint b
= gamma_adjust(v
->BlueGamma
, i
, 255);
1088 v
->RtoPixel
[i
] = (r
>> (8-rBits
)) << v
->rshift
;
1089 v
->GtoPixel
[i
] = (g
>> (8-gBits
)) << v
->gshift
;
1090 v
->BtoPixel
[i
] = (b
>> (8-bBits
)) << v
->bshift
;
1092 /* overflow protection */
1093 for (i
=256;i
<512;i
++) {
1094 v
->RtoPixel
[i
] = v
->RtoPixel
[255];
1095 v
->GtoPixel
[i
] = v
->GtoPixel
[255];
1096 v
->BtoPixel
[i
] = v
->BtoPixel
[255];
1099 /* setup dithering kernel */
1101 if (gBits
> maxBits
) maxBits
= gBits
;
1102 if (bBits
> maxBits
) maxBits
= bBits
;
1103 for (i
=0;i
<16;i
++) {
1104 v
->Kernel
[i
] = kernel
[i
] >> maxBits
;
1107 v
->undithered_pf
= PF_TRUECOLOR
;
1108 v
->dithered_pf
= (GET_VISUAL_DEPTH(v
)<24) ? PF_TRUEDITHER
: PF_TRUECOLOR
;
1112 * Now check for TrueColor visuals which we can optimize.
1114 if ( GET_REDMASK(v
) ==0x0000ff
1115 && GET_GREENMASK(v
)==0x00ff00
1116 && GET_BLUEMASK(v
) ==0xff0000
1117 && CHECK_BYTE_ORDER(v
)
1118 && v
->BitsPerPixel
==32
1119 && sizeof(GLuint
)==4
1120 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1121 /* common 32 bpp config used on SGI, Sun */
1122 v
->undithered_pf
= v
->dithered_pf
= PF_8A8B8G8R
;
1124 else if (GET_REDMASK(v
) ==0xff0000
1125 && GET_GREENMASK(v
)==0x00ff00
1126 && GET_BLUEMASK(v
) ==0x0000ff
1127 && CHECK_BYTE_ORDER(v
)
1128 && v
->BitsPerPixel
==32
1129 && sizeof(GLuint
)==4
1130 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1131 /* common 32 bpp config used on Linux, HP, IBM */
1132 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B
;
1134 else if (GET_REDMASK(v
) ==0xff0000
1135 && GET_GREENMASK(v
)==0x00ff00
1136 && GET_BLUEMASK(v
) ==0x0000ff
1137 && CHECK_BYTE_ORDER(v
)
1138 && v
->BitsPerPixel
==24
1139 && sizeof(GLuint
)==4
1140 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1141 /* common packed 24 bpp config used on Linux */
1142 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B24
;
1144 else if (GET_REDMASK(v
) ==0xf800
1145 && GET_GREENMASK(v
)==0x07e0
1146 && GET_BLUEMASK(v
) ==0x001f
1147 && CHECK_BYTE_ORDER(v
)
1148 && v
->BitsPerPixel
==16
1149 && sizeof(GLushort
)==2
1150 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1151 /* 5-6-5 color weight on common PC VGA boards */
1152 v
->undithered_pf
= PF_5R6G5B
;
1153 v
->dithered_pf
= PF_DITHER_5R6G5B
;
1155 else if (GET_REDMASK(v
) ==0xe0
1156 && GET_GREENMASK(v
)==0x1c
1157 && GET_BLUEMASK(v
) ==0x03
1158 && CHECK_FOR_HPCR(v
)) {
1159 setup_8bit_hpcr( v
);
1166 * Setup RGB rendering for a window with a monochrome visual.
1168 static void setup_monochrome( XMesaVisual v
, XMesaBuffer b
)
1171 v
->dithered_pf
= v
->undithered_pf
= PF_1BIT
;
1172 /* if black=1 then we must flip pixel values */
1173 v
->bitFlip
= (GET_BLACK_PIXEL(v
) != 0);
1179 * When a context is "made current" for the first time, we can finally
1180 * finish initializing the context's visual and buffer information.
1181 * Input: v - the XMesaVisual to initialize
1182 * b - the XMesaBuffer to initialize (may be NULL)
1183 * rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1184 * window - the window/pixmap we're rendering into
1185 * cmap - the colormap associated with the window/pixmap
1186 * Return: GL_TRUE=success, GL_FALSE=failure
1188 static GLboolean
initialize_visual_and_buffer( int client
,
1192 XMesaDrawable window
,
1193 XMesaColormap cmap
)
1195 #ifndef XFree86Server
1200 assert(b
->xm_visual
== v
);
1203 /* Save true bits/pixel */
1204 v
->BitsPerPixel
= bits_per_pixel(v
);
1205 assert(v
->BitsPerPixel
> 0);
1208 if (rgb_flag
==GL_FALSE
) {
1209 /* COLOR-INDEXED WINDOW:
1210 * Even if the visual is TrueColor or DirectColor we treat it as
1211 * being color indexed. This is weird but might be useful to someone.
1213 v
->dithered_pf
= v
->undithered_pf
= PF_INDEX
;
1214 v
->index_bits
= GET_VISUAL_DEPTH(v
);
1218 * We support RGB rendering into almost any kind of visual.
1221 xclass
= GET_VISUAL_CLASS(v
);
1222 if (xclass
==TrueColor
|| xclass
==DirectColor
) {
1223 setup_truecolor( v
, b
, cmap
);
1225 else if (xclass
==StaticGray
&& GET_VISUAL_DEPTH(v
)==1) {
1226 setup_monochrome( v
, b
);
1228 else if (xclass
==GrayScale
|| xclass
==StaticGray
) {
1229 if (!setup_grayscale( client
, v
, b
, cmap
)) {
1233 else if ((xclass
==PseudoColor
|| xclass
==StaticColor
)
1234 && GET_VISUAL_DEPTH(v
)>=4 && GET_VISUAL_DEPTH(v
)<=16) {
1235 if (!setup_dithered_color( client
, v
, b
, cmap
)) {
1240 error("XMesa: RGB mode rendering not supported in given visual.");
1245 if (_mesa_getenv("MESA_NO_DITHER")) {
1246 v
->dithered_pf
= v
->undithered_pf
;
1252 * If MESA_INFO env var is set print out some debugging info
1253 * which can help Brian figure out what's going on when a user
1256 if (_mesa_getenv("MESA_INFO")) {
1257 fprintf(stderr
, "X/Mesa visual = %p\n", (void *) v
);
1258 fprintf(stderr
, "X/Mesa dithered pf = %u\n", v
->dithered_pf
);
1259 fprintf(stderr
, "X/Mesa undithered pf = %u\n", v
->undithered_pf
);
1260 fprintf(stderr
, "X/Mesa level = %d\n", v
->level
);
1261 fprintf(stderr
, "X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v
));
1262 fprintf(stderr
, "X/Mesa bits per pixel = %d\n", v
->BitsPerPixel
);
1266 /* Do window-specific initializations */
1268 /* Window dimensions */
1270 get_drawable_size( v
->display
, window
, &w
, &h
);
1274 b
->frontbuffer
= window
;
1276 /* Setup for single/double buffering */
1277 if (v
->mesa_visual
.doubleBufferMode
) {
1278 /* Double buffered */
1279 #ifndef XFree86Server
1280 b
->shm
= check_for_xshm( v
->display
);
1282 xmesa_alloc_back_buffer( b
);
1283 if (b
->db_state
==BACK_PIXMAP
) {
1284 b
->buffer
= (XMesaDrawable
)b
->backpixmap
;
1291 /* Single Buffered */
1292 b
->buffer
= b
->frontbuffer
;
1295 /* X11 graphics contexts */
1296 #ifdef XFree86Server
1297 b
->gc
= CreateScratchGC(v
->display
, window
->depth
);
1299 b
->gc
= XCreateGC( v
->display
, window
, 0, NULL
);
1301 XMesaSetFunction( v
->display
, b
->gc
, GXcopy
);
1303 /* cleargc - for glClear() */
1304 #ifdef XFree86Server
1305 b
->cleargc
= CreateScratchGC(v
->display
, window
->depth
);
1307 b
->cleargc
= XCreateGC( v
->display
, window
, 0, NULL
);
1309 XMesaSetFunction( v
->display
, b
->cleargc
, GXcopy
);
1312 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1313 * Patch contributed by Michael Pichler May 15, 1995.
1315 #ifdef XFree86Server
1316 b
->swapgc
= CreateScratchGC(v
->display
, window
->depth
);
1320 dixChangeGC(NullClient
, b
->swapgc
, GCGraphicsExposures
, v
, NULL
);
1323 gcvalues
.graphics_exposures
= False
;
1324 b
->swapgc
= XCreateGC( v
->display
, window
,
1325 GCGraphicsExposures
, &gcvalues
);
1327 XMesaSetFunction( v
->display
, b
->swapgc
, GXcopy
);
1329 * Set fill style and tile pixmap once for all for HPCR stuff
1330 * (instead of doing it each time in clear_color_HPCR_pixmap())
1331 * Initialize whole stuff
1332 * Patch contributed by Jacques Leroy March 8, 1998.
1334 if (v
->hpcr_clear_flag
&& b
->buffer
!=XIMAGE
) {
1336 for (i
=0; i
<16; i
++)
1338 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 0, 0);
1339 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 1, 0);
1341 XMesaPutImage(b
->display
, (XMesaDrawable
)v
->hpcr_clear_pixmap
,
1342 b
->cleargc
, v
->hpcr_clear_ximage
, 0, 0, 0, 0, 16, 2);
1343 XMesaSetFillStyle( v
->display
, b
->cleargc
, FillTiled
);
1344 XMesaSetTile( v
->display
, b
->cleargc
, v
->hpcr_clear_pixmap
);
1347 /* Initialize the row buffer XImage for use in write_color_span() */
1348 #ifdef XFree86Server
1349 b
->rowimage
= XMesaCreateImage(GET_VISUAL_DEPTH(v
), MAX_WIDTH
, 1,
1350 (char *)MALLOC(MAX_WIDTH
*4));
1352 b
->rowimage
= XCreateImage( v
->display
,
1355 ZPixmap
, 0, /*format, offset*/
1356 (char*) MALLOC(MAX_WIDTH
*4), /*data*/
1357 MAX_WIDTH
, 1, /*width, height*/
1359 0 /*bytes_per_line*/ );
1369 * Convert an RGBA color to a pixel value.
1372 xmesa_color_to_pixel( XMesaContext xmesa
, GLubyte r
, GLubyte g
, GLubyte b
, GLubyte a
,
1375 switch (pixelFormat
) {
1381 PACK_TRUECOLOR( p
, r
, g
, b
);
1385 return PACK_8A8B8G8R( r
, g
, b
, a
);
1389 return PACK_8R8G8B( r
, g
, b
);
1391 return PACK_5R6G5B( r
, g
, b
);
1395 return DITHER( 1, 0, r
, g
, b
);
1398 /* 382 = (3*255)/2 */
1399 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
1401 return DITHER_HPCR(1, 1, r
, g
, b
);
1405 return LOOKUP( r
, g
, b
);
1408 return GRAY_RGB( r
, g
, b
);
1411 case PF_DITHER_5R6G5B
:
1414 PACK_TRUEDITHER(p
, 1, 0, r
, g
, b
);
1418 _mesa_problem(NULL
, "Bad pixel format in xmesa_color_to_pixel");
1424 /**********************************************************************/
1425 /***** Public Functions *****/
1426 /**********************************************************************/
1430 * Create a new X/Mesa visual.
1431 * Input: display - X11 display
1432 * visinfo - an XVisualInfo pointer
1433 * rgb_flag - GL_TRUE = RGB mode,
1434 * GL_FALSE = color index mode
1435 * alpha_flag - alpha buffer requested?
1436 * db_flag - GL_TRUE = double-buffered,
1437 * GL_FALSE = single buffered
1438 * stereo_flag - stereo visual?
1439 * ximage_flag - GL_TRUE = use an XImage for back buffer,
1440 * GL_FALSE = use an off-screen pixmap for back buffer
1441 * depth_size - requested bits/depth values, or zero
1442 * stencil_size - requested bits/stencil values, or zero
1443 * accum_red_size - requested bits/red accum values, or zero
1444 * accum_green_size - requested bits/green accum values, or zero
1445 * accum_blue_size - requested bits/blue accum values, or zero
1446 * accum_alpha_size - requested bits/alpha accum values, or zero
1447 * num_samples - number of samples/pixel if multisampling, or zero
1448 * level - visual level, usually 0
1449 * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT
1450 * Return; a new XMesaVisual or 0 if error.
1452 XMesaVisual
XMesaCreateVisual( XMesaDisplay
*display
,
1453 XMesaVisualInfo visinfo
,
1455 GLboolean alpha_flag
,
1457 GLboolean stereo_flag
,
1458 GLboolean ximage_flag
,
1461 GLint accum_red_size
,
1462 GLint accum_green_size
,
1463 GLint accum_blue_size
,
1464 GLint accum_alpha_size
,
1467 GLint visualCaveat
)
1471 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1473 /* For debugging only */
1474 if (_mesa_getenv("MESA_XSYNC")) {
1475 /* This makes debugging X easier.
1476 * In your debugger, set a breakpoint on _XError to stop when an
1477 * X protocol error is generated.
1479 #ifdef XFree86Server
1482 XSynchronize( display
, 1 );
1486 v
= (XMesaVisual
) CALLOC_STRUCT(xmesa_visual
);
1492 * In the X server, NULL is passed in for the display. It will have
1493 * to be set before using this visual. See XMesaSetVisualDisplay()
1496 v
->display
= display
;
1498 /* Save a copy of the XVisualInfo struct because the user may XFREE()
1499 * the struct but we may need some of the information contained in it
1502 #ifdef XFree86Server
1503 v
->visinfo
= visinfo
;
1505 v
->visinfo
= (XVisualInfo
*) MALLOC(sizeof(*visinfo
));
1510 MEMCPY(v
->visinfo
, visinfo
, sizeof(*visinfo
));
1512 /* Save a copy of the pointer now so we can find this visual again
1513 * if we need to search for it in find_glx_visual().
1515 v
->vishandle
= visinfo
;
1518 #ifdef XFree86Server
1519 /* Initialize the depth of the screen */
1521 PixmapFormatRec
*format
;
1523 for (format
= screenInfo
.formats
;
1524 format
->depth
!= display
->rootDepth
;
1527 v
->screen_depth
= format
->bitsPerPixel
;
1531 /* check for MESA_GAMMA environment variable */
1532 gamma
= _mesa_getenv("MESA_GAMMA");
1534 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 0.0;
1535 sscanf( gamma
, "%f %f %f", &v
->RedGamma
, &v
->GreenGamma
, &v
->BlueGamma
);
1536 if (v
->RedGamma
<=0.0) v
->RedGamma
= 1.0;
1537 if (v
->GreenGamma
<=0.0) v
->GreenGamma
= v
->RedGamma
;
1538 if (v
->BlueGamma
<=0.0) v
->BlueGamma
= v
->RedGamma
;
1541 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 1.0;
1544 v
->ximage_flag
= ximage_flag
;
1546 v
->VisualCaveat
= visualCaveat
;
1548 (void) initialize_visual_and_buffer( 0, v
, NULL
, rgb_flag
, 0, 0 );
1552 xclass
= GET_VISUAL_CLASS(v
);
1553 if (xclass
==TrueColor
|| xclass
==DirectColor
) {
1554 red_bits
= bitcount(GET_REDMASK(v
));
1555 green_bits
= bitcount(GET_GREENMASK(v
));
1556 blue_bits
= bitcount(GET_BLUEMASK(v
));
1560 /* this is an approximation */
1562 depth
= GET_VISUAL_DEPTH(v
);
1563 red_bits
= depth
/ 3;
1565 green_bits
= depth
/ 2;
1566 depth
-= green_bits
;
1569 assert( red_bits
+ green_bits
+ blue_bits
== GET_VISUAL_DEPTH(v
) );
1573 if (alpha_flag
&& alpha_bits
== 0)
1576 _mesa_initialize_visual( &v
->mesa_visual
,
1577 rgb_flag
, db_flag
, stereo_flag
,
1578 red_bits
, green_bits
,
1579 blue_bits
, alpha_bits
,
1583 accum_red_size
, accum_green_size
,
1584 accum_blue_size
, accum_alpha_size
,
1590 void XMesaSetVisualDisplay( XMesaDisplay
*dpy
, XMesaVisual v
)
1596 void XMesaDestroyVisual( XMesaVisual v
)
1598 #ifndef XFree86Server
1607 * Create a new XMesaContext.
1608 * Input: v - XMesaVisual
1609 * share_list - another XMesaContext with which to share display
1610 * lists or NULL if no sharing is wanted.
1611 * Return: an XMesaContext or NULL if error.
1613 XMesaContext
XMesaCreateContext( XMesaVisual v
, XMesaContext share_list
)
1615 static GLboolean firstTime
= GL_TRUE
;
1618 GLboolean direct
= GL_TRUE
; /* not really */
1621 _glthread_INIT_MUTEX(_xmesa_lock
);
1622 firstTime
= GL_FALSE
;
1625 c
= (XMesaContext
) CALLOC_STRUCT(xmesa_context
);
1630 ctx
= c
->gl_ctx
= _mesa_create_context( &v
->mesa_visual
,
1631 share_list
? share_list
->gl_ctx
: (GLcontext
*) NULL
,
1632 (void *) c
, direct
);
1638 _mesa_enable_sw_extensions(ctx
);
1639 _mesa_enable_1_3_extensions(ctx
);
1640 _mesa_enable_1_4_extensions(ctx
);
1642 if (CHECK_BYTE_ORDER(v
)) {
1643 c
->swapbytes
= GL_FALSE
;
1646 c
->swapbytes
= GL_TRUE
;
1650 c
->xm_draw_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1651 c
->xm_read_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1652 c
->xm_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1653 c
->display
= v
->display
;
1654 c
->pixelformat
= v
->dithered_pf
; /* Dithering is enabled by default */
1656 ctx
->Driver
.UpdateState
= xmesa_update_state
;
1658 /* Initialize the software rasterizer and helper modules.
1660 _swrast_CreateContext( ctx
);
1661 _ac_CreateContext( ctx
);
1662 _tnl_CreateContext( ctx
);
1663 _swsetup_CreateContext( ctx
);
1665 xmesa_register_swrast_functions( ctx
);
1667 /* Set up some constant pointers:
1669 xmesa_init_pointers( ctx
);
1677 void XMesaDestroyContext( XMesaContext c
)
1680 if (c
->xm_draw_buffer
&& c
->xm_buffer
->FXctx
)
1681 fxMesaDestroyContext(c
->xm_draw_buffer
->FXctx
);
1684 _swsetup_DestroyContext( c
->gl_ctx
);
1685 _swrast_DestroyContext( c
->gl_ctx
);
1686 _tnl_DestroyContext( c
->gl_ctx
);
1687 _ac_DestroyContext( c
->gl_ctx
);
1688 _mesa_destroy_context( c
->gl_ctx
);
1697 * XXX this isn't a public function! It's a hack for the 3Dfx driver.
1698 * Create a new XMesaBuffer from an X window.
1699 * Input: v - the XMesaVisual
1702 * Return: new XMesaBuffer or NULL if error
1704 XMesaBuffer
XMesaCreateWindowBuffer2( XMesaVisual v
, XMesaWindow w
,
1707 #ifndef XFree86Server
1708 XWindowAttributes attr
;
1715 XMesaBuffer b
= alloc_xmesa_buffer();
1722 #ifdef XFree86Server
1723 client
= CLIENT_ID(((XMesaDrawable
)w
)->id
);
1728 #ifdef XFree86Server
1729 if (GET_VISUAL_DEPTH(v
) != ((XMesaDrawable
)w
)->depth
) {
1731 XGetWindowAttributes( v
->display
, w
, &attr
);
1733 if (GET_VISUAL_DEPTH(v
) != attr
.depth
) {
1735 if (_mesa_getenv("MESA_DEBUG")) {
1736 fprintf(stderr
, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n");
1743 b
->display
= v
->display
;
1744 #ifdef XFree86Server
1745 b
->cmap
= (ColormapPtr
)LookupIDByType(wColormap(w
), RT_COLORMAP
);
1747 if (attr
.colormap
) {
1748 b
->cmap
= attr
.colormap
;
1751 if (_mesa_getenv("MESA_DEBUG")) {
1752 fprintf(stderr
, "Window %u has no colormap!\n", (unsigned int) w
);
1754 /* this is weird, a window w/out a colormap!? */
1755 /* OK, let's just allocate a new one and hope for the best */
1756 b
->cmap
= XCreateColormap(v
->display
, w
, attr
.visual
, AllocNone
);
1760 /* determine back buffer implementation */
1761 if (v
->mesa_visual
.doubleBufferMode
) {
1762 if (v
->ximage_flag
) {
1763 b
->db_state
= BACK_XIMAGE
;
1766 b
->db_state
= BACK_PIXMAP
;
1773 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
1775 v
->mesa_visual
.depthBits
> 0,
1776 v
->mesa_visual
.stencilBits
> 0,
1777 v
->mesa_visual
.accumRedBits
> 0,
1778 v
->mesa_visual
.alphaBits
> 0 );
1780 if (!initialize_visual_and_buffer( client
, v
, b
, v
->mesa_visual
.rgbMode
,
1781 (XMesaDrawable
)w
, b
->cmap
)) {
1782 free_xmesa_buffer(client
, b
);
1787 fxEnvVar
= _mesa_getenv("MESA_GLX_FX");
1789 if (fxEnvVar
[0]!='d') {
1793 if (v
->mesa_visual
.depthBits
> 0) {
1794 attribs
[numAttribs
++] = FXMESA_DEPTH_SIZE
;
1795 attribs
[numAttribs
++] = 1;
1797 if (v
->mesa_visual
.doubleBufferMode
) {
1798 attribs
[numAttribs
++] = FXMESA_DOUBLEBUFFER
;
1800 if (v
->mesa_visual
.accumRedBits
> 0) {
1801 attribs
[numAttribs
++] = FXMESA_ACCUM_SIZE
;
1802 attribs
[numAttribs
++] = v
->mesa_visual
.accumRedBits
;
1804 if (v
->mesa_visual
.stencilBits
> 0) {
1805 attribs
[numAttribs
++] = FXMESA_STENCIL_SIZE
;
1806 attribs
[numAttribs
++] = v
->mesa_visual
.stencilBits
;
1808 if (v
->mesa_visual
.alphaBits
> 0) {
1809 attribs
[numAttribs
++] = FXMESA_ALPHA_SIZE
;
1810 attribs
[numAttribs
++] = 1;
1813 #define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with fxapi.c! */
1814 attribs
[numAttribs
++] = FXMESA_SHARE_CONTEXT
;
1815 attribs
[numAttribs
++] = (int) c
->gl_ctx
;
1817 attribs
[numAttribs
++] = FXMESA_NONE
;
1819 if ((hw
= fxQueryHardware())==GR_SSTTYPE_VOODOO
) {
1820 b
->FXctx
= fxMesaCreateBestContext(0, b
->width
, b
->height
, attribs
);
1821 if ((v
->undithered_pf
!=PF_INDEX
) && (b
->backimage
)) {
1822 b
->FXisHackUsable
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1823 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1824 b
->FXwindowHack
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1826 b
->FXwindowHack
= GL_FALSE
;
1830 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1831 b
->FXctx
= fxMesaCreateContext(w
, GR_RESOLUTION_NONE
,
1832 GR_REFRESH_75Hz
, attribs
);
1834 b
->FXctx
= fxMesaCreateBestContext(0, b
->width
, b
->height
, attribs
);
1835 b
->FXisHackUsable
= GL_FALSE
;
1836 b
->FXwindowHack
= GL_FALSE
;
1840 "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1841 hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
1846 fprintf(stderr
,"WARNING: This Mesa Library includes the Glide driver but\n");
1847 fprintf(stderr
," you have not defined the MESA_GLX_FX env. var.\n");
1848 fprintf(stderr
," (check the README.3DFX file for more information).\n\n");
1849 fprintf(stderr
," you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1857 XMesaBuffer
XMesaCreateWindowBuffer( XMesaVisual v
, XMesaWindow w
)
1859 return XMesaCreateWindowBuffer2( v
, w
, NULL
);
1864 * Create a new XMesaBuffer from an X pixmap.
1865 * Input: v - the XMesaVisual
1867 * cmap - the colormap, may be 0 if using a TrueColor or DirectColor
1868 * visual for the pixmap
1869 * Return: new XMesaBuffer or NULL if error
1871 XMesaBuffer
XMesaCreatePixmapBuffer( XMesaVisual v
,
1872 XMesaPixmap p
, XMesaColormap cmap
)
1875 XMesaBuffer b
= alloc_xmesa_buffer();
1881 #ifdef XFree86Server
1882 client
= CLIENT_ID(((XMesaDrawable
)p
)->id
);
1889 b
->display
= v
->display
;
1892 /* determine back buffer implementation */
1893 if (v
->mesa_visual
.doubleBufferMode
) {
1894 if (v
->ximage_flag
) {
1895 b
->db_state
= BACK_XIMAGE
;
1898 b
->db_state
= BACK_PIXMAP
;
1905 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
1907 v
->mesa_visual
.depthBits
> 0,
1908 v
->mesa_visual
.stencilBits
> 0,
1909 v
->mesa_visual
.accumRedBits
+
1910 v
->mesa_visual
.accumGreenBits
+
1911 v
->mesa_visual
.accumBlueBits
> 0,
1912 v
->mesa_visual
.alphaBits
> 0 );
1914 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1915 (XMesaDrawable
)p
, cmap
)) {
1916 free_xmesa_buffer(client
, b
);
1925 XMesaBuffer
XMesaCreatePBuffer( XMesaVisual v
, XMesaColormap cmap
,
1926 unsigned int width
, unsigned int height
)
1928 #ifdef XFree86Server
1933 XMesaDrawable drawable
; /* X Pixmap Drawable */
1934 XMesaBuffer b
= alloc_xmesa_buffer();
1941 b
->display
= v
->display
;
1944 /* allocate pixmap for front buffer */
1945 root
= RootWindow( v
->display
, v
->visinfo
->screen
);
1946 drawable
= XCreatePixmap( v
->display
, root
, width
, height
, v
->visinfo
->depth
);
1948 /* determine back buffer implementation */
1949 if (v
->mesa_visual
.doubleBufferMode
) {
1950 if (v
->ximage_flag
) {
1951 b
->db_state
= BACK_XIMAGE
;
1954 b
->db_state
= BACK_PIXMAP
;
1961 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
1963 v
->mesa_visual
.depthBits
> 0,
1964 v
->mesa_visual
.stencilBits
> 0,
1965 v
->mesa_visual
.accumRedBits
+
1966 v
->mesa_visual
.accumGreenBits
+
1967 v
->mesa_visual
.accumBlueBits
> 0,
1968 v
->mesa_visual
.alphaBits
> 0 );
1970 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1972 free_xmesa_buffer(client
, b
);
1983 * Deallocate an XMesaBuffer structure and all related info.
1985 void XMesaDestroyBuffer( XMesaBuffer b
)
1989 #ifdef XFree86Server
1991 client
= CLIENT_ID(b
->frontbuffer
->id
);
1994 if (b
->gc
) XMesaFreeGC( b
->xm_visual
->display
, b
->gc
);
1995 if (b
->cleargc
) XMesaFreeGC( b
->xm_visual
->display
, b
->cleargc
);
1996 if (b
->swapgc
) XMesaFreeGC( b
->xm_visual
->display
, b
->swapgc
);
1999 #if defined(USE_XSHM) && !defined(XFree86Server)
2001 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
2002 XDestroyImage( b
->backimage
);
2003 shmdt( b
->shminfo
.shmaddr
);
2007 XMesaDestroyImage( b
->backimage
);
2009 if (b
->backpixmap
) {
2010 XMesaFreePixmap( b
->xm_visual
->display
, b
->backpixmap
);
2011 if (b
->xm_visual
->hpcr_clear_flag
) {
2012 XMesaFreePixmap( b
->xm_visual
->display
,
2013 b
->xm_visual
->hpcr_clear_pixmap
);
2014 XMesaDestroyImage( b
->xm_visual
->hpcr_clear_ximage
);
2018 FREE( b
->rowimage
->data
);
2019 b
->rowimage
->data
= NULL
;
2020 XMesaDestroyImage( b
->rowimage
);
2023 free_xmesa_buffer(client
, b
);
2029 * Bind buffer b to context c and make c the current rendering context.
2031 GLboolean
XMesaMakeCurrent( XMesaContext c
, XMesaBuffer b
)
2033 return XMesaMakeCurrent2( c
, b
, b
);
2038 * Bind buffer b to context c and make c the current rendering context.
2040 GLboolean
XMesaMakeCurrent2( XMesaContext c
, XMesaBuffer drawBuffer
,
2041 XMesaBuffer readBuffer
)
2044 if (!drawBuffer
|| !readBuffer
)
2045 return GL_FALSE
; /* must specify buffers! */
2048 if (drawBuffer
->FXctx
) {
2049 fxMesaMakeCurrent(drawBuffer
->FXctx
);
2051 c
->xm_draw_buffer
= drawBuffer
;
2052 c
->xm_read_buffer
= readBuffer
;
2053 c
->xm_buffer
= drawBuffer
;
2058 if (c
->gl_ctx
== _mesa_get_current_context()
2059 && c
->xm_draw_buffer
== drawBuffer
2060 && c
->xm_read_buffer
== readBuffer
2061 && c
->xm_draw_buffer
->wasCurrent
) {
2062 /* same context and buffer, do nothing */
2066 c
->xm_draw_buffer
= drawBuffer
;
2067 c
->xm_read_buffer
= readBuffer
;
2068 c
->xm_buffer
= drawBuffer
;
2070 _mesa_make_current2(c
->gl_ctx
,
2071 &drawBuffer
->mesa_buffer
,
2072 &readBuffer
->mesa_buffer
);
2074 if (c
->gl_ctx
->Viewport
.Width
== 0) {
2075 /* initialize viewport to window size */
2076 _mesa_Viewport( 0, 0, drawBuffer
->width
, drawBuffer
->height
);
2077 c
->gl_ctx
->Scissor
.Width
= drawBuffer
->width
;
2078 c
->gl_ctx
->Scissor
.Height
= drawBuffer
->height
;
2081 if (c
->xm_visual
->mesa_visual
.rgbMode
) {
2083 * Must recompute and set these pixel values because colormap
2084 * can be different for different windows.
2086 c
->clearpixel
= xmesa_color_to_pixel( c
,
2091 c
->xm_visual
->undithered_pf
);
2092 XMesaSetForeground(c
->display
, c
->xm_draw_buffer
->cleargc
, c
->clearpixel
);
2095 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2096 c
->xm_draw_buffer
->wasCurrent
= GL_TRUE
;
2100 _mesa_make_current2( NULL
, NULL
, NULL
);
2107 * Unbind the context c from its buffer.
2109 GLboolean
XMesaUnbindContext( XMesaContext c
)
2111 /* A no-op for XFree86 integration purposes */
2116 XMesaContext
XMesaGetCurrentContext( void )
2118 GET_CURRENT_CONTEXT(ctx
);
2120 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2129 XMesaBuffer
XMesaGetCurrentBuffer( void )
2131 GET_CURRENT_CONTEXT(ctx
);
2133 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2134 return xmesa
->xm_draw_buffer
;
2142 /* New in Mesa 3.1 */
2143 XMesaBuffer
XMesaGetCurrentReadBuffer( void )
2145 GET_CURRENT_CONTEXT(ctx
);
2147 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2148 return xmesa
->xm_read_buffer
;
2156 GLboolean
XMesaForceCurrent(XMesaContext c
)
2159 if (c
->gl_ctx
!= _mesa_get_current_context()) {
2160 _mesa_make_current(c
->gl_ctx
, &c
->xm_draw_buffer
->mesa_buffer
);
2164 _mesa_make_current(NULL
, NULL
);
2170 GLboolean
XMesaLoseCurrent(XMesaContext c
)
2173 _mesa_make_current(NULL
, NULL
);
2179 * Switch 3Dfx support hack between window and full-screen mode.
2181 GLboolean
XMesaSetFXmode( GLint mode
)
2184 const char *fx
= _mesa_getenv("MESA_GLX_FX");
2185 if (fx
&& fx
[0] != 'd') {
2186 GET_CURRENT_CONTEXT(ctx
);
2187 GrHwConfiguration hw
;
2188 if (!FX_grSstQueryHardware(&hw
)) {
2189 /*fprintf(stderr, "!grSstQueryHardware\n");*/
2192 if (hw
.num_sst
< 1) {
2193 /*fprintf(stderr, "hw.num_sst < 1\n");*/
2197 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2198 if (mode
== XMESA_FX_WINDOW
) {
2199 if (xmesa
->xm_draw_buffer
->FXisHackUsable
) {
2200 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
2201 xmesa
->xm_draw_buffer
->FXwindowHack
= GL_TRUE
;
2205 else if (mode
== XMESA_FX_FULLSCREEN
) {
2206 FX_grSstControl(GR_CONTROL_ACTIVATE
);
2207 xmesa
->xm_draw_buffer
->FXwindowHack
= GL_FALSE
;
2211 /* Error: Bad mode value */
2215 /*fprintf(stderr, "fallthrough\n");*/
2226 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2228 static void FXgetImage( XMesaBuffer b
)
2230 GET_CURRENT_CONTEXT(ctx
);
2231 static unsigned short pixbuf
[MAX_WIDTH
];
2235 unsigned int bw
, depth
, width
, height
;
2236 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
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( b
->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
, b
->FXctx
->width
);
2250 b
->height
= MIN2((int)height
, b
->FXctx
->height
);
2252 b
->width
--; /* prevent odd width */
2253 xmesa_alloc_back_buffer( b
);
2256 grLfbWriteColorFormat(GR_COLORFORMAT_ARGB
);
2257 if (b
->xm_visual
->undithered_pf
==PF_5R6G5B
) {
2258 /* Special case: 16bpp RGB */
2259 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
, /* src buffer */
2260 0, b
->FXctx
->height
- b
->height
, /*pos*/
2261 b
->width
, b
->height
, /* size */
2262 b
->width
* sizeof(GLushort
), /* stride */
2263 b
->backimage
->data
); /* dest buffer */
2265 else if (b
->xm_visual
->dithered_pf
==PF_DITHER
2266 && GET_VISUAL_DEPTH(b
->xm_visual
)==8) {
2267 /* Special case: 8bpp RGB */
2268 for (y
=0;y
<b
->height
;y
++) {
2269 GLubyte
*ptr
= (GLubyte
*) b
->backimage
->data
2270 + b
->backimage
->bytes_per_line
* y
;
2273 /* read row from 3Dfx frame buffer */
2274 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
,
2275 0, b
->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, b
->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,
2307 b
->xm_visual
->undithered_pf
));
2311 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR
);
2317 * Copy the back buffer to the front buffer. If there's no back buffer
2320 void XMesaSwapBuffers( XMesaBuffer b
)
2322 GET_CURRENT_CONTEXT(ctx
);
2324 /* If we're swapping the buffer associated with the current context
2325 * we have to flush any pending rendering commands first.
2327 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
2328 _mesa_notifySwapBuffers(ctx
);
2333 fxMesaSwapBuffers();
2335 if (b
->FXwindowHack
)
2342 /* Copy Ximage from host's memory to server's window */
2343 #if defined(USE_XSHM) && !defined(XFree86Server)
2345 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2346 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2349 0, 0, b
->width
, b
->height
, False
);
2350 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2355 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2356 XMesaPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2359 0, 0, b
->width
, b
->height
);
2360 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2364 /* Copy pixmap to window on server */
2365 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2366 XMesaCopyArea( b
->xm_visual
->display
,
2367 b
->backpixmap
, /* source drawable */
2368 b
->frontbuffer
, /* dest. drawable */
2370 0, 0, b
->width
, b
->height
, /* source region */
2371 0, 0 /* dest region */
2373 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2376 #if !defined(XFree86Server)
2377 XSync( b
->xm_visual
->display
, False
);
2384 * Copy sub-region of back buffer to front buffer
2386 void XMesaCopySubBuffer( XMesaBuffer b
, int x
, int y
, int width
, int height
)
2388 GET_CURRENT_CONTEXT(ctx
);
2390 /* If we're swapping the buffer associated with the current context
2391 * we have to flush any pending rendering commands first.
2393 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
2394 _mesa_notifySwapBuffers(ctx
);
2397 int yTop
= b
->height
- y
- height
;
2400 fxMesaSwapBuffers();
2401 if (b
->FXwindowHack
)
2408 /* Copy Ximage from host's memory to server's window */
2409 #if defined(USE_XSHM) && !defined(XFree86Server)
2411 /* XXX assuming width and height aren't too large! */
2412 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2414 b
->backimage
, x
, yTop
,
2415 x
, yTop
, width
, height
, False
);
2416 /* wait for finished event??? */
2421 /* XXX assuming width and height aren't too large! */
2422 XMesaPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2424 b
->backimage
, x
, yTop
,
2425 x
, yTop
, width
, height
);
2429 /* Copy pixmap to window on server */
2430 XMesaCopyArea( b
->xm_visual
->display
,
2431 b
->backpixmap
, /* source drawable */
2432 b
->frontbuffer
, /* dest. drawable */
2434 x
, yTop
, width
, height
, /* source region */
2435 x
, yTop
/* dest region */
2443 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
2444 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2445 * back buffer directly.
2446 * Output: pixmap - pointer to back buffer's Pixmap, or 0
2447 * ximage - pointer to back buffer's XImage, or NULL
2448 * Return: GL_TRUE = context is double buffered
2449 * GL_FALSE = context is single buffered
2451 GLboolean
XMesaGetBackBuffer( XMesaBuffer b
,
2452 XMesaPixmap
*pixmap
,
2453 XMesaImage
**ximage
)
2456 if (pixmap
) *pixmap
= b
->backpixmap
;
2457 if (ximage
) *ximage
= b
->backimage
;
2469 * Return the depth buffer associated with an XMesaBuffer.
2470 * Input: b - the XMesa buffer handle
2471 * Output: width, height - size of buffer in pixels
2472 * bytesPerValue - bytes per depth value (2 or 4)
2473 * buffer - pointer to depth buffer values
2474 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
2476 GLboolean
XMesaGetDepthBuffer( XMesaBuffer b
, GLint
*width
, GLint
*height
,
2477 GLint
*bytesPerValue
, void **buffer
)
2479 if (!b
->mesa_buffer
.DepthBuffer
) {
2487 *width
= b
->mesa_buffer
.Width
;
2488 *height
= b
->mesa_buffer
.Height
;
2489 *bytesPerValue
= sizeof(GLdepth
);
2490 *buffer
= b
->mesa_buffer
.DepthBuffer
;
2496 void XMesaFlush( XMesaContext c
)
2498 if (c
&& c
->xm_visual
) {
2499 #ifdef XFree86Server
2502 XSync( c
->xm_visual
->display
, False
);
2509 const char *XMesaGetString( XMesaContext c
, int name
)
2512 if (name
==XMESA_VERSION
) {
2515 else if (name
==XMESA_EXTENSIONS
) {
2525 XMesaBuffer
XMesaFindBuffer( XMesaDisplay
*dpy
, XMesaDrawable d
)
2528 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
2529 if (b
->frontbuffer
==d
&& b
->display
==dpy
) {
2539 * Look for XMesaBuffers whose X window has been destroyed.
2540 * Deallocate any such XMesaBuffers.
2542 void XMesaGarbageCollect( void )
2544 XMesaBuffer b
, next
;
2545 for (b
=XMesaBufferList
; b
; b
=next
) {
2547 if (b
->display
&& b
->frontbuffer
&& b
->type
== WINDOW
) {
2548 #ifdef XFree86Server
2551 XSync(b
->display
, False
);
2552 if (!window_exists( b
->display
, b
->frontbuffer
)) {
2553 /* found a dead window, free the ancillary info */
2554 XMesaDestroyBuffer( b
);
2562 void XMesaReset( void )
2564 while (XMesaBufferList
)
2565 XMesaDestroyBuffer(XMesaBufferList
);
2567 XMesaBufferList
= NULL
;
2571 unsigned long XMesaDitherColor( XMesaContext xmesa
, GLint x
, GLint y
,
2572 GLfloat red
, GLfloat green
,
2573 GLfloat blue
, GLfloat alpha
)
2575 GLint r
= (GLint
) (red
* 255.0F
);
2576 GLint g
= (GLint
) (green
* 255.0F
);
2577 GLint b
= (GLint
) (blue
* 255.0F
);
2578 GLint a
= (GLint
) (alpha
* 255.0F
);
2580 switch (xmesa
->pixelformat
) {
2586 PACK_TRUECOLOR( p
, r
, g
, b
);
2590 return PACK_8A8B8G8R( r
, g
, b
, a
);
2592 return PACK_8R8G8B( r
, g
, b
);
2594 return PACK_5R6G5B( r
, g
, b
);
2598 return DITHER( x
, y
, r
, g
, b
);
2601 /* 382 = (3*255)/2 */
2602 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
2604 return DITHER_HPCR(x
, y
, r
, g
, b
);
2608 return LOOKUP( r
, g
, b
);
2611 return GRAY_RGB( r
, g
, b
);
2612 case PF_DITHER_5R6G5B
:
2617 PACK_TRUEDITHER(p
, x
, y
, r
, g
, b
);
2621 _mesa_problem(NULL
, "Bad pixel format in XMesaDitherColor");
2628 * This is typically called when the window size changes and we need
2629 * to reallocate the buffer's back/depth/stencil/accum buffers.
2631 void XMesaResizeBuffers( XMesaBuffer b
)
2633 xmesa_resize_buffers( &(b
->mesa_buffer
) );