2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * This file contains the implementations of all the XMesa* functions.
31 * The window coordinate system origin (0,0) is in the lower-left corner
32 * of the window. X11's window coordinate origin is in the upper-left
33 * corner of the window. Therefore, most drawing functions in this
34 * file have to flip Y coordinates.
36 * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
37 * in support for the MIT Shared Memory extension. If enabled, when you
38 * use an Ximage for the back buffer in double buffered mode, the "swap"
39 * operation will be faster. You must also link with -lXext.
41 * Byte swapping: If the Mesa host and the X display use a different
42 * byte order then there's some trickiness to be aware of when using
43 * XImages. The byte ordering used for the XImage is that of the X
44 * display, not the Mesa host.
45 * The color-to-pixel encoding for True/DirectColor must be done
46 * according to the display's visual red_mask, green_mask, and blue_mask.
47 * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
48 * do byte swapping if needed. If one wants to directly "poke" the pixel
49 * into the XImage's buffer then the pixel must be byte swapped first. In
50 * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
51 * and use XPutPixel everywhere except in the implementation of
52 * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so
53 * instead of using XPutPixel we "poke" our values after byte-swapping
54 * the clear pixel value if needed.
63 #include "glxheader.h"
67 #include "extensions.h"
73 #include "texformat.h"
76 #include "swrast/swrast.h"
77 #include "swrast_setup/swrast_setup.h"
78 #include "array_cache/acache.h"
80 #include "tnl/t_context.h"
81 #include "tnl/t_pipeline.h"
82 #include "drivers/common/driverfuncs.h"
85 #include <GL/glxtokens.h>
89 * Global X driver lock
91 _glthread_Mutex _xmesa_lock
;
96 * Lookup tables for HPCR pixel format:
98 static short hpcr_rgbTbl
[3][256] = {
100 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
101 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
102 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
103 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
104 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
105 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
106 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
107 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
108 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
109 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
110 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
111 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
112 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
113 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
114 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
115 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
118 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
119 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
120 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
121 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
122 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
123 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
124 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
125 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
126 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
127 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
128 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
129 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
130 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
131 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
132 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
133 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
136 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
137 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
138 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55,
139 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
140 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
141 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79,
142 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87,
143 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
144 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
145 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
146 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
147 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
148 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
149 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
150 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
151 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
157 /**********************************************************************/
158 /***** X Utility Functions *****/
159 /**********************************************************************/
163 * Return the host's byte order as LSBFirst or MSBFirst ala X.
165 #ifndef XFree86Server
166 static int host_byte_order( void )
169 char *cptr
= (char *) &i
;
170 return (*cptr
==1) ? LSBFirst
: MSBFirst
;
178 #ifndef XFree86Server
179 static volatile int mesaXErrorFlag
= 0;
181 static int mesaHandleXError( XMesaDisplay
*dpy
, XErrorEvent
*event
)
192 * Check if the X Shared Memory extension is available.
193 * Return: 0 = not available
194 * 1 = shared XImage support available
195 * 2 = shared Pixmap support available also
197 #ifndef XFree86Server
198 static int check_for_xshm( XMesaDisplay
*display
)
201 int major
, minor
, ignore
;
204 if (XQueryExtension( display
, "MIT-SHM", &ignore
, &ignore
, &ignore
)) {
205 if (XShmQueryVersion( display
, &major
, &minor
, &pixmaps
)==True
) {
206 return (pixmaps
==True
) ? 2 : 1;
216 /* Can't compile XSHM support */
224 * Apply gamma correction to an intensity value in [0..max]. Return the
225 * new intensity value.
227 static GLint
gamma_adjust( GLfloat gamma
, GLint value
, GLint max
)
233 double x
= (double) value
/ (double) max
;
234 return IROUND_POS((GLfloat
) max
* _mesa_pow(x
, 1.0F
/gamma
));
241 * Return the true number of bits per pixel for XImages.
242 * For example, if we request a 24-bit deep visual we may actually need/get
243 * 32bpp XImages. This function returns the appropriate bpp.
244 * Input: dpy - the X display
245 * visinfo - desribes the visual to be used for XImages
246 * Return: true number of bits per pixel for XImages
250 static int bits_per_pixel( XMesaVisual xmv
)
252 const int depth
= xmv
->nplanes
;
254 for (i
= 0; i
< screenInfo
.numPixmapFormats
; i
++) {
255 if (screenInfo
.formats
[i
].depth
== depth
)
256 return screenInfo
.formats
[i
].bitsPerPixel
;
258 return depth
; /* should never get here, but this should be safe */
263 static int bits_per_pixel( XMesaVisual xmv
)
265 XMesaDisplay
*dpy
= xmv
->display
;
266 XMesaVisualInfo visinfo
= xmv
->visinfo
;
269 /* Create a temporary XImage */
270 img
= XCreateImage( dpy
, visinfo
->visual
, visinfo
->depth
,
271 ZPixmap
, 0, /*format, offset*/
272 (char*) MALLOC(8), /*data*/
273 1, 1, /*width, height*/
278 /* grab the bits/pixel value */
279 bitsPerPixel
= img
->bits_per_pixel
;
280 /* free the XImage */
283 XMesaDestroyImage( img
);
291 * Determine if a given X window ID is valid (window exists).
292 * Do this by calling XGetWindowAttributes() for the window and
293 * checking if we catch an X error.
294 * Input: dpy - the display
295 * win - the window to check for existance
296 * Return: GL_TRUE - window exists
297 * GL_FALSE - window doesn't exist
299 #ifndef XFree86Server
300 static GLboolean WindowExistsFlag
;
302 static int window_exists_err_handler( XMesaDisplay
* dpy
, XErrorEvent
* xerr
)
305 if (xerr
->error_code
== BadWindow
) {
306 WindowExistsFlag
= GL_FALSE
;
311 static GLboolean
window_exists( XMesaDisplay
*dpy
, Window win
)
313 XWindowAttributes wa
;
314 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
315 WindowExistsFlag
= GL_TRUE
;
316 old_handler
= XSetErrorHandler(window_exists_err_handler
);
317 XGetWindowAttributes( dpy
, win
, &wa
); /* dummy request */
318 XSetErrorHandler(old_handler
);
319 return WindowExistsFlag
;
325 /**********************************************************************/
326 /***** Linked list of XMesaBuffers *****/
327 /**********************************************************************/
329 static XMesaBuffer XMesaBufferList
= NULL
;
333 * Allocate a new XMesaBuffer, initialize basic fields and add to
334 * the list of all buffers.
337 alloc_xmesa_buffer(XMesaVisual vis
, BufferType type
, XMesaColormap cmap
)
339 XMesaBuffer b
= (XMesaBuffer
) CALLOC_STRUCT(xmesa_buffer
);
341 b
->display
= vis
->display
;
346 _mesa_initialize_framebuffer(&b
->mesa_buffer
,
348 vis
->mesa_visual
.depthBits
> 0,
349 vis
->mesa_visual
.stencilBits
> 0,
350 vis
->mesa_visual
.accumRedBits
+
351 vis
->mesa_visual
.accumGreenBits
+
352 vis
->mesa_visual
.accumBlueBits
> 0,
353 vis
->mesa_visual
.alphaBits
> 0
354 /*v->mesa_visual.numAuxBuffers > 0*/ );
356 if (vis
->mesa_visual
.numAuxBuffers
> 0)
357 b
->mesa_buffer
.UseSoftwareAuxBuffers
= GL_TRUE
;
359 /* determine back buffer implementation */
360 if (vis
->mesa_visual
.doubleBufferMode
) {
361 if (vis
->ximage_flag
) {
362 b
->db_state
= BACK_XIMAGE
;
365 b
->db_state
= BACK_PIXMAP
;
372 /* insert into linked list */
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 if (b
->mesa_buffer
.Width
== 0 || b
->mesa_buffer
.Height
== 0) {
494 /* this will be true the first time we're called on 'b' */
498 b
->backimage
= XShmCreateImage(b
->xm_visual
->display
,
499 b
->xm_visual
->visinfo
->visual
,
500 b
->xm_visual
->visinfo
->depth
,
501 ZPixmap
, NULL
, &b
->shminfo
,
502 b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
);
503 if (b
->backimage
== NULL
) {
504 _mesa_warning(NULL
, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
509 b
->shminfo
.shmid
= shmget( IPC_PRIVATE
, b
->backimage
->bytes_per_line
510 * b
->backimage
->height
, IPC_CREAT
|0777 );
511 if (b
->shminfo
.shmid
< 0) {
512 _mesa_warning(NULL
, "shmget failed while allocating back buffer");
513 XDestroyImage( b
->backimage
);
515 _mesa_warning(NULL
, "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 _mesa_warning(NULL
, "shmat() failed while allocating back buffer");
524 XDestroyImage( b
->backimage
);
525 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
527 _mesa_warning(NULL
, "alloc_back_buffer: Shared memory error (shmat), disabling.");
532 b
->shminfo
.readOnly
= False
;
534 old_handler
= XSetErrorHandler( mesaHandleXError
);
535 /* This may trigger the X protocol error we're ready to catch: */
536 XShmAttach( b
->xm_visual
->display
, &b
->shminfo
);
537 XSync( b
->xm_visual
->display
, False
);
539 if (mesaXErrorFlag
) {
540 /* we are on a remote display, this error is normal, don't print it */
541 XFlush( b
->xm_visual
->display
);
543 XDestroyImage( b
->backimage
);
544 shmdt( b
->shminfo
.shmaddr
);
545 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
548 (void) XSetErrorHandler( old_handler
);
552 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 ); /* nobody else needs it */
554 /* Finally, try an XShmPutImage to be really sure the extension works */
555 gc
= XCreateGC( b
->xm_visual
->display
, b
->frontbuffer
, 0, NULL
);
556 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
, gc
,
557 b
->backimage
, 0, 0, 0, 0, 1, 1 /*one pixel*/, False
);
558 XSync( b
->xm_visual
->display
, False
);
559 XFreeGC( b
->xm_visual
->display
, gc
);
560 (void) XSetErrorHandler( old_handler
);
561 if (mesaXErrorFlag
) {
562 XFlush( b
->xm_visual
->display
);
564 XDestroyImage( b
->backimage
);
565 shmdt( b
->shminfo
.shmaddr
);
566 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
573 int height
= b
->backimage
->height
;
574 /* Needed by PIXELADDR1 macro */
575 b
->ximage_width1
= b
->backimage
->bytes_per_line
;
576 b
->ximage_origin1
= (GLubyte
*) b
->backimage
->data
577 + b
->ximage_width1
* (height
-1);
578 /* Needed by PIXELADDR2 macro */
579 b
->ximage_width2
= b
->backimage
->bytes_per_line
/ 2;
580 b
->ximage_origin2
= (GLushort
*) b
->backimage
->data
581 + b
->ximage_width2
* (height
-1);
582 /* Needed by PIXELADDR3 macro */
583 b
->ximage_width3
= b
->backimage
->bytes_per_line
;
584 b
->ximage_origin3
= (GLubyte
*) b
->backimage
->data
585 + b
->ximage_width3
* (height
-1);
586 /* Needed by PIXELADDR4 macro */
587 b
->ximage_width4
= b
->backimage
->width
;
588 b
->ximage_origin4
= (GLuint
*) b
->backimage
->data
589 + b
->ximage_width4
* (height
-1);
594 /* Can't compile XSHM support */
603 * Setup an off-screen pixmap or Ximage to use as the back buffer.
604 * Input: b - the X/Mesa buffer
606 void xmesa_alloc_back_buffer( XMesaBuffer b
)
608 if (b
->db_state
==BACK_XIMAGE
) {
609 /* Deallocate the old backimage, if any */
611 #if defined(USE_XSHM) && !defined(XFree86Server)
613 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
614 XDestroyImage( b
->backimage
);
615 shmdt( b
->shminfo
.shmaddr
);
619 XMesaDestroyImage( b
->backimage
);
623 /* Allocate new back buffer */
626 /* Allocate a regular XImage for the back buffer. */
627 b
->backimage
= XMesaCreateImage(b
->xm_visual
->BitsPerPixel
,
628 b
->mesa_buffer
.Width
,
629 b
->mesa_buffer
.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 */
638 b
->mesa_buffer
.Width
,
639 b
->mesa_buffer
.Height
,
640 8, 0 ); /* pad, bytes_per_line */
643 _mesa_warning(NULL
, "alloc_back_buffer: XCreateImage failed.");
645 b
->backimage
->data
= (char *) MALLOC( b
->backimage
->height
646 * b
->backimage
->bytes_per_line
);
647 if (!b
->backimage
->data
) {
648 _mesa_warning(NULL
, "alloc_back_buffer: MALLOC failed.");
649 XMesaDestroyImage( b
->backimage
);
653 b
->backpixmap
= None
;
655 else if (b
->db_state
==BACK_PIXMAP
) {
656 XMesaPixmap old_pixmap
= b
->backpixmap
;
657 int width
= b
->mesa_buffer
.Width
, height
= b
->mesa_buffer
.Height
;
664 /* Free the old back pixmap */
666 XMesaFreePixmap( b
->xm_visual
->display
, b
->backpixmap
);
668 /* Allocate new back pixmap */
669 b
->backpixmap
= XMesaCreatePixmap( b
->xm_visual
->display
, b
->frontbuffer
,
671 GET_VISUAL_DEPTH(b
->xm_visual
) );
673 /* update other references to backpixmap */
674 if (b
->buffer
==(XMesaDrawable
)old_pixmap
) {
675 b
->buffer
= (XMesaDrawable
)b
->backpixmap
;
683 * A replacement for XAllocColor. This function should never
684 * fail to allocate a color. When XAllocColor fails, we return
685 * the nearest matching color. If we have to allocate many colors
686 * this function isn't too efficient; the XQueryColors() could be
688 * Written by Michael Pichler, Brian Paul, Mark Kilgard
689 * Input: dpy - X display
691 * cmapSize - size of colormap
692 * In/Out: color - the XColor struct
693 * Output: exact - 1=exact color match, 0=closest match
694 * alloced - 1=XAlloc worked, 0=XAlloc failed
697 noFaultXAllocColor( int client
,
702 int *exact
, int *alloced
)
708 /* we'll try to cache ctable for better remote display performance */
709 static Display
*prevDisplay
= NULL
;
710 static XMesaColormap prevCmap
= 0;
711 static int prevCmapSize
= 0;
712 static XMesaColor
*ctable
= NULL
;
716 double mindist
; /* 3*2^16^2 exceeds long int precision. */
720 /* First try just using XAllocColor. */
723 &color
->red
, &color
->green
, &color
->blue
,
725 client
) == Success
) {
727 if (XAllocColor(dpy
, cmap
, color
)) {
734 /* Alloc failed, search for closest match */
736 /* Retrieve color table entries. */
737 /* XXX alloca candidate. */
739 ppixIn
= (Pixel
*) MALLOC(cmapSize
* sizeof(Pixel
));
740 ctable
= (xrgb
*) MALLOC(cmapSize
* sizeof(xrgb
));
741 for (i
= 0; i
< cmapSize
; i
++) {
744 QueryColors(cmap
, cmapSize
, ppixIn
, ctable
);
746 if (prevDisplay
!= dpy
|| prevCmap
!= cmap
747 || prevCmapSize
!= cmapSize
|| !ctable
) {
748 /* free previously cached color table */
751 /* Get the color table from X */
752 ctable
= (XMesaColor
*) MALLOC(cmapSize
* sizeof(XMesaColor
));
754 for (i
= 0; i
< cmapSize
; i
++) {
757 XQueryColors(dpy
, cmap
, ctable
, cmapSize
);
760 prevCmapSize
= cmapSize
;
764 /* Find best match. */
767 for (i
= 0; i
< cmapSize
; i
++) {
768 double dr
= 0.30 * ((double) color
->red
- (double) ctable
[i
].red
);
769 double dg
= 0.59 * ((double) color
->green
- (double) ctable
[i
].green
);
770 double db
= 0.11 * ((double) color
->blue
- (double) ctable
[i
].blue
);
771 double dist
= dr
* dr
+ dg
* dg
+ db
* db
;
772 if (bestmatch
< 0 || dist
< mindist
) {
779 subColor
.red
= ctable
[bestmatch
].red
;
780 subColor
.green
= ctable
[bestmatch
].green
;
781 subColor
.blue
= ctable
[bestmatch
].blue
;
782 /* Try to allocate the closest match color. This should only
783 * fail if the cell is read/write. Otherwise, we're incrementing
784 * the cell's reference count.
788 &subColor
.red
, &subColor
.green
, &subColor
.blue
,
790 client
) == Success
) {
792 if (XAllocColor(dpy
, cmap
, &subColor
)) {
797 /* do this to work around a problem reported by Frank Ortega */
798 subColor
.pixel
= (unsigned long) bestmatch
;
799 subColor
.red
= ctable
[bestmatch
].red
;
800 subColor
.green
= ctable
[bestmatch
].green
;
801 subColor
.blue
= ctable
[bestmatch
].blue
;
802 subColor
.flags
= DoRed
| DoGreen
| DoBlue
;
809 /* don't free table, save it for next time */
820 * Do setup for PF_GRAYSCALE pixel format.
821 * Note that buffer may be NULL.
823 static GLboolean
setup_grayscale( int client
, XMesaVisual v
,
824 XMesaBuffer buffer
, XMesaColormap cmap
)
826 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
831 XMesaBuffer prevBuffer
;
837 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
839 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
840 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
841 /* Copy colormap stuff from previous XMesaBuffer which uses same
842 * X colormap. Do this to avoid time spent in noFaultXAllocColor.
844 copy_colortable_info(buffer
, prevBuffer
);
847 /* Allocate 256 shades of gray */
849 int colorsfailed
= 0;
850 for (gray
=0;gray
<256;gray
++) {
851 GLint r
= gamma_adjust( v
->RedGamma
, gray
, 255 );
852 GLint g
= gamma_adjust( v
->GreenGamma
, gray
, 255 );
853 GLint b
= gamma_adjust( v
->BlueGamma
, gray
, 255 );
856 xcol
.red
= (r
<< 8) | r
;
857 xcol
.green
= (g
<< 8) | g
;
858 xcol
.blue
= (b
<< 8) | b
;
859 noFaultXAllocColor( client
, v
->display
,
860 cmap
, GET_COLORMAP_SIZE(v
),
861 &xcol
, &exact
, &alloced
);
866 assert(buffer
->num_alloced
<256);
867 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
868 buffer
->num_alloced
++;
873 buffer->color_table[gray*3+0] = xcol.pixel;
874 buffer->color_table[gray*3+1] = xcol.pixel;
875 buffer->color_table[gray*3+2] = xcol.pixel;
876 assert(xcol.pixel < 65536);
877 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
878 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
879 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
881 buffer
->color_table
[gray
] = xcol
.pixel
;
882 assert(xcol
.pixel
< 65536);
883 buffer
->pixel_to_r
[xcol
.pixel
] = gray
;
884 buffer
->pixel_to_g
[xcol
.pixel
] = gray
;
885 buffer
->pixel_to_b
[xcol
.pixel
] = gray
;
888 if (colorsfailed
&& _mesa_getenv("MESA_DEBUG")) {
890 "Note: %d out of 256 needed colors do not match exactly.\n",
896 v
->dithered_pf
= PF_Grayscale
;
897 v
->undithered_pf
= PF_Grayscale
;
904 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
905 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
906 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
907 * color. While this function was originally designed just for 8-bit
908 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
909 * Dithering code contributed by Bob Mercier.
911 static GLboolean
setup_dithered_color( int client
, XMesaVisual v
,
912 XMesaBuffer buffer
, XMesaColormap cmap
)
914 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
919 XMesaBuffer prevBuffer
;
925 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
927 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
928 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
929 /* Copy colormap stuff from previous, matching XMesaBuffer.
930 * Do this to avoid time spent in noFaultXAllocColor.
932 copy_colortable_info(buffer
, prevBuffer
);
935 /* Allocate X colors and initialize color_table[], red_table[], etc */
937 int colorsfailed
= 0;
938 for (r
= 0; r
< DITH_R
; r
++) {
939 for (g
= 0; g
< DITH_G
; g
++) {
940 for (b
= 0; b
< DITH_B
; b
++) {
943 xcol
.red
=gamma_adjust(v
->RedGamma
, r
*65535/(DITH_R
-1),65535);
944 xcol
.green
=gamma_adjust(v
->GreenGamma
, g
*65535/(DITH_G
-1),65535);
945 xcol
.blue
=gamma_adjust(v
->BlueGamma
, b
*65535/(DITH_B
-1),65535);
946 noFaultXAllocColor( client
, v
->display
,
947 cmap
, GET_COLORMAP_SIZE(v
),
948 &xcol
, &exact
, &alloced
);
953 assert(buffer
->num_alloced
<256);
954 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
955 buffer
->num_alloced
++;
957 i
= DITH_MIX( r
, g
, b
);
959 buffer
->color_table
[i
] = xcol
.pixel
;
960 assert(xcol
.pixel
< 65536);
961 buffer
->pixel_to_r
[xcol
.pixel
] = r
* 255 / (DITH_R
-1);
962 buffer
->pixel_to_g
[xcol
.pixel
] = g
* 255 / (DITH_G
-1);
963 buffer
->pixel_to_b
[xcol
.pixel
] = b
* 255 / (DITH_B
-1);
968 if (colorsfailed
&& _mesa_getenv("MESA_DEBUG")) {
970 "Note: %d out of %d needed colors do not match exactly.\n",
971 colorsfailed
, DITH_R
* DITH_G
* DITH_B
);
976 v
->dithered_pf
= PF_Dither
;
977 v
->undithered_pf
= PF_Lookup
;
983 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
984 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
985 * Special dithering tables have to be initialized.
987 static void setup_8bit_hpcr( XMesaVisual v
)
989 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be)
990 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
991 * on the root window AND the colormap obtainable by XGetRGBColormaps
992 * for that atom must be set on the window. (see also tkInitWindow)
993 * If that colormap is not set, the output will look stripy.
996 /* Setup color tables with gamma correction */
1000 g
= 1.0 / v
->RedGamma
;
1001 for (i
=0; i
<256; i
++) {
1002 GLint red
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[0][i
]/255.0, g
));
1003 v
->hpcr_rgbTbl
[0][i
] = CLAMP( red
, 16, 239 );
1006 g
= 1.0 / v
->GreenGamma
;
1007 for (i
=0; i
<256; i
++) {
1008 GLint green
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[1][i
]/255.0, g
));
1009 v
->hpcr_rgbTbl
[1][i
] = CLAMP( green
, 16, 239 );
1012 g
= 1.0 / v
->BlueGamma
;
1013 for (i
=0; i
<256; i
++) {
1014 GLint blue
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[2][i
]/255.0, g
));
1015 v
->hpcr_rgbTbl
[2][i
] = CLAMP( blue
, 32, 223 );
1017 v
->undithered_pf
= PF_HPCR
; /* can't really disable dithering for now */
1018 v
->dithered_pf
= PF_HPCR
;
1020 /* which method should I use to clear */
1021 /* GL_FALSE: keep the ordinary method */
1022 /* GL_TRUE : clear with dither pattern */
1023 v
->hpcr_clear_flag
= _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE
: GL_FALSE
;
1025 if (v
->hpcr_clear_flag
) {
1026 v
->hpcr_clear_pixmap
= XMesaCreatePixmap(v
->display
,
1027 DefaultRootWindow(v
->display
),
1029 #ifndef XFree86Server
1030 v
->hpcr_clear_ximage
= XGetImage(v
->display
, v
->hpcr_clear_pixmap
,
1031 0, 0, 16, 2, AllPlanes
, ZPixmap
);
1038 * Setup RGB rendering for a window with a True/DirectColor visual.
1040 static void setup_truecolor( XMesaVisual v
, XMesaBuffer buffer
,
1041 XMesaColormap cmap
)
1043 unsigned long rmask
, gmask
, bmask
;
1047 /* Compute red multiplier (mask) and bit shift */
1049 rmask
= GET_REDMASK(v
);
1050 while ((rmask
& 1)==0) {
1055 /* Compute green multiplier (mask) and bit shift */
1057 gmask
= GET_GREENMASK(v
);
1058 while ((gmask
& 1)==0) {
1063 /* Compute blue multiplier (mask) and bit shift */
1065 bmask
= GET_BLUEMASK(v
);
1066 while ((bmask
& 1)==0) {
1072 * Compute component-to-pixel lookup tables and dithering kernel
1075 static GLubyte kernel
[16] = {
1076 0*16, 8*16, 2*16, 10*16,
1077 12*16, 4*16, 14*16, 6*16,
1078 3*16, 11*16, 1*16, 9*16,
1079 15*16, 7*16, 13*16, 5*16,
1081 GLint rBits
= bitcount(rmask
);
1082 GLint gBits
= bitcount(gmask
);
1083 GLint bBits
= bitcount(bmask
);
1087 /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1088 for (i
=0; i
<=rmask
; i
++)
1089 v
->PixelToR
[i
] = (unsigned char) ((i
* 255) / rmask
);
1090 for (i
=0; i
<=gmask
; i
++)
1091 v
->PixelToG
[i
] = (unsigned char) ((i
* 255) / gmask
);
1092 for (i
=0; i
<=bmask
; i
++)
1093 v
->PixelToB
[i
] = (unsigned char) ((i
* 255) / bmask
);
1095 /* convert RGB values from [0,255] to pixel components */
1097 for (i
=0;i
<256;i
++) {
1098 GLint r
= gamma_adjust(v
->RedGamma
, i
, 255);
1099 GLint g
= gamma_adjust(v
->GreenGamma
, i
, 255);
1100 GLint b
= gamma_adjust(v
->BlueGamma
, i
, 255);
1101 v
->RtoPixel
[i
] = (r
>> (8-rBits
)) << v
->rshift
;
1102 v
->GtoPixel
[i
] = (g
>> (8-gBits
)) << v
->gshift
;
1103 v
->BtoPixel
[i
] = (b
>> (8-bBits
)) << v
->bshift
;
1105 /* overflow protection */
1106 for (i
=256;i
<512;i
++) {
1107 v
->RtoPixel
[i
] = v
->RtoPixel
[255];
1108 v
->GtoPixel
[i
] = v
->GtoPixel
[255];
1109 v
->BtoPixel
[i
] = v
->BtoPixel
[255];
1112 /* setup dithering kernel */
1114 if (gBits
> maxBits
) maxBits
= gBits
;
1115 if (bBits
> maxBits
) maxBits
= bBits
;
1116 for (i
=0;i
<16;i
++) {
1117 v
->Kernel
[i
] = kernel
[i
] >> maxBits
;
1120 v
->undithered_pf
= PF_Truecolor
;
1121 v
->dithered_pf
= (GET_VISUAL_DEPTH(v
)<24) ? PF_Dither_True
: PF_Truecolor
;
1125 * Now check for TrueColor visuals which we can optimize.
1127 if ( GET_REDMASK(v
) ==0x0000ff
1128 && GET_GREENMASK(v
)==0x00ff00
1129 && GET_BLUEMASK(v
) ==0xff0000
1130 && CHECK_BYTE_ORDER(v
)
1131 && v
->BitsPerPixel
==32
1132 && sizeof(GLuint
)==4
1133 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1134 /* common 32 bpp config used on SGI, Sun */
1135 v
->undithered_pf
= v
->dithered_pf
= PF_8A8B8G8R
;
1137 else if (GET_REDMASK(v
) ==0xff0000
1138 && GET_GREENMASK(v
)==0x00ff00
1139 && GET_BLUEMASK(v
) ==0x0000ff
1140 && CHECK_BYTE_ORDER(v
)
1141 && v
->BitsPerPixel
==32
1142 && sizeof(GLuint
)==4
1143 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1144 /* common 32 bpp config used on Linux, HP, IBM */
1145 if (GET_VISUAL_DEPTH(v
)==32)
1146 v
->undithered_pf
= v
->dithered_pf
= PF_8A8R8G8B
;
1148 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B
;
1150 else if (GET_REDMASK(v
) ==0xff0000
1151 && GET_GREENMASK(v
)==0x00ff00
1152 && GET_BLUEMASK(v
) ==0x0000ff
1153 && CHECK_BYTE_ORDER(v
)
1154 && v
->BitsPerPixel
==24
1155 && sizeof(GLuint
)==4
1156 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1157 /* common packed 24 bpp config used on Linux */
1158 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B24
;
1160 else if (GET_REDMASK(v
) ==0xf800
1161 && GET_GREENMASK(v
)==0x07e0
1162 && GET_BLUEMASK(v
) ==0x001f
1163 && CHECK_BYTE_ORDER(v
)
1164 && v
->BitsPerPixel
==16
1165 && sizeof(GLushort
)==2
1166 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1167 /* 5-6-5 color weight on common PC VGA boards */
1168 v
->undithered_pf
= PF_5R6G5B
;
1169 v
->dithered_pf
= PF_Dither_5R6G5B
;
1171 else if (GET_REDMASK(v
) ==0xe0
1172 && GET_GREENMASK(v
)==0x1c
1173 && GET_BLUEMASK(v
) ==0x03
1174 && CHECK_FOR_HPCR(v
)) {
1175 setup_8bit_hpcr( v
);
1182 * Setup RGB rendering for a window with a monochrome visual.
1184 static void setup_monochrome( XMesaVisual v
, XMesaBuffer b
)
1187 v
->dithered_pf
= v
->undithered_pf
= PF_1Bit
;
1188 /* if black=1 then we must flip pixel values */
1189 v
->bitFlip
= (GET_BLACK_PIXEL(v
) != 0);
1195 * When a context is "made current" for the first time, we can finally
1196 * finish initializing the context's visual and buffer information.
1197 * Input: v - the XMesaVisual to initialize
1198 * b - the XMesaBuffer to initialize (may be NULL)
1199 * rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1200 * window - the window/pixmap we're rendering into
1201 * cmap - the colormap associated with the window/pixmap
1202 * Return: GL_TRUE=success, GL_FALSE=failure
1204 static GLboolean
initialize_visual_and_buffer( int client
,
1208 XMesaDrawable window
,
1209 XMesaColormap cmap
)
1211 #ifndef XFree86Server
1216 assert(b
->xm_visual
== v
);
1219 /* Save true bits/pixel */
1220 v
->BitsPerPixel
= bits_per_pixel(v
);
1221 assert(v
->BitsPerPixel
> 0);
1224 if (rgb_flag
==GL_FALSE
) {
1225 /* COLOR-INDEXED WINDOW:
1226 * Even if the visual is TrueColor or DirectColor we treat it as
1227 * being color indexed. This is weird but might be useful to someone.
1229 v
->dithered_pf
= v
->undithered_pf
= PF_Index
;
1230 v
->mesa_visual
.indexBits
= GET_VISUAL_DEPTH(v
);
1234 * We support RGB rendering into almost any kind of visual.
1236 const int xclass
= v
->mesa_visual
.visualType
;
1237 if (xclass
==GLX_TRUE_COLOR
|| xclass
==GLX_DIRECT_COLOR
) {
1238 setup_truecolor( v
, b
, cmap
);
1240 else if (xclass
==GLX_STATIC_GRAY
&& GET_VISUAL_DEPTH(v
)==1) {
1241 setup_monochrome( v
, b
);
1243 else if (xclass
==GLX_GRAY_SCALE
|| xclass
==GLX_STATIC_GRAY
) {
1244 if (!setup_grayscale( client
, v
, b
, cmap
)) {
1248 else if ((xclass
==GLX_PSEUDO_COLOR
|| xclass
==GLX_STATIC_COLOR
)
1249 && GET_VISUAL_DEPTH(v
)>=4 && GET_VISUAL_DEPTH(v
)<=16) {
1250 if (!setup_dithered_color( client
, v
, b
, cmap
)) {
1255 _mesa_warning(NULL
, "XMesa: RGB mode rendering not supported in given visual.");
1258 v
->mesa_visual
.indexBits
= 0;
1260 if (_mesa_getenv("MESA_NO_DITHER")) {
1261 v
->dithered_pf
= v
->undithered_pf
;
1267 * If MESA_INFO env var is set print out some debugging info
1268 * which can help Brian figure out what's going on when a user
1271 if (_mesa_getenv("MESA_INFO")) {
1272 _mesa_printf("X/Mesa visual = %p\n", (void *) v
);
1273 _mesa_printf("X/Mesa dithered pf = %u\n", v
->dithered_pf
);
1274 _mesa_printf("X/Mesa undithered pf = %u\n", v
->undithered_pf
);
1275 _mesa_printf("X/Mesa level = %d\n", v
->mesa_visual
.level
);
1276 _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v
));
1277 _mesa_printf("X/Mesa bits per pixel = %d\n", v
->BitsPerPixel
);
1281 /* Do window-specific initializations */
1283 b
->frontbuffer
= window
;
1285 /* Setup for single/double buffering */
1286 if (v
->mesa_visual
.doubleBufferMode
) {
1287 /* Double buffered */
1288 #ifndef XFree86Server
1289 b
->shm
= check_for_xshm( v
->display
);
1291 xmesa_alloc_back_buffer( b
);
1292 if (b
->db_state
==BACK_PIXMAP
) {
1293 b
->buffer
= (XMesaDrawable
)b
->backpixmap
;
1300 /* Single Buffered */
1301 b
->buffer
= b
->frontbuffer
;
1304 /* X11 graphics contexts */
1305 #ifdef XFree86Server
1306 b
->gc
= CreateScratchGC(v
->display
, window
->depth
);
1308 b
->gc
= XCreateGC( v
->display
, window
, 0, NULL
);
1310 XMesaSetFunction( v
->display
, b
->gc
, GXcopy
);
1312 /* cleargc - for glClear() */
1313 #ifdef XFree86Server
1314 b
->cleargc
= CreateScratchGC(v
->display
, window
->depth
);
1316 b
->cleargc
= XCreateGC( v
->display
, window
, 0, NULL
);
1318 XMesaSetFunction( v
->display
, b
->cleargc
, GXcopy
);
1321 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1322 * Patch contributed by Michael Pichler May 15, 1995.
1324 #ifdef XFree86Server
1325 b
->swapgc
= CreateScratchGC(v
->display
, window
->depth
);
1329 dixChangeGC(NullClient
, b
->swapgc
, GCGraphicsExposures
, v
, NULL
);
1332 gcvalues
.graphics_exposures
= False
;
1333 b
->swapgc
= XCreateGC( v
->display
, window
,
1334 GCGraphicsExposures
, &gcvalues
);
1336 XMesaSetFunction( v
->display
, b
->swapgc
, GXcopy
);
1338 * Set fill style and tile pixmap once for all for HPCR stuff
1339 * (instead of doing it each time in clear_color_HPCR_pixmap())
1340 * Initialize whole stuff
1341 * Patch contributed by Jacques Leroy March 8, 1998.
1343 if (v
->hpcr_clear_flag
&& b
->buffer
!=XIMAGE
) {
1345 for (i
=0; i
<16; i
++)
1347 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 0, 0);
1348 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 1, 0);
1350 XMesaPutImage(b
->display
, (XMesaDrawable
)v
->hpcr_clear_pixmap
,
1351 b
->cleargc
, v
->hpcr_clear_ximage
, 0, 0, 0, 0, 16, 2);
1352 XMesaSetFillStyle( v
->display
, b
->cleargc
, FillTiled
);
1353 XMesaSetTile( v
->display
, b
->cleargc
, v
->hpcr_clear_pixmap
);
1356 /* Initialize the row buffer XImage for use in write_color_span() */
1357 #ifdef XFree86Server
1358 b
->rowimage
= XMesaCreateImage(GET_VISUAL_DEPTH(v
), MAX_WIDTH
, 1,
1359 (char *)MALLOC(MAX_WIDTH
*4));
1361 b
->rowimage
= XCreateImage( v
->display
,
1364 ZPixmap
, 0, /*format, offset*/
1365 (char*) MALLOC(MAX_WIDTH
*4), /*data*/
1366 MAX_WIDTH
, 1, /*width, height*/
1368 0 /*bytes_per_line*/ );
1380 * Convert an RGBA color to a pixel value.
1383 xmesa_color_to_pixel( XMesaContext xmesa
, GLubyte r
, GLubyte g
, GLubyte b
, GLubyte a
,
1386 switch (pixelFormat
) {
1392 PACK_TRUECOLOR( p
, r
, g
, b
);
1396 return PACK_8A8B8G8R( r
, g
, b
, a
);
1398 return PACK_8A8R8G8B( r
, g
, b
, a
);
1402 return PACK_8R8G8B( r
, g
, b
);
1404 return PACK_5R6G5B( r
, g
, b
);
1408 return DITHER( 1, 0, r
, g
, b
);
1411 /* 382 = (3*255)/2 */
1412 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
1414 return DITHER_HPCR(1, 1, r
, g
, b
);
1418 return LOOKUP( r
, g
, b
);
1421 return GRAY_RGB( r
, g
, b
);
1422 case PF_Dither_True
:
1424 case PF_Dither_5R6G5B
:
1427 PACK_TRUEDITHER(p
, 1, 0, r
, g
, b
);
1431 _mesa_problem(NULL
, "Bad pixel format in xmesa_color_to_pixel");
1437 #define NUM_VISUAL_TYPES 6
1440 * Convert an X visual type to a GLX visual type.
1442 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
1444 * \return If \c visualType is a valid X visual type, a GLX visual type will
1445 * be returned. Otherwise \c GLX_NONE will be returned.
1448 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
1452 xmesa_convert_from_x_visual_type( int visualType
)
1454 static const int glx_visual_types
[ NUM_VISUAL_TYPES
] = {
1455 GLX_STATIC_GRAY
, GLX_GRAY_SCALE
,
1456 GLX_STATIC_COLOR
, GLX_PSEUDO_COLOR
,
1457 GLX_TRUE_COLOR
, GLX_DIRECT_COLOR
1460 return ( (unsigned) visualType
< NUM_VISUAL_TYPES
)
1461 ? glx_visual_types
[ visualType
] : GLX_NONE
;
1465 /**********************************************************************/
1466 /***** Public Functions *****/
1467 /**********************************************************************/
1471 * Create a new X/Mesa visual.
1472 * Input: display - X11 display
1473 * visinfo - an XVisualInfo pointer
1474 * rgb_flag - GL_TRUE = RGB mode,
1475 * GL_FALSE = color index mode
1476 * alpha_flag - alpha buffer requested?
1477 * db_flag - GL_TRUE = double-buffered,
1478 * GL_FALSE = single buffered
1479 * stereo_flag - stereo visual?
1480 * ximage_flag - GL_TRUE = use an XImage for back buffer,
1481 * GL_FALSE = use an off-screen pixmap for back buffer
1482 * depth_size - requested bits/depth values, or zero
1483 * stencil_size - requested bits/stencil values, or zero
1484 * accum_red_size - requested bits/red accum values, or zero
1485 * accum_green_size - requested bits/green accum values, or zero
1486 * accum_blue_size - requested bits/blue accum values, or zero
1487 * accum_alpha_size - requested bits/alpha accum values, or zero
1488 * num_samples - number of samples/pixel if multisampling, or zero
1489 * level - visual level, usually 0
1490 * visualCaveat - ala the GLX extension, usually GLX_NONE
1491 * Return; a new XMesaVisual or 0 if error.
1493 XMesaVisual
XMesaCreateVisual( XMesaDisplay
*display
,
1494 XMesaVisualInfo visinfo
,
1496 GLboolean alpha_flag
,
1498 GLboolean stereo_flag
,
1499 GLboolean ximage_flag
,
1502 GLint accum_red_size
,
1503 GLint accum_green_size
,
1504 GLint accum_blue_size
,
1505 GLint accum_alpha_size
,
1508 GLint visualCaveat
)
1512 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1514 /* For debugging only */
1515 if (_mesa_getenv("MESA_XSYNC")) {
1516 /* This makes debugging X easier.
1517 * In your debugger, set a breakpoint on _XError to stop when an
1518 * X protocol error is generated.
1520 #ifdef XFree86Server
1523 XSynchronize( display
, 1 );
1527 v
= (XMesaVisual
) CALLOC_STRUCT(xmesa_visual
);
1533 * In the X server, NULL is passed in for the display. It will have
1534 * to be set before using this visual. See XMesaSetVisualDisplay()
1537 v
->display
= display
;
1539 /* Save a copy of the XVisualInfo struct because the user may XFREE()
1540 * the struct but we may need some of the information contained in it
1543 #ifndef XFree86Server
1544 v
->visinfo
= (XVisualInfo
*) MALLOC(sizeof(*visinfo
));
1549 MEMCPY(v
->visinfo
, visinfo
, sizeof(*visinfo
));
1552 /* check for MESA_GAMMA environment variable */
1553 gamma
= _mesa_getenv("MESA_GAMMA");
1555 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 0.0;
1556 sscanf( gamma
, "%f %f %f", &v
->RedGamma
, &v
->GreenGamma
, &v
->BlueGamma
);
1557 if (v
->RedGamma
<=0.0) v
->RedGamma
= 1.0;
1558 if (v
->GreenGamma
<=0.0) v
->GreenGamma
= v
->RedGamma
;
1559 if (v
->BlueGamma
<=0.0) v
->BlueGamma
= v
->RedGamma
;
1562 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 1.0;
1565 v
->ximage_flag
= ximage_flag
;
1567 #ifdef XFree86Server
1568 /* We could calculate these values by ourselves. nplanes is either the sum
1569 * of the red, green, and blue bits or the number index bits.
1570 * ColormapEntries is either (1U << index_bits) or
1571 * (1U << max(redBits, greenBits, blueBits)).
1573 v
->nplanes
= visinfo
->nplanes
;
1574 v
->ColormapEntries
= visinfo
->ColormapEntries
;
1576 v
->mesa_visual
.redMask
= visinfo
->redMask
;
1577 v
->mesa_visual
.greenMask
= visinfo
->greenMask
;
1578 v
->mesa_visual
.blueMask
= visinfo
->blueMask
;
1579 v
->mesa_visual
.visualID
= visinfo
->vid
;
1580 v
->mesa_visual
.screen
= 0; /* FIXME: What should be done here? */
1582 v
->mesa_visual
.redMask
= visinfo
->red_mask
;
1583 v
->mesa_visual
.greenMask
= visinfo
->green_mask
;
1584 v
->mesa_visual
.blueMask
= visinfo
->blue_mask
;
1585 v
->mesa_visual
.visualID
= visinfo
->visualid
;
1586 v
->mesa_visual
.screen
= visinfo
->screen
;
1589 #if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
1590 v
->mesa_visual
.visualType
= xmesa_convert_from_x_visual_type(visinfo
->class);
1592 v
->mesa_visual
.visualType
= xmesa_convert_from_x_visual_type(visinfo
->c_class
);
1595 v
->mesa_visual
.visualRating
= visualCaveat
;
1597 (void) initialize_visual_and_buffer( 0, v
, NULL
, rgb_flag
, 0, 0 );
1600 const int xclass
= v
->mesa_visual
.visualType
;
1601 if (xclass
==GLX_TRUE_COLOR
|| xclass
==GLX_DIRECT_COLOR
) {
1602 red_bits
= bitcount(GET_REDMASK(v
));
1603 green_bits
= bitcount(GET_GREENMASK(v
));
1604 blue_bits
= bitcount(GET_BLUEMASK(v
));
1608 /* this is an approximation */
1610 depth
= GET_VISUAL_DEPTH(v
);
1611 red_bits
= depth
/ 3;
1613 green_bits
= depth
/ 2;
1614 depth
-= green_bits
;
1617 assert( red_bits
+ green_bits
+ blue_bits
== GET_VISUAL_DEPTH(v
) );
1621 if (alpha_flag
&& alpha_bits
== 0)
1624 _mesa_initialize_visual( &v
->mesa_visual
,
1625 rgb_flag
, db_flag
, stereo_flag
,
1626 red_bits
, green_bits
,
1627 blue_bits
, alpha_bits
,
1628 v
->mesa_visual
.indexBits
,
1631 accum_red_size
, accum_green_size
,
1632 accum_blue_size
, accum_alpha_size
,
1635 /* XXX minor hack */
1636 v
->mesa_visual
.level
= level
;
1641 void XMesaSetVisualDisplay( XMesaDisplay
*dpy
, XMesaVisual v
)
1647 void XMesaDestroyVisual( XMesaVisual v
)
1649 #ifndef XFree86Server
1658 * Create a new XMesaContext.
1659 * \param v the XMesaVisual
1660 * \param share_list another XMesaContext with which to share display
1661 * lists or NULL if no sharing is wanted.
1662 * \return an XMesaContext or NULL if error.
1664 XMesaContext
XMesaCreateContext( XMesaVisual v
, XMesaContext share_list
)
1666 static GLboolean firstTime
= GL_TRUE
;
1669 struct dd_function_table functions
;
1673 _glthread_INIT_MUTEX(_xmesa_lock
);
1674 firstTime
= GL_FALSE
;
1677 /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
1678 c
= (XMesaContext
) CALLOC_STRUCT(xmesa_context
);
1682 mesaCtx
= &(c
->mesa
);
1684 /* initialize with default driver functions, then plug in XMesa funcs */
1685 _mesa_init_driver_functions(&functions
);
1686 xmesa_init_driver_functions(v
, &functions
);
1687 if (!_mesa_initialize_context(mesaCtx
, &v
->mesa_visual
,
1688 share_list
? &(share_list
->mesa
) : (GLcontext
*) NULL
,
1689 &functions
, (void *) c
)) {
1694 _mesa_enable_sw_extensions(mesaCtx
);
1695 _mesa_enable_1_3_extensions(mesaCtx
);
1696 _mesa_enable_1_4_extensions(mesaCtx
);
1697 _mesa_enable_1_5_extensions(mesaCtx
);
1698 _mesa_enable_2_0_extensions(mesaCtx
);
1701 _mesa_enable_extension(c
, "GL_EXT_texture_compression_s3tc");
1702 _mesa_enable_extension(c
, "GL_S3_s3tc");
1704 _mesa_enable_extension(c
, "GL_3DFX_texture_compression_FXT1");
1707 /* finish up xmesa context initializations */
1708 c
->swapbytes
= CHECK_BYTE_ORDER(v
) ? GL_FALSE
: GL_TRUE
;
1710 c
->xm_draw_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1711 c
->xm_read_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1712 c
->xm_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1713 c
->display
= v
->display
;
1714 c
->pixelformat
= v
->dithered_pf
; /* Dithering is enabled by default */
1716 /* Initialize the software rasterizer and helper modules.
1718 if (!_swrast_CreateContext( mesaCtx
) ||
1719 !_ac_CreateContext( mesaCtx
) ||
1720 !_tnl_CreateContext( mesaCtx
) ||
1721 !_swsetup_CreateContext( mesaCtx
)) {
1722 _mesa_free_context_data(&c
->mesa
);
1728 tnl
= TNL_CONTEXT(mesaCtx
);
1729 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
1731 xmesa_register_swrast_functions( mesaCtx
);
1732 _swsetup_Wakeup(mesaCtx
);
1739 void XMesaDestroyContext( XMesaContext c
)
1741 GLcontext
*mesaCtx
= &c
->mesa
;
1743 if (c
->xm_draw_buffer
&& c
->xm_buffer
->FXctx
)
1744 fxMesaDestroyContext(c
->xm_draw_buffer
->FXctx
);
1746 _swsetup_DestroyContext( mesaCtx
);
1747 _swrast_DestroyContext( mesaCtx
);
1748 _tnl_DestroyContext( mesaCtx
);
1749 _ac_DestroyContext( mesaCtx
);
1750 _mesa_free_context_data( mesaCtx
);
1757 * XXX this isn't a public function! It's a hack for the 3Dfx driver.
1758 * Create a new XMesaBuffer from an X window.
1759 * Input: v - the XMesaVisual
1762 * Return: new XMesaBuffer or NULL if error
1765 XMesaCreateWindowBuffer2(XMesaVisual v
, XMesaWindow w
, XMesaContext c
)
1767 #ifndef XFree86Server
1768 XWindowAttributes attr
;
1780 /* Check that window depth matches visual depth */
1781 #ifdef XFree86Server
1782 client
= CLIENT_ID(((XMesaDrawable
)w
)->id
);
1784 if (GET_VISUAL_DEPTH(v
) != ((XMesaDrawable
)w
)->depth
) {
1785 _mesa_warning(NULL
, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1786 GET_VISUAL_DEPTH(v
), ((XMesaDrawable
) w
)->depth
);
1790 XGetWindowAttributes( v
->display
, w
, &attr
);
1792 if (GET_VISUAL_DEPTH(v
) != attr
.depth
) {
1793 _mesa_warning(NULL
, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1794 GET_VISUAL_DEPTH(v
), attr
.depth
);
1800 #ifdef XFree86Server
1801 cmap
= (ColormapPtr
)LookupIDByType(wColormap(w
), RT_COLORMAP
);
1803 if (attr
.colormap
) {
1804 cmap
= attr
.colormap
;
1807 _mesa_warning(NULL
, "Window %u has no colormap!\n", (unsigned int) w
);
1808 /* this is weird, a window w/out a colormap!? */
1809 /* OK, let's just allocate a new one and hope for the best */
1810 cmap
= XCreateColormap(v
->display
, w
, attr
.visual
, AllocNone
);
1814 b
= alloc_xmesa_buffer(v
, WINDOW
, cmap
);
1819 if (!initialize_visual_and_buffer( client
, v
, b
, v
->mesa_visual
.rgbMode
,
1820 (XMesaDrawable
)w
, cmap
)) {
1821 free_xmesa_buffer(client
, b
);
1826 fxEnvVar
= _mesa_getenv("MESA_GLX_FX");
1828 if (fxEnvVar
[0]!='d') {
1832 if (v
->mesa_visual
.depthBits
> 0) {
1833 attribs
[numAttribs
++] = FXMESA_DEPTH_SIZE
;
1834 attribs
[numAttribs
++] = v
->mesa_visual
.depthBits
;
1836 if (v
->mesa_visual
.doubleBufferMode
) {
1837 attribs
[numAttribs
++] = FXMESA_DOUBLEBUFFER
;
1839 if (v
->mesa_visual
.accumRedBits
> 0) {
1840 attribs
[numAttribs
++] = FXMESA_ACCUM_SIZE
;
1841 attribs
[numAttribs
++] = v
->mesa_visual
.accumRedBits
;
1843 if (v
->mesa_visual
.stencilBits
> 0) {
1844 attribs
[numAttribs
++] = FXMESA_STENCIL_SIZE
;
1845 attribs
[numAttribs
++] = v
->mesa_visual
.stencilBits
;
1847 if (v
->mesa_visual
.alphaBits
> 0) {
1848 attribs
[numAttribs
++] = FXMESA_ALPHA_SIZE
;
1849 attribs
[numAttribs
++] = v
->mesa_visual
.alphaBits
;
1852 attribs
[numAttribs
++] = FXMESA_SHARE_CONTEXT
;
1853 attribs
[numAttribs
++] = (int) &(c
->mesa
);
1855 attribs
[numAttribs
++] = FXMESA_NONE
;
1857 /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
1858 hw
= fxMesaSelectCurrentBoard(0);
1860 /* if these fail, there's a new bug somewhere */
1861 ASSERT(b
->mesa_buffer
.Width
> 0);
1862 ASSERT(b
->mesa_buffer
.Height
> 0);
1864 if ((hw
== GR_SSTTYPE_VOODOO
) || (hw
== GR_SSTTYPE_Voodoo2
)) {
1865 b
->FXctx
= fxMesaCreateBestContext(0, b
->mesa_buffer
.Width
,
1866 b
->mesa_buffer
.Height
, attribs
);
1867 if ((v
->undithered_pf
!=PF_Index
) && (b
->backimage
)) {
1868 b
->FXisHackUsable
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1869 if (b
->FXctx
&& (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')) {
1870 b
->FXwindowHack
= GL_TRUE
;
1871 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
1874 b
->FXwindowHack
= GL_FALSE
;
1879 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1880 b
->FXctx
= fxMesaCreateContext(w
, GR_RESOLUTION_NONE
,
1881 GR_REFRESH_75Hz
, attribs
);
1883 b
->FXctx
= fxMesaCreateBestContext(0, b
->mesa_buffer
.Width
,
1884 b
->mesa_buffer
.Height
, attribs
);
1885 b
->FXisHackUsable
= GL_FALSE
;
1886 b
->FXwindowHack
= GL_FALSE
;
1890 "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1891 hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
1896 _mesa_warning(NULL
, "WARNING: This Mesa Library includes the Glide driver but\n");
1897 _mesa_warning(NULL
, " you have not defined the MESA_GLX_FX env. var.\n");
1898 _mesa_warning(NULL
, " (check the README.3DFX file for more information).\n\n");
1899 _mesa_warning(NULL
, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1908 XMesaCreateWindowBuffer(XMesaVisual v
, XMesaWindow w
)
1910 return XMesaCreateWindowBuffer2( v
, w
, NULL
);
1915 * Create a new XMesaBuffer from an X pixmap.
1917 * \param v the XMesaVisual
1918 * \param p the pixmap
1919 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1920 * \c GLX_DIRECT_COLOR visual for the pixmap
1921 * \returns new XMesaBuffer or NULL if error
1924 XMesaCreatePixmapBuffer(XMesaVisual v
, XMesaPixmap p
, XMesaColormap cmap
)
1931 b
= alloc_xmesa_buffer(v
, PIXMAP
, cmap
);
1936 #ifdef XFree86Server
1937 client
= CLIENT_ID(((XMesaDrawable
)p
)->id
);
1940 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1941 (XMesaDrawable
)p
, cmap
)) {
1942 free_xmesa_buffer(client
, b
);
1952 XMesaCreatePBuffer(XMesaVisual v
, XMesaColormap cmap
,
1953 unsigned int width
, unsigned int height
)
1955 #ifdef XFree86Server
1960 XMesaDrawable drawable
; /* X Pixmap Drawable */
1963 b
= alloc_xmesa_buffer(v
, PBUFFER
, cmap
);
1968 /* allocate pixmap for front buffer */
1969 root
= RootWindow( v
->display
, v
->visinfo
->screen
);
1970 drawable
= XCreatePixmap( v
->display
, root
, width
, height
, v
->visinfo
->depth
);
1972 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1974 free_xmesa_buffer(client
, b
);
1985 * Deallocate an XMesaBuffer structure and all related info.
1987 void XMesaDestroyBuffer( XMesaBuffer b
)
1991 #ifdef XFree86Server
1993 client
= CLIENT_ID(b
->frontbuffer
->id
);
1996 if (b
->gc
) XMesaFreeGC( b
->xm_visual
->display
, b
->gc
);
1997 if (b
->cleargc
) XMesaFreeGC( b
->xm_visual
->display
, b
->cleargc
);
1998 if (b
->swapgc
) XMesaFreeGC( b
->xm_visual
->display
, b
->swapgc
);
2001 #if defined(USE_XSHM) && !defined(XFree86Server)
2003 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
2004 XDestroyImage( b
->backimage
);
2005 shmdt( b
->shminfo
.shmaddr
);
2009 XMesaDestroyImage( b
->backimage
);
2011 if (b
->backpixmap
) {
2012 XMesaFreePixmap( b
->xm_visual
->display
, b
->backpixmap
);
2013 if (b
->xm_visual
->hpcr_clear_flag
) {
2014 XMesaFreePixmap( b
->xm_visual
->display
,
2015 b
->xm_visual
->hpcr_clear_pixmap
);
2016 XMesaDestroyImage( b
->xm_visual
->hpcr_clear_ximage
);
2020 FREE( b
->rowimage
->data
);
2021 b
->rowimage
->data
= NULL
;
2022 XMesaDestroyImage( b
->rowimage
);
2025 free_xmesa_buffer(client
, b
);
2031 * Bind buffer b to context c and make c the current rendering context.
2033 GLboolean
XMesaMakeCurrent( XMesaContext c
, XMesaBuffer b
)
2035 return XMesaMakeCurrent2( c
, b
, b
);
2040 * Bind buffer b to context c and make c the current rendering context.
2042 GLboolean
XMesaMakeCurrent2( XMesaContext c
, XMesaBuffer drawBuffer
,
2043 XMesaBuffer readBuffer
)
2046 if (!drawBuffer
|| !readBuffer
)
2047 return GL_FALSE
; /* must specify buffers! */
2050 if (drawBuffer
->FXctx
) {
2051 fxMesaMakeCurrent(drawBuffer
->FXctx
);
2053 c
->xm_draw_buffer
= drawBuffer
;
2054 c
->xm_read_buffer
= readBuffer
;
2055 c
->xm_buffer
= drawBuffer
;
2060 if (&(c
->mesa
) == _mesa_get_current_context()
2061 && c
->xm_draw_buffer
== drawBuffer
2062 && c
->xm_read_buffer
== readBuffer
2063 && c
->xm_draw_buffer
->wasCurrent
) {
2064 /* same context and buffer, do nothing */
2068 c
->xm_draw_buffer
= drawBuffer
;
2069 c
->xm_read_buffer
= readBuffer
;
2070 c
->xm_buffer
= drawBuffer
;
2072 _mesa_make_current2(&(c
->mesa
),
2073 &drawBuffer
->mesa_buffer
,
2074 &readBuffer
->mesa_buffer
);
2076 if (c
->xm_visual
->mesa_visual
.rgbMode
) {
2078 * Must recompute and set these pixel values because colormap
2079 * can be different for different windows.
2081 c
->clearpixel
= xmesa_color_to_pixel( c
,
2086 c
->xm_visual
->undithered_pf
);
2087 XMesaSetForeground(c
->display
, c
->xm_draw_buffer
->cleargc
, c
->clearpixel
);
2090 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2091 c
->xm_draw_buffer
->wasCurrent
= GL_TRUE
;
2095 _mesa_make_current2( NULL
, NULL
, NULL
);
2102 * Unbind the context c from its buffer.
2104 GLboolean
XMesaUnbindContext( XMesaContext c
)
2106 /* A no-op for XFree86 integration purposes */
2111 XMesaContext
XMesaGetCurrentContext( void )
2113 GET_CURRENT_CONTEXT(ctx
);
2115 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
2124 XMesaBuffer
XMesaGetCurrentBuffer( void )
2126 GET_CURRENT_CONTEXT(ctx
);
2128 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
2129 return xmesa
->xm_draw_buffer
;
2137 /* New in Mesa 3.1 */
2138 XMesaBuffer
XMesaGetCurrentReadBuffer( void )
2140 GET_CURRENT_CONTEXT(ctx
);
2142 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
2143 return xmesa
->xm_read_buffer
;
2151 GLboolean
XMesaForceCurrent(XMesaContext c
)
2154 if (&(c
->mesa
) != _mesa_get_current_context()) {
2155 _mesa_make_current(&(c
->mesa
), &c
->xm_draw_buffer
->mesa_buffer
);
2159 _mesa_make_current(NULL
, NULL
);
2165 GLboolean
XMesaLoseCurrent(XMesaContext c
)
2168 _mesa_make_current(NULL
, NULL
);
2174 * Switch 3Dfx support hack between window and full-screen mode.
2176 GLboolean
XMesaSetFXmode( GLint mode
)
2179 const char *fx
= _mesa_getenv("MESA_GLX_FX");
2180 if (fx
&& fx
[0] != 'd') {
2181 GET_CURRENT_CONTEXT(ctx
);
2182 GrHwConfiguration hw
;
2183 if (!FX_grSstQueryHardware(&hw
)) {
2184 /*fprintf(stderr, "!grSstQueryHardware\n");*/
2187 if (hw
.num_sst
< 1) {
2188 /*fprintf(stderr, "hw.num_sst < 1\n");*/
2192 /* [dBorca] Hack alert:
2193 * oh, this is sooo wrong: ctx above is
2194 * really an fxMesaContext, not an XMesaContext
2196 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
2197 if (mode
== XMESA_FX_WINDOW
) {
2198 if (xmesa
->xm_draw_buffer
->FXisHackUsable
) {
2199 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
2200 xmesa
->xm_draw_buffer
->FXwindowHack
= GL_TRUE
;
2204 else if (mode
== XMESA_FX_FULLSCREEN
) {
2205 FX_grSstControl(GR_CONTROL_ACTIVATE
);
2206 xmesa
->xm_draw_buffer
->FXwindowHack
= GL_FALSE
;
2210 /* Error: Bad mode value */
2214 /*fprintf(stderr, "fallthrough\n");*/
2225 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2227 static void FXgetImage( XMesaBuffer b
)
2229 GET_CURRENT_CONTEXT(ctx
);
2230 static unsigned short pixbuf
[MAX_WIDTH
];
2234 unsigned int bw
, depth
, width
, height
;
2235 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
2237 #ifdef XFree86Server
2238 x
= b
->frontbuffer
->x
;
2239 y
= b
->frontbuffer
->y
;
2240 width
= b
->frontbuffer
->width
;
2241 height
= b
->frontbuffer
->height
;
2242 depth
= b
->frontbuffer
->depth
;
2244 XGetGeometry( b
->xm_visual
->display
, b
->frontbuffer
,
2245 &root
, &xpos
, &ypos
, &width
, &height
, &bw
, &depth
);
2247 if (b
->mesa_buffer
.Width
!= width
|| b
->mesa_buffer
.Height
!= height
) {
2248 b
->mesa_buffer
.Width
= MIN2((int)width
, b
->FXctx
->width
);
2249 b
->mesa_buffer
.Height
= MIN2((int)height
, b
->FXctx
->height
);
2250 if (b
->mesa_buffer
.Width
& 1)
2251 b
->mesa_buffer
.Width
--; /* prevent odd width */
2252 xmesa_alloc_back_buffer( b
);
2255 /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
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
->mesa_buffer
.Height
, /*pos*/
2261 b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
, /* size */
2262 b
->mesa_buffer
.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
->mesa_buffer
.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
->mesa_buffer
.Height
-y
),
2276 b
->mesa_buffer
.Width
, 1,
2280 /* write to XImage back buffer */
2281 for (x
=0;x
<b
->mesa_buffer
.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
->mesa_buffer
.Height
;y
++) {
2292 /* read row from 3Dfx frame buffer */
2293 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
,
2294 0, b
->FXctx
->height
-(b
->mesa_buffer
.Height
-y
),
2295 b
->mesa_buffer
.Width
, 1,
2299 /* write to XImage back buffer */
2300 for (x
=0;x
<b
->mesa_buffer
.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
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
,
2351 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2356 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2357 XMesaPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2360 0, 0, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
);
2361 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2365 /* Copy pixmap to window on server */
2366 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2367 XMesaCopyArea( b
->xm_visual
->display
,
2368 b
->backpixmap
, /* source drawable */
2369 b
->frontbuffer
, /* dest. drawable */
2371 0, 0, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
,
2372 0, 0 /* dest region */
2374 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2377 #if !defined(XFree86Server)
2378 XSync( b
->xm_visual
->display
, False
);
2385 * Copy sub-region of back buffer to front buffer
2387 void XMesaCopySubBuffer( XMesaBuffer b
, int x
, int y
, int width
, int height
)
2389 GET_CURRENT_CONTEXT(ctx
);
2391 /* If we're swapping the buffer associated with the current context
2392 * we have to flush any pending rendering commands first.
2394 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
2395 _mesa_notifySwapBuffers(ctx
);
2398 int yTop
= b
->mesa_buffer
.Height
- y
- height
;
2401 fxMesaSwapBuffers();
2402 if (b
->FXwindowHack
)
2409 /* Copy Ximage from host's memory to server's window */
2410 #if defined(USE_XSHM) && !defined(XFree86Server)
2412 /* XXX assuming width and height aren't too large! */
2413 XShmPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2415 b
->backimage
, x
, yTop
,
2416 x
, yTop
, width
, height
, False
);
2417 /* wait for finished event??? */
2422 /* XXX assuming width and height aren't too large! */
2423 XMesaPutImage( b
->xm_visual
->display
, b
->frontbuffer
,
2425 b
->backimage
, x
, yTop
,
2426 x
, yTop
, width
, height
);
2430 /* Copy pixmap to window on server */
2431 XMesaCopyArea( b
->xm_visual
->display
,
2432 b
->backpixmap
, /* source drawable */
2433 b
->frontbuffer
, /* dest. drawable */
2435 x
, yTop
, width
, height
, /* source region */
2436 x
, yTop
/* dest region */
2444 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
2445 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2446 * back buffer directly.
2447 * Output: pixmap - pointer to back buffer's Pixmap, or 0
2448 * ximage - pointer to back buffer's XImage, or NULL
2449 * Return: GL_TRUE = context is double buffered
2450 * GL_FALSE = context is single buffered
2452 GLboolean
XMesaGetBackBuffer( XMesaBuffer b
,
2453 XMesaPixmap
*pixmap
,
2454 XMesaImage
**ximage
)
2457 if (pixmap
) *pixmap
= b
->backpixmap
;
2458 if (ximage
) *ximage
= b
->backimage
;
2470 * Return the depth buffer associated with an XMesaBuffer.
2471 * Input: b - the XMesa buffer handle
2472 * Output: width, height - size of buffer in pixels
2473 * bytesPerValue - bytes per depth value (2 or 4)
2474 * buffer - pointer to depth buffer values
2475 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
2477 GLboolean
XMesaGetDepthBuffer( XMesaBuffer b
, GLint
*width
, GLint
*height
,
2478 GLint
*bytesPerValue
, void **buffer
)
2480 if (!b
->mesa_buffer
.DepthBuffer
) {
2488 *width
= b
->mesa_buffer
.Width
;
2489 *height
= b
->mesa_buffer
.Height
;
2490 *bytesPerValue
= b
->mesa_buffer
.Visual
.depthBits
<= 16
2491 ? sizeof(GLushort
) : sizeof(GLuint
);
2492 *buffer
= b
->mesa_buffer
.DepthBuffer
;
2498 void XMesaFlush( XMesaContext c
)
2500 if (c
&& c
->xm_visual
) {
2501 #ifdef XFree86Server
2504 XSync( c
->xm_visual
->display
, False
);
2511 const char *XMesaGetString( XMesaContext c
, int name
)
2514 if (name
==XMESA_VERSION
) {
2517 else if (name
==XMESA_EXTENSIONS
) {
2527 XMesaBuffer
XMesaFindBuffer( XMesaDisplay
*dpy
, XMesaDrawable d
)
2530 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
2531 if (b
->frontbuffer
==d
&& b
->display
==dpy
) {
2541 * Look for XMesaBuffers whose X window has been destroyed.
2542 * Deallocate any such XMesaBuffers.
2544 void XMesaGarbageCollect( void )
2546 XMesaBuffer b
, next
;
2547 for (b
=XMesaBufferList
; b
; b
=next
) {
2549 if (b
->display
&& b
->frontbuffer
&& b
->type
== WINDOW
) {
2550 #ifdef XFree86Server
2553 XSync(b
->display
, False
);
2554 if (!window_exists( b
->display
, b
->frontbuffer
)) {
2555 /* found a dead window, free the ancillary info */
2556 XMesaDestroyBuffer( b
);
2564 void XMesaReset( void )
2566 while (XMesaBufferList
)
2567 XMesaDestroyBuffer(XMesaBufferList
);
2569 XMesaBufferList
= NULL
;
2573 unsigned long XMesaDitherColor( XMesaContext xmesa
, GLint x
, GLint y
,
2574 GLfloat red
, GLfloat green
,
2575 GLfloat blue
, GLfloat alpha
)
2577 GLint r
= (GLint
) (red
* 255.0F
);
2578 GLint g
= (GLint
) (green
* 255.0F
);
2579 GLint b
= (GLint
) (blue
* 255.0F
);
2580 GLint a
= (GLint
) (alpha
* 255.0F
);
2582 switch (xmesa
->pixelformat
) {
2588 PACK_TRUECOLOR( p
, r
, g
, b
);
2592 return PACK_8A8B8G8R( r
, g
, b
, a
);
2594 return PACK_8A8R8G8B( r
, g
, b
, a
);
2596 return PACK_8R8G8B( r
, g
, b
);
2598 return PACK_5R6G5B( r
, g
, b
);
2602 return DITHER( x
, y
, r
, g
, b
);
2605 /* 382 = (3*255)/2 */
2606 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
2608 return DITHER_HPCR(x
, y
, r
, g
, b
);
2612 return LOOKUP( r
, g
, b
);
2615 return GRAY_RGB( r
, g
, b
);
2616 case PF_Dither_5R6G5B
:
2618 case PF_Dither_True
:
2621 PACK_TRUEDITHER(p
, x
, y
, r
, g
, b
);
2625 _mesa_problem(NULL
, "Bad pixel format in XMesaDitherColor");
2632 * This is typically called when the window size changes and we need
2633 * to reallocate the buffer's back/depth/stencil/accum buffers.
2635 void XMesaResizeBuffers( XMesaBuffer b
)
2637 xmesa_resize_buffers( &(b
->mesa_buffer
) );