1 /* $Id: xm_api.c,v 1.45 2002/10/14 17:08:34 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"
81 #include "texformat.h"
83 #include "swrast/swrast.h"
84 #include "swrast_setup/swrast_setup.h"
85 #include "array_cache/acache.h"
89 #define GLX_NONE_EXT 0x8000
94 * Global X driver lock
96 _glthread_Mutex _xmesa_lock
;
101 * Lookup tables for HPCR pixel format:
103 static short hpcr_rgbTbl
[3][256] = {
105 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
106 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
107 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
108 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
109 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
110 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
111 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
112 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
113 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
114 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
115 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
116 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
117 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
118 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
119 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
120 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
123 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
124 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
125 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
126 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
127 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
128 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
129 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
130 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
131 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
132 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
133 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
134 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
135 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
136 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
137 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
138 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
141 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
142 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
143 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55,
144 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
145 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
146 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79,
147 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87,
148 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
149 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
150 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
151 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
152 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
153 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
154 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
155 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
156 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
162 /**********************************************************************/
163 /***** X Utility Functions *****/
164 /**********************************************************************/
168 * X/Mesa error reporting function:
170 static void error( const char *msg
)
172 (void)DitherValues
; /* Muffle compiler */
174 if (getenv("MESA_DEBUG"))
175 fprintf( stderr
, "X/Mesa error: %s\n", msg
);
180 * Return the host's byte order as LSBFirst or MSBFirst ala X.
182 #ifndef XFree86Server
183 static int host_byte_order( void )
186 char *cptr
= (char *) &i
;
187 return (*cptr
==1) ? LSBFirst
: MSBFirst
;
195 #ifndef XFree86Server
196 static int mesaXErrorFlag
= 0;
198 static int mesaHandleXError( XMesaDisplay
*dpy
, XErrorEvent
*event
)
209 * Check if the X Shared Memory extension is available.
210 * Return: 0 = not available
211 * 1 = shared XImage support available
212 * 2 = shared Pixmap support available also
214 #ifndef XFree86Server
215 static int check_for_xshm( XMesaDisplay
*display
)
218 int major
, minor
, ignore
;
221 if (XQueryExtension( display
, "MIT-SHM", &ignore
, &ignore
, &ignore
)) {
222 if (XShmQueryVersion( display
, &major
, &minor
, &pixmaps
)==True
) {
223 return (pixmaps
==True
) ? 2 : 1;
233 /* Can't compile XSHM support */
241 * Return the width and height of the given drawable.
243 static void get_drawable_size( XMesaDisplay
*dpy
, XMesaDrawable d
,
244 unsigned int *width
, unsigned int *height
)
253 unsigned int bw
, depth
;
255 _glthread_LOCK_MUTEX(_xmesa_lock
);
256 XGetGeometry( dpy
, d
, &root
, &x
, &y
, width
, height
, &bw
, &depth
);
257 _glthread_UNLOCK_MUTEX(_xmesa_lock
);
263 * Apply gamma correction to an intensity value in [0..max]. Return the
264 * new intensity value.
266 static GLint
gamma_adjust( GLfloat gamma
, GLint value
, GLint max
)
272 double x
= (double) value
/ (double) max
;
273 return IROUND_POS((GLfloat
) max
* pow(x
, 1.0F
/gamma
));
280 * Return the true number of bits per pixel for XImages.
281 * For example, if we request a 24-bit deep visual we may actually need/get
282 * 32bpp XImages. This function returns the appropriate bpp.
283 * Input: dpy - the X display
284 * visinfo - desribes the visual to be used for XImages
285 * Return: true number of bits per pixel for XImages
289 static int bits_per_pixel( XMesaVisual xmv
)
291 XMesaVisualInfo visinfo
= xmv
->visinfo
;
292 const int depth
= visinfo
->nplanes
;
294 for (i
= 0; i
< screenInfo
.numPixmapFormats
; i
++) {
295 if (screenInfo
.formats
[i
].depth
== depth
)
296 return screenInfo
.formats
[i
].bitsPerPixel
;
298 return depth
; /* should never get here, but this should be safe */
303 static int bits_per_pixel( XMesaVisual xmv
)
305 XMesaDisplay
*dpy
= xmv
->display
;
306 XMesaVisualInfo visinfo
= xmv
->visinfo
;
309 /* Create a temporary XImage */
310 img
= XCreateImage( dpy
, visinfo
->visual
, visinfo
->depth
,
311 ZPixmap
, 0, /*format, offset*/
312 (char*) MALLOC(8), /*data*/
313 1, 1, /*width, height*/
318 /* grab the bits/pixel value */
319 bitsPerPixel
= img
->bits_per_pixel
;
320 /* free the XImage */
323 XMesaDestroyImage( img
);
331 * Determine if a given X window ID is valid (window exists).
332 * Do this by calling XGetWindowAttributes() for the window and
333 * checking if we catch an X error.
334 * Input: dpy - the display
335 * win - the window to check for existance
336 * Return: GL_TRUE - window exists
337 * GL_FALSE - window doesn't exist
339 #ifndef XFree86Server
340 static GLboolean WindowExistsFlag
;
342 static int window_exists_err_handler( XMesaDisplay
* dpy
, XErrorEvent
* xerr
)
345 if (xerr
->error_code
== BadWindow
) {
346 WindowExistsFlag
= GL_FALSE
;
351 static GLboolean
window_exists( XMesaDisplay
*dpy
, Window win
)
353 XWindowAttributes wa
;
354 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
355 WindowExistsFlag
= GL_TRUE
;
356 old_handler
= XSetErrorHandler(window_exists_err_handler
);
357 XGetWindowAttributes( dpy
, win
, &wa
); /* dummy request */
358 XSetErrorHandler(old_handler
);
359 return WindowExistsFlag
;
365 /**********************************************************************/
366 /***** Linked list of XMesaBuffers *****/
367 /**********************************************************************/
369 static XMesaBuffer XMesaBufferList
= NULL
;
372 /* Allocate a new XMesaBuffer, add to linked list */
373 static XMesaBuffer
alloc_xmesa_buffer(void)
375 XMesaBuffer b
= (XMesaBuffer
) CALLOC_STRUCT(xmesa_buffer
);
377 b
->Next
= XMesaBufferList
;
385 * Find an XMesaBuffer by matching X display and colormap but NOT matching
386 * the notThis buffer.
388 static XMesaBuffer
find_xmesa_buffer(XMesaDisplay
*dpy
,
393 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
394 if (b
->display
==dpy
&& b
->cmap
==cmap
&& b
!=notThis
) {
403 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
406 static void free_xmesa_buffer(int client
, XMesaBuffer buffer
)
408 XMesaBuffer prev
= NULL
, b
;
410 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
412 /* unlink bufer from list */
414 prev
->Next
= buffer
->Next
;
416 XMesaBufferList
= buffer
->Next
;
417 /* Check to free X colors */
418 if (buffer
->num_alloced
>0) {
419 /* If no other buffer uses this X colormap then free the colors. */
420 if (!find_xmesa_buffer(buffer
->display
, buffer
->cmap
, buffer
)) {
422 (void)FreeColors(buffer
->cmap
, client
,
423 buffer
->num_alloced
, buffer
->alloced_colors
,
426 XFreeColors(buffer
->display
, buffer
->cmap
,
427 buffer
->alloced_colors
, buffer
->num_alloced
, 0);
432 _mesa_free_framebuffer_data(&buffer
->mesa_buffer
);
437 /* continue search */
440 /* buffer not found in XMesaBufferList */
441 _mesa_problem(NULL
,"free_xmesa_buffer() - buffer not found\n");
445 /* Copy X color table stuff from one XMesaBuffer to another. */
446 static void copy_colortable_info(XMesaBuffer dst
, const XMesaBuffer src
)
448 MEMCPY(dst
->color_table
, src
->color_table
, sizeof(src
->color_table
));
449 MEMCPY(dst
->pixel_to_r
, src
->pixel_to_r
, sizeof(src
->pixel_to_r
));
450 MEMCPY(dst
->pixel_to_g
, src
->pixel_to_g
, sizeof(src
->pixel_to_g
));
451 MEMCPY(dst
->pixel_to_b
, src
->pixel_to_b
, sizeof(src
->pixel_to_b
));
452 dst
->num_alloced
= src
->num_alloced
;
453 MEMCPY(dst
->alloced_colors
, src
->alloced_colors
,
454 sizeof(src
->alloced_colors
));
459 /**********************************************************************/
460 /***** Misc Private Functions *****/
461 /**********************************************************************/
465 * Return number of bits set in n.
467 static int bitcount( unsigned long n
)
470 for (bits
=0; n
>0; n
=n
>>1) {
481 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
482 * Return: GL_TRUE if success, GL_FALSE if error
484 #ifndef XFree86Server
485 static GLboolean
alloc_shm_back_buffer( XMesaBuffer b
)
489 * We have to do a _lot_ of error checking here to be sure we can
490 * really use the XSHM extension. It seems different servers trigger
491 * errors at different points if the extension won't work. Therefore
492 * we have to be very careful...
495 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
497 b
->backimage
= XShmCreateImage( b
->xm_visual
->display
,
498 b
->xm_visual
->visinfo
->visual
,
499 b
->xm_visual
->visinfo
->depth
,
500 ZPixmap
, NULL
, &b
->shminfo
,
501 b
->width
, b
->height
);
502 if (b
->backimage
== NULL
) {
503 error("alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
508 b
->shminfo
.shmid
= shmget( IPC_PRIVATE
, b
->backimage
->bytes_per_line
509 * b
->backimage
->height
, IPC_CREAT
|0777 );
510 if (b
->shminfo
.shmid
< 0) {
511 if (getenv("MESA_DEBUG"))
512 perror("alloc_back_buffer");
513 XDestroyImage( b
->backimage
);
515 error("alloc_back_buffer: Shared memory error (shmget), disabling.");
520 b
->shminfo
.shmaddr
= b
->backimage
->data
521 = (char*)shmat( b
->shminfo
.shmid
, 0, 0 );
522 if (b
->shminfo
.shmaddr
== (char *) -1) {
523 if (getenv("MESA_DEBUG"))
524 perror("alloc_back_buffer");
525 XDestroyImage( b
->backimage
);
526 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
528 error("alloc_back_buffer: Shared memory error (shmat), disabling.");
533 b
->shminfo
.readOnly
= False
;
535 old_handler
= XSetErrorHandler( mesaHandleXError
);
536 /* This may trigger the X protocol error we're ready to catch: */
537 XShmAttach( b
->xm_visual
->display
, &b
->shminfo
);
538 XSync( b
->xm_visual
->display
, False
);
540 if (mesaXErrorFlag
) {
541 /* we are on a remote display, this error is normal, don't print it */
542 XFlush( b
->xm_visual
->display
);
544 XDestroyImage( b
->backimage
);
545 shmdt( b
->shminfo
.shmaddr
);
546 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
549 (void) XSetErrorHandler( old_handler
);
553 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 ); /* nobody else needs it */
555 /* Finally, try an XShmPutImage to be really sure the extension works */
556 gc
= XCreateGC( b
->xm_visual
->display
, b
->frontbuffer
, 0, NULL
);
557 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
, gc
,
558 b
->backimage
, 0, 0, 0, 0, 1, 1 /*one pixel*/, False
);
559 XSync( b
->xm_visual
->display
, False
);
560 XFreeGC( b
->xm_visual
->display
, gc
);
561 (void) XSetErrorHandler( old_handler
);
562 if (mesaXErrorFlag
) {
563 XFlush( b
->xm_visual
->display
);
565 XDestroyImage( b
->backimage
);
566 shmdt( b
->shminfo
.shmaddr
);
567 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
574 int height
= b
->backimage
->height
;
575 /* Needed by PIXELADDR1 macro */
576 b
->ximage_width1
= b
->backimage
->bytes_per_line
;
577 b
->ximage_origin1
= (GLubyte
*) b
->backimage
->data
578 + b
->ximage_width1
* (height
-1);
579 /* Needed by PIXELADDR2 macro */
580 b
->ximage_width2
= b
->backimage
->bytes_per_line
/ 2;
581 b
->ximage_origin2
= (GLushort
*) b
->backimage
->data
582 + b
->ximage_width2
* (height
-1);
583 /* Needed by PIXELADDR3 macro */
584 b
->ximage_width3
= b
->backimage
->bytes_per_line
;
585 b
->ximage_origin3
= (GLubyte
*) b
->backimage
->data
586 + b
->ximage_width3
* (height
-1);
587 /* Needed by PIXELADDR4 macro */
588 b
->ximage_width4
= b
->backimage
->width
;
589 b
->ximage_origin4
= (GLuint
*) b
->backimage
->data
590 + b
->ximage_width4
* (height
-1);
595 /* Can't compile XSHM support */
604 * Setup an off-screen pixmap or Ximage to use as the back buffer.
605 * Input: b - the X/Mesa buffer
607 void xmesa_alloc_back_buffer( XMesaBuffer b
)
609 if (b
->db_state
==BACK_XIMAGE
) {
610 /* Deallocate the old backimage, if any */
612 #if defined(USE_XSHM) && !defined(XFree86Server)
614 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
615 XDestroyImage( b
->backimage
);
616 shmdt( b
->shminfo
.shmaddr
);
620 XMesaDestroyImage( b
->backimage
);
624 /* Allocate new back buffer */
627 /* Allocate a regular XImage for the back buffer. */
628 b
->backimage
= XMesaCreateImage(b
->xm_visual
->BitsPerPixel
,
629 b
->width
, b
->height
, NULL
);
631 if (b
->shm
==0 || alloc_shm_back_buffer(b
)==GL_FALSE
) {
632 /* Allocate a regular XImage for the back buffer. */
633 b
->backimage
= XCreateImage( b
->xm_visual
->display
,
634 b
->xm_visual
->visinfo
->visual
,
635 GET_VISUAL_DEPTH(b
->xm_visual
),
636 ZPixmap
, 0, /* format, offset */
637 NULL
, b
->width
, b
->height
,
638 8, 0 ); /* pad, bytes_per_line */
641 error("alloc_back_buffer: XCreateImage failed.");
643 b
->backimage
->data
= (char *) MALLOC( b
->backimage
->height
644 * b
->backimage
->bytes_per_line
);
645 if (!b
->backimage
->data
) {
646 error("alloc_back_buffer: MALLOC failed.");
647 XMesaDestroyImage( b
->backimage
);
651 b
->backpixmap
= None
;
653 else if (b
->db_state
==BACK_PIXMAP
) {
654 XMesaPixmap old_pixmap
= b
->backpixmap
;
655 /* Free the old back pixmap */
657 XMesaFreePixmap( b
->xm_visual
->display
, b
->backpixmap
);
659 /* Allocate new back pixmap */
660 b
->backpixmap
= XMesaCreatePixmap( b
->xm_visual
->display
, b
->frontbuffer
,
662 GET_VISUAL_DEPTH(b
->xm_visual
) );
664 /* update other references to backpixmap */
665 if (b
->buffer
==(XMesaDrawable
)old_pixmap
) {
666 b
->buffer
= (XMesaDrawable
)b
->backpixmap
;
674 * A replacement for XAllocColor. This function should never
675 * fail to allocate a color. When XAllocColor fails, we return
676 * the nearest matching color. If we have to allocate many colors
677 * this function isn't too efficient; the XQueryColors() could be
679 * Written by Michael Pichler, Brian Paul, Mark Kilgard
680 * Input: dpy - X display
682 * cmapSize - size of colormap
683 * In/Out: color - the XColor struct
684 * Output: exact - 1=exact color match, 0=closest match
685 * alloced - 1=XAlloc worked, 0=XAlloc failed
688 noFaultXAllocColor( int client
,
693 int *exact
, int *alloced
)
699 /* we'll try to cache ctable for better remote display performance */
700 static Display
*prevDisplay
= NULL
;
701 static XMesaColormap prevCmap
= 0;
702 static int prevCmapSize
= 0;
703 static XMesaColor
*ctable
= NULL
;
707 double mindist
; /* 3*2^16^2 exceeds long int precision. */
711 /* First try just using XAllocColor. */
714 &color
->red
, &color
->green
, &color
->blue
,
716 client
) == Success
) {
718 if (XAllocColor(dpy
, cmap
, color
)) {
725 /* Alloc failed, search for closest match */
727 /* Retrieve color table entries. */
728 /* XXX alloca candidate. */
730 ppixIn
= (Pixel
*) MALLOC(cmapSize
* sizeof(Pixel
));
731 ctable
= (xrgb
*) MALLOC(cmapSize
* sizeof(xrgb
));
732 for (i
= 0; i
< cmapSize
; i
++) {
735 QueryColors(cmap
, cmapSize
, ppixIn
, ctable
);
737 if (prevDisplay
!= dpy
|| prevCmap
!= cmap
738 || prevCmapSize
!= cmapSize
|| !ctable
) {
739 /* free previously cached color table */
742 /* Get the color table from X */
743 ctable
= (XMesaColor
*) MALLOC(cmapSize
* sizeof(XMesaColor
));
745 for (i
= 0; i
< cmapSize
; i
++) {
748 XQueryColors(dpy
, cmap
, ctable
, cmapSize
);
751 prevCmapSize
= cmapSize
;
755 /* Find best match. */
758 for (i
= 0; i
< cmapSize
; i
++) {
759 double dr
= 0.30 * ((double) color
->red
- (double) ctable
[i
].red
);
760 double dg
= 0.59 * ((double) color
->green
- (double) ctable
[i
].green
);
761 double db
= 0.11 * ((double) color
->blue
- (double) ctable
[i
].blue
);
762 double dist
= dr
* dr
+ dg
* dg
+ db
* db
;
763 if (bestmatch
< 0 || dist
< mindist
) {
770 subColor
.red
= ctable
[bestmatch
].red
;
771 subColor
.green
= ctable
[bestmatch
].green
;
772 subColor
.blue
= ctable
[bestmatch
].blue
;
773 /* Try to allocate the closest match color. This should only
774 * fail if the cell is read/write. Otherwise, we're incrementing
775 * the cell's reference count.
779 &subColor
.red
, &subColor
.green
, &subColor
.blue
,
781 client
) == Success
) {
783 if (XAllocColor(dpy
, cmap
, &subColor
)) {
788 /* do this to work around a problem reported by Frank Ortega */
789 subColor
.pixel
= (unsigned long) bestmatch
;
790 subColor
.red
= ctable
[bestmatch
].red
;
791 subColor
.green
= ctable
[bestmatch
].green
;
792 subColor
.blue
= ctable
[bestmatch
].blue
;
793 subColor
.flags
= DoRed
| DoGreen
| DoBlue
;
800 /* don't free table, save it for next time */
811 * Do setup for PF_GRAYSCALE pixel format.
812 * Note that buffer may be NULL.
814 static GLboolean
setup_grayscale( int client
, XMesaVisual v
,
815 XMesaBuffer buffer
, XMesaColormap cmap
)
817 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
822 XMesaBuffer prevBuffer
;
828 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
830 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
831 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
832 /* Copy colormap stuff from previous XMesaBuffer which uses same
833 * X colormap. Do this to avoid time spent in noFaultXAllocColor.
835 copy_colortable_info(buffer
, prevBuffer
);
838 /* Allocate 256 shades of gray */
840 int colorsfailed
= 0;
841 for (gray
=0;gray
<256;gray
++) {
842 GLint r
= gamma_adjust( v
->RedGamma
, gray
, 255 );
843 GLint g
= gamma_adjust( v
->GreenGamma
, gray
, 255 );
844 GLint b
= gamma_adjust( v
->BlueGamma
, gray
, 255 );
847 xcol
.red
= (r
<< 8) | r
;
848 xcol
.green
= (g
<< 8) | g
;
849 xcol
.blue
= (b
<< 8) | b
;
850 noFaultXAllocColor( client
, v
->display
,
851 cmap
, GET_COLORMAP_SIZE(v
),
852 &xcol
, &exact
, &alloced
);
857 assert(buffer
->num_alloced
<256);
858 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
859 buffer
->num_alloced
++;
864 buffer->color_table[gray*3+0] = xcol.pixel;
865 buffer->color_table[gray*3+1] = xcol.pixel;
866 buffer->color_table[gray*3+2] = xcol.pixel;
867 assert(xcol.pixel < 65536);
868 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
869 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
870 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
872 buffer
->color_table
[gray
] = xcol
.pixel
;
873 assert(xcol
.pixel
< 65536);
874 buffer
->pixel_to_r
[xcol
.pixel
] = gray
;
875 buffer
->pixel_to_g
[xcol
.pixel
] = gray
;
876 buffer
->pixel_to_b
[xcol
.pixel
] = gray
;
879 if (colorsfailed
&& getenv("MESA_DEBUG")) {
881 "Note: %d out of 256 needed colors do not match exactly.\n",
887 v
->dithered_pf
= PF_GRAYSCALE
;
888 v
->undithered_pf
= PF_GRAYSCALE
;
895 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
896 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
897 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
898 * color. While this function was originally designed just for 8-bit
899 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
900 * Dithering code contributed by Bob Mercier.
902 static GLboolean
setup_dithered_color( int client
, XMesaVisual v
,
903 XMesaBuffer buffer
, XMesaColormap cmap
)
905 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
910 XMesaBuffer prevBuffer
;
916 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
918 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
919 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
920 /* Copy colormap stuff from previous, matching XMesaBuffer.
921 * Do this to avoid time spent in noFaultXAllocColor.
923 copy_colortable_info(buffer
, prevBuffer
);
926 /* Allocate X colors and initialize color_table[], red_table[], etc */
928 int colorsfailed
= 0;
929 for (r
= 0; r
< _R
; r
++) {
930 for (g
= 0; g
< _G
; g
++) {
931 for (b
= 0; b
< _B
; b
++) {
934 xcol
.red
=gamma_adjust(v
->RedGamma
, r
*65535/(_R
-1),65535);
935 xcol
.green
=gamma_adjust(v
->GreenGamma
, g
*65535/(_G
-1),65535);
936 xcol
.blue
=gamma_adjust(v
->BlueGamma
, b
*65535/(_B
-1),65535);
937 noFaultXAllocColor( client
, v
->display
,
938 cmap
, GET_COLORMAP_SIZE(v
),
939 &xcol
, &exact
, &alloced
);
944 assert(buffer
->num_alloced
<256);
945 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
946 buffer
->num_alloced
++;
950 buffer
->color_table
[i
] = xcol
.pixel
;
951 assert(xcol
.pixel
< 65536);
952 buffer
->pixel_to_r
[xcol
.pixel
] = r
* 255 / (_R
-1);
953 buffer
->pixel_to_g
[xcol
.pixel
] = g
* 255 / (_G
-1);
954 buffer
->pixel_to_b
[xcol
.pixel
] = b
* 255 / (_B
-1);
959 if (colorsfailed
&& getenv("MESA_DEBUG")) {
961 "Note: %d out of %d needed colors do not match exactly.\n",
962 colorsfailed
, _R
*_G
*_B
);
967 v
->dithered_pf
= PF_DITHER
;
968 v
->undithered_pf
= PF_LOOKUP
;
974 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
975 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
976 * Special dithering tables have to be initialized.
978 static void setup_8bit_hpcr( XMesaVisual v
)
980 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be)
981 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
982 * on the root window AND the colormap obtainable by XGetRGBColormaps
983 * for that atom must be set on the window. (see also tkInitWindow)
984 * If that colormap is not set, the output will look stripy.
987 /* Setup color tables with gamma correction */
991 g
= 1.0 / v
->RedGamma
;
992 for (i
=0; i
<256; i
++) {
993 GLint red
= IROUND_POS(255.0 * pow( hpcr_rgbTbl
[0][i
]/255.0, g
));
994 v
->hpcr_rgbTbl
[0][i
] = CLAMP( red
, 16, 239 );
997 g
= 1.0 / v
->GreenGamma
;
998 for (i
=0; i
<256; i
++) {
999 GLint green
= IROUND_POS(255.0 * pow( hpcr_rgbTbl
[1][i
]/255.0, g
));
1000 v
->hpcr_rgbTbl
[1][i
] = CLAMP( green
, 16, 239 );
1003 g
= 1.0 / v
->BlueGamma
;
1004 for (i
=0; i
<256; i
++) {
1005 GLint blue
= IROUND_POS(255.0 * pow( hpcr_rgbTbl
[2][i
]/255.0, g
));
1006 v
->hpcr_rgbTbl
[2][i
] = CLAMP( blue
, 32, 223 );
1008 v
->undithered_pf
= PF_HPCR
; /* can't really disable dithering for now */
1009 v
->dithered_pf
= PF_HPCR
;
1011 /* which method should I use to clear */
1012 /* GL_FALSE: keep the ordinary method */
1013 /* GL_TRUE : clear with dither pattern */
1014 v
->hpcr_clear_flag
= getenv("MESA_HPCR_CLEAR") ? GL_TRUE
: GL_FALSE
;
1016 if (v
->hpcr_clear_flag
) {
1017 v
->hpcr_clear_pixmap
= XMesaCreatePixmap(v
->display
,
1018 DefaultRootWindow(v
->display
),
1020 #ifndef XFree86Server
1021 v
->hpcr_clear_ximage
= XGetImage(v
->display
, v
->hpcr_clear_pixmap
,
1022 0, 0, 16, 2, AllPlanes
, ZPixmap
);
1029 * Setup RGB rendering for a window with a True/DirectColor visual.
1031 static void setup_truecolor( XMesaVisual v
, XMesaBuffer buffer
,
1032 XMesaColormap cmap
)
1034 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
,
1197 XMesaColormap cmap
)
1199 #ifndef XFree86Server
1204 assert(b
->xm_visual
== v
);
1207 /* Save true bits/pixel */
1208 v
->BitsPerPixel
= bits_per_pixel(v
);
1209 assert(v
->BitsPerPixel
> 0);
1212 if (rgb_flag
==GL_FALSE
) {
1213 /* COLOR-INDEXED WINDOW:
1214 * Even if the visual is TrueColor or DirectColor we treat it as
1215 * being color indexed. This is weird but might be useful to someone.
1217 v
->dithered_pf
= v
->undithered_pf
= PF_INDEX
;
1218 v
->index_bits
= GET_VISUAL_DEPTH(v
);
1222 * We support RGB rendering into almost any kind of visual.
1225 xclass
= GET_VISUAL_CLASS(v
);
1226 if (xclass
==TrueColor
|| xclass
==DirectColor
) {
1227 setup_truecolor( v
, b
, cmap
);
1229 else if (xclass
==StaticGray
&& GET_VISUAL_DEPTH(v
)==1) {
1230 setup_monochrome( v
, b
);
1232 else if (xclass
==GrayScale
|| xclass
==StaticGray
) {
1233 if (!setup_grayscale( client
, v
, b
, cmap
)) {
1237 else if ((xclass
==PseudoColor
|| xclass
==StaticColor
)
1238 && GET_VISUAL_DEPTH(v
)>=4 && GET_VISUAL_DEPTH(v
)<=16) {
1239 if (!setup_dithered_color( client
, v
, b
, cmap
)) {
1244 error("XMesa: RGB mode rendering not supported in given visual.");
1249 if (getenv("MESA_NO_DITHER")) {
1250 v
->dithered_pf
= v
->undithered_pf
;
1256 * If MESA_INFO env var is set print out some debugging info
1257 * which can help Brian figure out what's going on when a user
1260 if (getenv("MESA_INFO")) {
1261 fprintf(stderr
, "X/Mesa visual = %p\n", (void *) v
);
1262 fprintf(stderr
, "X/Mesa dithered pf = %u\n", v
->dithered_pf
);
1263 fprintf(stderr
, "X/Mesa undithered pf = %u\n", v
->undithered_pf
);
1264 fprintf(stderr
, "X/Mesa level = %d\n", v
->level
);
1265 fprintf(stderr
, "X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v
));
1266 fprintf(stderr
, "X/Mesa bits per pixel = %d\n", v
->BitsPerPixel
);
1270 /* Do window-specific initializations */
1272 /* Window dimensions */
1274 get_drawable_size( v
->display
, window
, &w
, &h
);
1278 b
->frontbuffer
= window
;
1280 /* Setup for single/double buffering */
1281 if (v
->mesa_visual
.doubleBufferMode
) {
1282 /* Double buffered */
1283 #ifndef XFree86Server
1284 b
->shm
= check_for_xshm( v
->display
);
1286 xmesa_alloc_back_buffer( b
);
1287 if (b
->db_state
==BACK_PIXMAP
) {
1288 b
->buffer
= (XMesaDrawable
)b
->backpixmap
;
1295 /* Single Buffered */
1296 b
->buffer
= b
->frontbuffer
;
1299 /* X11 graphics contexts */
1300 #ifdef XFree86Server
1301 b
->gc
= CreateScratchGC(v
->display
, window
->depth
);
1303 b
->gc
= XCreateGC( v
->display
, window
, 0, NULL
);
1305 XMesaSetFunction( v
->display
, b
->gc
, GXcopy
);
1307 /* cleargc - for glClear() */
1308 #ifdef XFree86Server
1309 b
->cleargc
= CreateScratchGC(v
->display
, window
->depth
);
1311 b
->cleargc
= XCreateGC( v
->display
, window
, 0, NULL
);
1313 XMesaSetFunction( v
->display
, b
->cleargc
, GXcopy
);
1316 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1317 * Patch contributed by Michael Pichler May 15, 1995.
1319 #ifdef XFree86Server
1320 b
->swapgc
= CreateScratchGC(v
->display
, window
->depth
);
1324 dixChangeGC(NullClient
, b
->swapgc
, GCGraphicsExposures
, v
, NULL
);
1327 gcvalues
.graphics_exposures
= False
;
1328 b
->swapgc
= XCreateGC( v
->display
, window
,
1329 GCGraphicsExposures
, &gcvalues
);
1331 XMesaSetFunction( v
->display
, b
->swapgc
, GXcopy
);
1333 * Set fill style and tile pixmap once for all for HPCR stuff
1334 * (instead of doing it each time in clear_color_HPCR_pixmap())
1335 * Initialize whole stuff
1336 * Patch contributed by Jacques Leroy March 8, 1998.
1338 if (v
->hpcr_clear_flag
&& b
->buffer
!=XIMAGE
) {
1340 for (i
=0; i
<16; i
++)
1342 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 0, 0);
1343 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 1, 0);
1345 XMesaPutImage(b
->display
, (XMesaDrawable
)v
->hpcr_clear_pixmap
,
1346 b
->cleargc
, v
->hpcr_clear_ximage
, 0, 0, 0, 0, 16, 2);
1347 XMesaSetFillStyle( v
->display
, b
->cleargc
, FillTiled
);
1348 XMesaSetTile( v
->display
, b
->cleargc
, v
->hpcr_clear_pixmap
);
1351 /* Initialize the row buffer XImage for use in write_color_span() */
1352 #ifdef XFree86Server
1353 b
->rowimage
= XMesaCreateImage(GET_VISUAL_DEPTH(v
), MAX_WIDTH
, 1,
1354 (char *)MALLOC(MAX_WIDTH
*4));
1356 b
->rowimage
= XCreateImage( v
->display
,
1359 ZPixmap
, 0, /*format, offset*/
1360 (char*) MALLOC(MAX_WIDTH
*4), /*data*/
1361 MAX_WIDTH
, 1, /*width, height*/
1363 0 /*bytes_per_line*/ );
1373 * Convert an RGBA color to a pixel value.
1376 xmesa_color_to_pixel( XMesaContext xmesa
, GLubyte r
, GLubyte g
, GLubyte b
, GLubyte a
,
1379 switch (pixelFormat
) {
1385 PACK_TRUECOLOR( p
, r
, g
, b
);
1389 return PACK_8A8B8G8R( r
, g
, b
, a
);
1393 return PACK_8R8G8B( r
, g
, b
);
1395 return PACK_5R6G5B( r
, g
, b
);
1399 return DITHER( 1, 0, r
, g
, b
);
1402 /* 382 = (3*255)/2 */
1403 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
1405 return DITHER_HPCR(1, 1, r
, g
, b
);
1409 return LOOKUP( r
, g
, b
);
1412 return GRAY_RGB( r
, g
, b
);
1415 case PF_DITHER_5R6G5B
:
1418 PACK_TRUEDITHER(p
, 1, 0, r
, g
, b
);
1422 _mesa_problem(NULL
, "Bad pixel format in xmesa_color_to_pixel");
1428 /**********************************************************************/
1429 /***** Public Functions *****/
1430 /**********************************************************************/
1434 * Create a new X/Mesa visual.
1435 * Input: display - X11 display
1436 * visinfo - an XVisualInfo pointer
1437 * rgb_flag - GL_TRUE = RGB mode,
1438 * GL_FALSE = color index mode
1439 * alpha_flag - alpha buffer requested?
1440 * db_flag - GL_TRUE = double-buffered,
1441 * GL_FALSE = single buffered
1442 * stereo_flag - stereo visual?
1443 * ximage_flag - GL_TRUE = use an XImage for back buffer,
1444 * GL_FALSE = use an off-screen pixmap for back buffer
1445 * depth_size - requested bits/depth values, or zero
1446 * stencil_size - requested bits/stencil values, or zero
1447 * accum_red_size - requested bits/red accum values, or zero
1448 * accum_green_size - requested bits/green accum values, or zero
1449 * accum_blue_size - requested bits/blue accum values, or zero
1450 * accum_alpha_size - requested bits/alpha accum values, or zero
1451 * num_samples - number of samples/pixel if multisampling, or zero
1452 * level - visual level, usually 0
1453 * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT
1454 * Return; a new XMesaVisual or 0 if error.
1456 XMesaVisual
XMesaCreateVisual( XMesaDisplay
*display
,
1457 XMesaVisualInfo visinfo
,
1459 GLboolean alpha_flag
,
1461 GLboolean stereo_flag
,
1462 GLboolean ximage_flag
,
1465 GLint accum_red_size
,
1466 GLint accum_green_size
,
1467 GLint accum_blue_size
,
1468 GLint accum_alpha_size
,
1471 GLint visualCaveat
)
1475 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1477 /* For debugging only */
1478 if (getenv("MESA_XSYNC")) {
1479 /* This makes debugging X easier.
1480 * In your debugger, set a breakpoint on _XError to stop when an
1481 * X protocol error is generated.
1483 #ifdef XFree86Server
1486 XSynchronize( display
, 1 );
1490 v
= (XMesaVisual
) CALLOC_STRUCT(xmesa_visual
);
1496 * In the X server, NULL is passed in for the display. It will have
1497 * to be set before using this visual. See XMesaSetVisualDisplay()
1500 v
->display
= display
;
1502 /* Save a copy of the XVisualInfo struct because the user may XFREE()
1503 * the struct but we may need some of the information contained in it
1506 #ifdef XFree86Server
1507 v
->visinfo
= visinfo
;
1509 v
->visinfo
= (XVisualInfo
*) MALLOC(sizeof(*visinfo
));
1514 MEMCPY(v
->visinfo
, visinfo
, sizeof(*visinfo
));
1516 /* Save a copy of the pointer now so we can find this visual again
1517 * if we need to search for it in find_glx_visual().
1519 v
->vishandle
= visinfo
;
1522 #ifdef XFree86Server
1523 /* Initialize the depth of the screen */
1525 PixmapFormatRec
*format
;
1527 for (format
= screenInfo
.formats
;
1528 format
->depth
!= display
->rootDepth
;
1531 v
->screen_depth
= format
->bitsPerPixel
;
1535 /* check for MESA_GAMMA environment variable */
1536 gamma
= getenv("MESA_GAMMA");
1538 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 0.0;
1539 sscanf( gamma
, "%f %f %f", &v
->RedGamma
, &v
->GreenGamma
, &v
->BlueGamma
);
1540 if (v
->RedGamma
<=0.0) v
->RedGamma
= 1.0;
1541 if (v
->GreenGamma
<=0.0) v
->GreenGamma
= v
->RedGamma
;
1542 if (v
->BlueGamma
<=0.0) v
->BlueGamma
= v
->RedGamma
;
1545 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 1.0;
1548 v
->ximage_flag
= ximage_flag
;
1550 v
->VisualCaveat
= visualCaveat
;
1552 (void) initialize_visual_and_buffer( 0, v
, NULL
, rgb_flag
, 0, 0 );
1556 xclass
= GET_VISUAL_CLASS(v
);
1557 if (xclass
==TrueColor
|| xclass
==DirectColor
) {
1558 red_bits
= bitcount(GET_REDMASK(v
));
1559 green_bits
= bitcount(GET_GREENMASK(v
));
1560 blue_bits
= bitcount(GET_BLUEMASK(v
));
1564 /* this is an approximation */
1566 depth
= GET_VISUAL_DEPTH(v
);
1567 red_bits
= depth
/ 3;
1569 green_bits
= depth
/ 2;
1570 depth
-= green_bits
;
1573 assert( red_bits
+ green_bits
+ blue_bits
== GET_VISUAL_DEPTH(v
) );
1577 if (alpha_flag
&& alpha_bits
== 0)
1580 _mesa_initialize_visual( &v
->mesa_visual
,
1581 rgb_flag
, db_flag
, stereo_flag
,
1582 red_bits
, green_bits
,
1583 blue_bits
, alpha_bits
,
1587 accum_red_size
, accum_green_size
,
1588 accum_blue_size
, accum_alpha_size
,
1594 void XMesaSetVisualDisplay( XMesaDisplay
*dpy
, XMesaVisual v
)
1600 void XMesaDestroyVisual( XMesaVisual v
)
1602 #ifndef XFree86Server
1611 * Create a new XMesaContext.
1612 * Input: v - XMesaVisual
1613 * share_list - another XMesaContext with which to share display
1614 * lists or NULL if no sharing is wanted.
1615 * Return: an XMesaContext or NULL if error.
1617 XMesaContext
XMesaCreateContext( XMesaVisual v
, XMesaContext share_list
)
1619 static GLboolean firstTime
= GL_TRUE
;
1622 __GLimports imports
;
1625 _glthread_INIT_MUTEX(_xmesa_lock
);
1626 firstTime
= GL_FALSE
;
1629 c
= (XMesaContext
) CALLOC_STRUCT(xmesa_context
);
1634 _mesa_init_default_imports( &imports
, (void *) c
);
1635 ctx
= c
->gl_ctx
= _mesa_create_context( &v
->mesa_visual
,
1636 share_list
? share_list
->gl_ctx
: (GLcontext
*) NULL
,
1643 _mesa_enable_sw_extensions(ctx
);
1644 _mesa_enable_1_3_extensions(ctx
);
1645 /*_mesa_enable_1_4_extensions(ctx);*/
1647 if (CHECK_BYTE_ORDER(v
)) {
1648 c
->swapbytes
= GL_FALSE
;
1651 c
->swapbytes
= GL_TRUE
;
1655 c
->xm_draw_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1656 c
->xm_read_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1657 c
->xm_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1658 c
->display
= v
->display
;
1659 c
->pixelformat
= v
->dithered_pf
; /* Dithering is enabled by default */
1661 ctx
->Driver
.UpdateState
= xmesa_update_state
;
1663 /* Initialize the software rasterizer and helper modules.
1665 _swrast_CreateContext( ctx
);
1666 _ac_CreateContext( ctx
);
1667 _tnl_CreateContext( ctx
);
1668 _swsetup_CreateContext( ctx
);
1670 xmesa_register_swrast_functions( ctx
);
1672 /* Set up some constant pointers:
1674 xmesa_init_pointers( ctx
);
1682 void XMesaDestroyContext( XMesaContext c
)
1685 if (c
->xm_draw_buffer
&& c
->xm_buffer
->FXctx
)
1686 fxMesaDestroyContext(c
->xm_draw_buffer
->FXctx
);
1689 _swsetup_DestroyContext( c
->gl_ctx
);
1690 _swrast_DestroyContext( c
->gl_ctx
);
1691 _tnl_DestroyContext( c
->gl_ctx
);
1692 _ac_DestroyContext( c
->gl_ctx
);
1693 _mesa_destroy_context( c
->gl_ctx
);
1702 * XXX this isn't a public function! It's a hack for the 3Dfx driver.
1703 * Create a new XMesaBuffer from an X window.
1704 * Input: v - the XMesaVisual
1707 * Return: new XMesaBuffer or NULL if error
1709 XMesaBuffer
XMesaCreateWindowBuffer2( XMesaVisual v
, XMesaWindow w
,
1712 #ifndef XFree86Server
1713 XWindowAttributes attr
;
1720 XMesaBuffer b
= alloc_xmesa_buffer();
1727 #ifdef XFree86Server
1728 client
= CLIENT_ID(((XMesaDrawable
)w
)->id
);
1733 #ifdef XFree86Server
1734 if (GET_VISUAL_DEPTH(v
) != ((XMesaDrawable
)w
)->depth
) {
1736 XGetWindowAttributes( v
->display
, w
, &attr
);
1738 if (GET_VISUAL_DEPTH(v
) != attr
.depth
) {
1740 if (getenv("MESA_DEBUG")) {
1741 fprintf(stderr
, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n");
1748 b
->display
= v
->display
;
1749 #ifdef XFree86Server
1750 b
->cmap
= (ColormapPtr
)LookupIDByType(wColormap(w
), RT_COLORMAP
);
1752 if (attr
.colormap
) {
1753 b
->cmap
= attr
.colormap
;
1756 if (getenv("MESA_DEBUG")) {
1757 fprintf(stderr
, "Window %u has no colormap!\n", (unsigned int) w
);
1759 /* this is weird, a window w/out a colormap!? */
1760 /* OK, let's just allocate a new one and hope for the best */
1761 b
->cmap
= XCreateColormap(v
->display
, w
, attr
.visual
, AllocNone
);
1765 /* determine back buffer implementation */
1766 if (v
->mesa_visual
.doubleBufferMode
) {
1767 if (v
->ximage_flag
) {
1768 b
->db_state
= BACK_XIMAGE
;
1771 b
->db_state
= BACK_PIXMAP
;
1778 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
1780 v
->mesa_visual
.depthBits
> 0,
1781 v
->mesa_visual
.stencilBits
> 0,
1782 v
->mesa_visual
.accumRedBits
> 0,
1783 v
->mesa_visual
.alphaBits
> 0 );
1785 if (!initialize_visual_and_buffer( client
, v
, b
, v
->mesa_visual
.rgbMode
,
1786 (XMesaDrawable
)w
, b
->cmap
)) {
1787 free_xmesa_buffer(client
, b
);
1792 fxEnvVar
= getenv("MESA_GLX_FX");
1794 if (fxEnvVar
[0]!='d') {
1798 if (v
->mesa_visual
.depthBits
> 0) {
1799 attribs
[numAttribs
++] = FXMESA_DEPTH_SIZE
;
1800 attribs
[numAttribs
++] = 1;
1802 if (v
->mesa_visual
.doubleBufferMode
) {
1803 attribs
[numAttribs
++] = FXMESA_DOUBLEBUFFER
;
1805 if (v
->mesa_visual
.accumRedBits
> 0) {
1806 attribs
[numAttribs
++] = FXMESA_ACCUM_SIZE
;
1807 attribs
[numAttribs
++] = v
->mesa_visual
.accumRedBits
;
1809 if (v
->mesa_visual
.stencilBits
> 0) {
1810 attribs
[numAttribs
++] = FXMESA_STENCIL_SIZE
;
1811 attribs
[numAttribs
++] = v
->mesa_visual
.stencilBits
;
1813 if (v
->mesa_visual
.alphaBits
> 0) {
1814 attribs
[numAttribs
++] = FXMESA_ALPHA_SIZE
;
1815 attribs
[numAttribs
++] = 1;
1818 #define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with fxapi.c! */
1819 attribs
[numAttribs
++] = FXMESA_SHARE_CONTEXT
;
1820 attribs
[numAttribs
++] = (int) c
->gl_ctx
;
1822 attribs
[numAttribs
++] = FXMESA_NONE
;
1824 if ((hw
= fxQueryHardware())==GR_SSTTYPE_VOODOO
) {
1825 b
->FXctx
= fxMesaCreateBestContext(0, b
->width
, b
->height
, attribs
);
1826 if ((v
->undithered_pf
!=PF_INDEX
) && (b
->backimage
)) {
1827 b
->FXisHackUsable
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1828 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1829 b
->FXwindowHack
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1831 b
->FXwindowHack
= GL_FALSE
;
1835 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1836 b
->FXctx
= fxMesaCreateContext(w
, GR_RESOLUTION_NONE
,
1837 GR_REFRESH_75Hz
, attribs
);
1839 b
->FXctx
= fxMesaCreateBestContext(0, b
->width
, b
->height
, attribs
);
1840 b
->FXisHackUsable
= GL_FALSE
;
1841 b
->FXwindowHack
= GL_FALSE
;
1845 "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1846 hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
1851 fprintf(stderr
,"WARNING: This Mesa Library includes the Glide driver but\n");
1852 fprintf(stderr
," you have not defined the MESA_GLX_FX env. var.\n");
1853 fprintf(stderr
," (check the README.3DFX file for more information).\n\n");
1854 fprintf(stderr
," you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1862 XMesaBuffer
XMesaCreateWindowBuffer( XMesaVisual v
, XMesaWindow w
)
1864 return XMesaCreateWindowBuffer2( v
, w
, NULL
);
1869 * Create a new XMesaBuffer from an X pixmap.
1870 * Input: v - the XMesaVisual
1872 * cmap - the colormap, may be 0 if using a TrueColor or DirectColor
1873 * visual for the pixmap
1874 * Return: new XMesaBuffer or NULL if error
1876 XMesaBuffer
XMesaCreatePixmapBuffer( XMesaVisual v
,
1877 XMesaPixmap p
, XMesaColormap cmap
)
1880 XMesaBuffer b
= alloc_xmesa_buffer();
1886 #ifdef XFree86Server
1887 client
= CLIENT_ID(((XMesaDrawable
)p
)->id
);
1894 b
->display
= v
->display
;
1897 /* determine back buffer implementation */
1898 if (v
->mesa_visual
.doubleBufferMode
) {
1899 if (v
->ximage_flag
) {
1900 b
->db_state
= BACK_XIMAGE
;
1903 b
->db_state
= BACK_PIXMAP
;
1910 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
1912 v
->mesa_visual
.depthBits
> 0,
1913 v
->mesa_visual
.stencilBits
> 0,
1914 v
->mesa_visual
.accumRedBits
+
1915 v
->mesa_visual
.accumGreenBits
+
1916 v
->mesa_visual
.accumBlueBits
> 0,
1917 v
->mesa_visual
.alphaBits
> 0 );
1919 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1920 (XMesaDrawable
)p
, cmap
)) {
1921 free_xmesa_buffer(client
, b
);
1930 XMesaBuffer
XMesaCreatePBuffer( XMesaVisual v
, XMesaColormap cmap
,
1931 unsigned int width
, unsigned int height
)
1933 #ifdef XFree86Server
1938 XMesaDrawable drawable
; /* X Pixmap Drawable */
1939 XMesaBuffer b
= alloc_xmesa_buffer();
1946 b
->display
= v
->display
;
1949 /* allocate pixmap for front buffer */
1950 root
= RootWindow( v
->display
, v
->visinfo
->screen
);
1951 drawable
= XCreatePixmap( v
->display
, root
, width
, height
, v
->visinfo
->depth
);
1953 /* determine back buffer implementation */
1954 if (v
->mesa_visual
.doubleBufferMode
) {
1955 if (v
->ximage_flag
) {
1956 b
->db_state
= BACK_XIMAGE
;
1959 b
->db_state
= BACK_PIXMAP
;
1966 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
1968 v
->mesa_visual
.depthBits
> 0,
1969 v
->mesa_visual
.stencilBits
> 0,
1970 v
->mesa_visual
.accumRedBits
+
1971 v
->mesa_visual
.accumGreenBits
+
1972 v
->mesa_visual
.accumBlueBits
> 0,
1973 v
->mesa_visual
.alphaBits
> 0 );
1975 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1977 free_xmesa_buffer(client
, b
);
1988 * Deallocate an XMesaBuffer structure and all related info.
1990 void XMesaDestroyBuffer( XMesaBuffer b
)
1994 #ifdef XFree86Server
1996 client
= CLIENT_ID(b
->frontbuffer
->id
);
1999 if (b
->gc
) XMesaFreeGC( b
->xm_visual
->display
, b
->gc
);
2000 if (b
->cleargc
) XMesaFreeGC( b
->xm_visual
->display
, b
->cleargc
);
2001 if (b
->swapgc
) XMesaFreeGC( b
->xm_visual
->display
, b
->swapgc
);
2004 #if defined(USE_XSHM) && !defined(XFree86Server)
2006 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
2007 XDestroyImage( b
->backimage
);
2008 shmdt( b
->shminfo
.shmaddr
);
2012 XMesaDestroyImage( b
->backimage
);
2014 if (b
->backpixmap
) {
2015 XMesaFreePixmap( b
->xm_visual
->display
, b
->backpixmap
);
2016 if (b
->xm_visual
->hpcr_clear_flag
) {
2017 XMesaFreePixmap( b
->xm_visual
->display
,
2018 b
->xm_visual
->hpcr_clear_pixmap
);
2019 XMesaDestroyImage( b
->xm_visual
->hpcr_clear_ximage
);
2023 FREE( b
->rowimage
->data
);
2024 b
->rowimage
->data
= NULL
;
2025 XMesaDestroyImage( b
->rowimage
);
2028 free_xmesa_buffer(client
, b
);
2034 * Bind buffer b to context c and make c the current rendering context.
2036 GLboolean
XMesaMakeCurrent( XMesaContext c
, XMesaBuffer b
)
2038 return XMesaMakeCurrent2( c
, b
, b
);
2043 * Bind buffer b to context c and make c the current rendering context.
2045 GLboolean
XMesaMakeCurrent2( XMesaContext c
, XMesaBuffer drawBuffer
,
2046 XMesaBuffer readBuffer
)
2049 if (!drawBuffer
|| !readBuffer
)
2050 return GL_FALSE
; /* must specify buffers! */
2053 if (drawBuffer
->FXctx
) {
2054 fxMesaMakeCurrent(drawBuffer
->FXctx
);
2056 c
->xm_draw_buffer
= drawBuffer
;
2057 c
->xm_read_buffer
= readBuffer
;
2058 c
->xm_buffer
= drawBuffer
;
2063 if (c
->gl_ctx
== _mesa_get_current_context()
2064 && c
->xm_draw_buffer
== drawBuffer
2065 && c
->xm_read_buffer
== readBuffer
2066 && c
->xm_draw_buffer
->wasCurrent
) {
2067 /* same context and buffer, do nothing */
2071 c
->xm_draw_buffer
= drawBuffer
;
2072 c
->xm_read_buffer
= readBuffer
;
2073 c
->xm_buffer
= drawBuffer
;
2075 _mesa_make_current2(c
->gl_ctx
,
2076 &drawBuffer
->mesa_buffer
,
2077 &readBuffer
->mesa_buffer
);
2079 if (c
->gl_ctx
->Viewport
.Width
== 0) {
2080 /* initialize viewport to window size */
2081 _mesa_Viewport( 0, 0, drawBuffer
->width
, drawBuffer
->height
);
2082 c
->gl_ctx
->Scissor
.Width
= drawBuffer
->width
;
2083 c
->gl_ctx
->Scissor
.Height
= drawBuffer
->height
;
2086 if (c
->xm_visual
->mesa_visual
.rgbMode
) {
2088 * Must recompute and set these pixel values because colormap
2089 * can be different for different windows.
2091 c
->clearpixel
= xmesa_color_to_pixel( c
,
2096 c
->xm_visual
->undithered_pf
);
2097 XMesaSetForeground(c
->display
, c
->xm_draw_buffer
->cleargc
, c
->clearpixel
);
2100 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2101 c
->xm_draw_buffer
->wasCurrent
= GL_TRUE
;
2105 _mesa_make_current2( NULL
, NULL
, NULL
);
2112 * Unbind the context c from its buffer.
2114 GLboolean
XMesaUnbindContext( XMesaContext c
)
2116 /* A no-op for XFree86 integration purposes */
2121 XMesaContext
XMesaGetCurrentContext( void )
2123 GET_CURRENT_CONTEXT(ctx
);
2125 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2134 XMesaBuffer
XMesaGetCurrentBuffer( void )
2136 GET_CURRENT_CONTEXT(ctx
);
2138 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2139 return xmesa
->xm_draw_buffer
;
2147 /* New in Mesa 3.1 */
2148 XMesaBuffer
XMesaGetCurrentReadBuffer( void )
2150 GET_CURRENT_CONTEXT(ctx
);
2152 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2153 return xmesa
->xm_read_buffer
;
2161 GLboolean
XMesaForceCurrent(XMesaContext c
)
2164 if (c
->gl_ctx
!= _mesa_get_current_context()) {
2165 _mesa_make_current(c
->gl_ctx
, &c
->xm_draw_buffer
->mesa_buffer
);
2169 _mesa_make_current(NULL
, NULL
);
2175 GLboolean
XMesaLoseCurrent(XMesaContext c
)
2178 _mesa_make_current(NULL
, NULL
);
2184 * Switch 3Dfx support hack between window and full-screen mode.
2186 GLboolean
XMesaSetFXmode( GLint mode
)
2189 const char *fx
= getenv("MESA_GLX_FX");
2190 if (fx
&& fx
[0] != 'd') {
2191 GET_CURRENT_CONTEXT(ctx
);
2192 GrHwConfiguration hw
;
2193 if (!FX_grSstQueryHardware(&hw
)) {
2194 /*fprintf(stderr, "!grSstQueryHardware\n");*/
2197 if (hw
.num_sst
< 1) {
2198 /*fprintf(stderr, "hw.num_sst < 1\n");*/
2202 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2203 if (mode
== XMESA_FX_WINDOW
) {
2204 if (xmesa
->xm_draw_buffer
->FXisHackUsable
) {
2205 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
2206 xmesa
->xm_draw_buffer
->FXwindowHack
= GL_TRUE
;
2210 else if (mode
== XMESA_FX_FULLSCREEN
) {
2211 FX_grSstControl(GR_CONTROL_ACTIVATE
);
2212 xmesa
->xm_draw_buffer
->FXwindowHack
= GL_FALSE
;
2216 /* Error: Bad mode value */
2220 /*fprintf(stderr, "fallthrough\n");*/
2231 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2233 static void FXgetImage( XMesaBuffer b
)
2235 GET_CURRENT_CONTEXT(ctx
);
2236 static unsigned short pixbuf
[MAX_WIDTH
];
2240 unsigned int bw
, depth
, width
, height
;
2241 XMesaContext xmesa
= (XMesaContext
) ctx
->DriverCtx
;
2243 #ifdef XFree86Server
2244 x
= b
->frontbuffer
->x
;
2245 y
= b
->frontbuffer
->y
;
2246 width
= b
->frontbuffer
->width
;
2247 height
= b
->frontbuffer
->height
;
2248 depth
= b
->frontbuffer
->depth
;
2250 XGetGeometry( b
->xm_visual
->display
, b
->frontbuffer
,
2251 &root
, &xpos
, &ypos
, &width
, &height
, &bw
, &depth
);
2253 if (b
->width
!= width
|| b
->height
!= height
) {
2254 b
->width
= MIN2((int)width
, b
->FXctx
->width
);
2255 b
->height
= MIN2((int)height
, b
->FXctx
->height
);
2257 b
->width
--; /* prevent odd width */
2258 xmesa_alloc_back_buffer( b
);
2261 grLfbWriteColorFormat(GR_COLORFORMAT_ARGB
);
2262 if (b
->xm_visual
->undithered_pf
==PF_5R6G5B
) {
2263 /* Special case: 16bpp RGB */
2264 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
, /* src buffer */
2265 0, b
->FXctx
->height
- b
->height
, /*pos*/
2266 b
->width
, b
->height
, /* size */
2267 b
->width
* sizeof(GLushort
), /* stride */
2268 b
->backimage
->data
); /* dest buffer */
2270 else if (b
->xm_visual
->dithered_pf
==PF_DITHER
2271 && GET_VISUAL_DEPTH(b
->xm_visual
)==8) {
2272 /* Special case: 8bpp RGB */
2273 for (y
=0;y
<b
->height
;y
++) {
2274 GLubyte
*ptr
= (GLubyte
*) b
->backimage
->data
2275 + b
->backimage
->bytes_per_line
* y
;
2278 /* read row from 3Dfx frame buffer */
2279 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
,
2280 0, b
->FXctx
->height
-(b
->height
-y
),
2285 /* write to XImage back buffer */
2286 for (x
=0;x
<b
->width
;x
++) {
2287 GLubyte r
= (pixbuf
[x
] & 0xf800) >> 8;
2288 GLubyte g
= (pixbuf
[x
] & 0x07e0) >> 3;
2289 GLubyte b
= (pixbuf
[x
] & 0x001f) << 3;
2290 *ptr
++ = XDITHER( x
, r
, g
, b
);
2295 /* General case: slow! */
2296 for (y
=0;y
<b
->height
;y
++) {
2297 /* read row from 3Dfx frame buffer */
2298 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
,
2299 0, b
->FXctx
->height
-(b
->height
-y
),
2304 /* write to XImage back buffer */
2305 for (x
=0;x
<b
->width
;x
++) {
2306 XMesaPutPixel(b
->backimage
,x
,y
,
2307 xmesa_color_to_pixel(xmesa
,
2308 (pixbuf
[x
] & 0xf800) >> 8,
2309 (pixbuf
[x
] & 0x07e0) >> 3,
2310 (pixbuf
[x
] & 0x001f) << 3,
2312 b
->xm_visual
->undithered_pf
));
2316 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR
);
2322 * Copy the back buffer to the front buffer. If there's no back buffer
2325 void XMesaSwapBuffers( XMesaBuffer b
)
2327 GET_CURRENT_CONTEXT(ctx
);
2329 /* If we're swapping the buffer associated with the current context
2330 * we have to flush any pending rendering commands first.
2332 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
2333 _mesa_notifySwapBuffers(ctx
);
2338 fxMesaSwapBuffers();
2340 if (b
->FXwindowHack
)
2347 /* Copy Ximage from host's memory to server's window */
2348 #if defined(USE_XSHM) && !defined(XFree86Server)
2350 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2351 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2354 0, 0, b
->width
, b
->height
, False
);
2355 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2360 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2361 XMesaPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2364 0, 0, b
->width
, b
->height
);
2365 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2369 /* Copy pixmap to window on server */
2370 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2371 XMesaCopyArea( b
->xm_visual
->display
,
2372 b
->backpixmap
, /* source drawable */
2373 b
->frontbuffer
, /* dest. drawable */
2375 0, 0, b
->width
, b
->height
, /* source region */
2376 0, 0 /* dest region */
2378 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2381 #if !defined(XFree86Server)
2382 XSync( b
->xm_visual
->display
, False
);
2389 * Copy sub-region of back buffer to front buffer
2391 void XMesaCopySubBuffer( XMesaBuffer b
, int x
, int y
, int width
, int height
)
2393 GET_CURRENT_CONTEXT(ctx
);
2395 /* If we're swapping the buffer associated with the current context
2396 * we have to flush any pending rendering commands first.
2398 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
2399 _mesa_notifySwapBuffers(ctx
);
2402 int yTop
= b
->height
- y
- height
;
2405 fxMesaSwapBuffers();
2406 if (b
->FXwindowHack
)
2413 /* Copy Ximage from host's memory to server's window */
2414 #if defined(USE_XSHM) && !defined(XFree86Server)
2416 /* XXX assuming width and height aren't too large! */
2417 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2419 b
->backimage
, x
, yTop
,
2420 x
, yTop
, width
, height
, False
);
2421 /* wait for finished event??? */
2426 /* XXX assuming width and height aren't too large! */
2427 XMesaPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2429 b
->backimage
, x
, yTop
,
2430 x
, yTop
, width
, height
);
2434 /* Copy pixmap to window on server */
2435 XMesaCopyArea( b
->xm_visual
->display
,
2436 b
->backpixmap
, /* source drawable */
2437 b
->frontbuffer
, /* dest. drawable */
2439 x
, yTop
, width
, height
, /* source region */
2440 x
, yTop
/* dest region */
2448 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
2449 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2450 * back buffer directly.
2451 * Output: pixmap - pointer to back buffer's Pixmap, or 0
2452 * ximage - pointer to back buffer's XImage, or NULL
2453 * Return: GL_TRUE = context is double buffered
2454 * GL_FALSE = context is single buffered
2456 GLboolean
XMesaGetBackBuffer( XMesaBuffer b
,
2457 XMesaPixmap
*pixmap
,
2458 XMesaImage
**ximage
)
2461 if (pixmap
) *pixmap
= b
->backpixmap
;
2462 if (ximage
) *ximage
= b
->backimage
;
2474 * Return the depth buffer associated with an XMesaBuffer.
2475 * Input: b - the XMesa buffer handle
2476 * Output: width, height - size of buffer in pixels
2477 * bytesPerValue - bytes per depth value (2 or 4)
2478 * buffer - pointer to depth buffer values
2479 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
2481 GLboolean
XMesaGetDepthBuffer( XMesaBuffer b
, GLint
*width
, GLint
*height
,
2482 GLint
*bytesPerValue
, void **buffer
)
2484 if (!b
->mesa_buffer
.DepthBuffer
) {
2492 *width
= b
->mesa_buffer
.Width
;
2493 *height
= b
->mesa_buffer
.Height
;
2494 *bytesPerValue
= sizeof(GLdepth
);
2495 *buffer
= b
->mesa_buffer
.DepthBuffer
;
2501 void XMesaFlush( XMesaContext c
)
2503 if (c
&& c
->xm_visual
) {
2504 #ifdef XFree86Server
2507 XSync( c
->xm_visual
->display
, False
);
2514 const char *XMesaGetString( XMesaContext c
, int name
)
2517 if (name
==XMESA_VERSION
) {
2520 else if (name
==XMESA_EXTENSIONS
) {
2530 XMesaBuffer
XMesaFindBuffer( XMesaDisplay
*dpy
, XMesaDrawable d
)
2533 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
2534 if (b
->frontbuffer
==d
&& b
->display
==dpy
) {
2544 * Look for XMesaBuffers whose X window has been destroyed.
2545 * Deallocate any such XMesaBuffers.
2547 void XMesaGarbageCollect( void )
2549 XMesaBuffer b
, next
;
2550 for (b
=XMesaBufferList
; b
; b
=next
) {
2552 if (b
->display
&& b
->frontbuffer
&& b
->type
== WINDOW
) {
2553 #ifdef XFree86Server
2556 XSync(b
->display
, False
);
2557 if (!window_exists( b
->display
, b
->frontbuffer
)) {
2558 /* found a dead window, free the ancillary info */
2559 XMesaDestroyBuffer( b
);
2567 void XMesaReset( void )
2569 while (XMesaBufferList
)
2570 XMesaDestroyBuffer(XMesaBufferList
);
2572 XMesaBufferList
= NULL
;
2576 unsigned long XMesaDitherColor( XMesaContext xmesa
, GLint x
, GLint y
,
2577 GLfloat red
, GLfloat green
,
2578 GLfloat blue
, GLfloat alpha
)
2580 GLint r
= (GLint
) (red
* 255.0F
);
2581 GLint g
= (GLint
) (green
* 255.0F
);
2582 GLint b
= (GLint
) (blue
* 255.0F
);
2583 GLint a
= (GLint
) (alpha
* 255.0F
);
2585 switch (xmesa
->pixelformat
) {
2591 PACK_TRUECOLOR( p
, r
, g
, b
);
2595 return PACK_8A8B8G8R( r
, g
, b
, a
);
2597 return PACK_8R8G8B( r
, g
, b
);
2599 return PACK_5R6G5B( r
, g
, b
);
2603 return DITHER( x
, y
, r
, g
, b
);
2606 /* 382 = (3*255)/2 */
2607 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
2609 return DITHER_HPCR(x
, y
, r
, g
, b
);
2613 return LOOKUP( r
, g
, b
);
2616 return GRAY_RGB( r
, g
, b
);
2617 case PF_DITHER_5R6G5B
:
2622 PACK_TRUEDITHER(p
, x
, y
, r
, g
, b
);
2626 _mesa_problem(NULL
, "Bad pixel format in XMesaDitherColor");
2633 * This is typically called when the window size changes and we need
2634 * to reallocate the buffer's back/depth/stencil/accum buffers.
2636 void XMesaResizeBuffers( XMesaBuffer b
)
2638 xmesa_resize_buffers( &(b
->mesa_buffer
) );