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"
68 #include "framebuffer.h"
74 #include "renderbuffer.h"
75 #include "texformat.h"
78 #include "swrast/swrast.h"
79 #include "swrast_setup/swrast_setup.h"
80 #include "array_cache/acache.h"
82 #include "tnl/t_context.h"
83 #include "tnl/t_pipeline.h"
84 #include "drivers/common/driverfuncs.h"
87 #include <GL/glxtokens.h>
91 * Global X driver lock
93 _glthread_Mutex _xmesa_lock
;
98 * Lookup tables for HPCR pixel format:
100 static short hpcr_rgbTbl
[3][256] = {
102 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
103 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
104 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
105 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
106 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
107 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
108 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
109 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
110 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
111 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
112 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
113 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
114 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
115 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
116 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
117 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
120 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
121 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
122 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
123 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
124 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
125 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
126 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
127 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
128 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
129 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
130 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
131 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
132 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
133 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
134 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
135 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
138 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
139 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
140 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55,
141 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
142 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
143 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79,
144 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87,
145 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
146 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
147 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
148 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
149 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
150 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
151 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
152 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
153 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
159 /**********************************************************************/
160 /***** X Utility Functions *****/
161 /**********************************************************************/
165 * Return the host's byte order as LSBFirst or MSBFirst ala X.
167 #ifndef XFree86Server
168 static int host_byte_order( void )
171 char *cptr
= (char *) &i
;
172 return (*cptr
==1) ? LSBFirst
: MSBFirst
;
180 #ifndef XFree86Server
181 static volatile int mesaXErrorFlag
= 0;
183 static int mesaHandleXError( XMesaDisplay
*dpy
, XErrorEvent
*event
)
194 * Check if the X Shared Memory extension is available.
195 * Return: 0 = not available
196 * 1 = shared XImage support available
197 * 2 = shared Pixmap support available also
199 #ifndef XFree86Server
200 static int check_for_xshm( XMesaDisplay
*display
)
203 int major
, minor
, ignore
;
206 if (XQueryExtension( display
, "MIT-SHM", &ignore
, &ignore
, &ignore
)) {
207 if (XShmQueryVersion( display
, &major
, &minor
, &pixmaps
)==True
) {
208 return (pixmaps
==True
) ? 2 : 1;
218 /* Can't compile XSHM support */
226 * Apply gamma correction to an intensity value in [0..max]. Return the
227 * new intensity value.
229 static GLint
gamma_adjust( GLfloat gamma
, GLint value
, GLint max
)
235 double x
= (double) value
/ (double) max
;
236 return IROUND_POS((GLfloat
) max
* _mesa_pow(x
, 1.0F
/gamma
));
243 * Return the true number of bits per pixel for XImages.
244 * For example, if we request a 24-bit deep visual we may actually need/get
245 * 32bpp XImages. This function returns the appropriate bpp.
246 * Input: dpy - the X display
247 * visinfo - desribes the visual to be used for XImages
248 * Return: true number of bits per pixel for XImages
252 static int bits_per_pixel( XMesaVisual xmv
)
254 const int depth
= xmv
->nplanes
;
256 for (i
= 0; i
< screenInfo
.numPixmapFormats
; i
++) {
257 if (screenInfo
.formats
[i
].depth
== depth
)
258 return screenInfo
.formats
[i
].bitsPerPixel
;
260 return depth
; /* should never get here, but this should be safe */
265 static int bits_per_pixel( XMesaVisual xmv
)
267 XMesaDisplay
*dpy
= xmv
->display
;
268 XMesaVisualInfo visinfo
= xmv
->visinfo
;
271 /* Create a temporary XImage */
272 img
= XCreateImage( dpy
, visinfo
->visual
, visinfo
->depth
,
273 ZPixmap
, 0, /*format, offset*/
274 (char*) MALLOC(8), /*data*/
275 1, 1, /*width, height*/
280 /* grab the bits/pixel value */
281 bitsPerPixel
= img
->bits_per_pixel
;
282 /* free the XImage */
283 _mesa_free( img
->data
);
285 XMesaDestroyImage( img
);
293 * Determine if a given X window ID is valid (window exists).
294 * Do this by calling XGetWindowAttributes() for the window and
295 * checking if we catch an X error.
296 * Input: dpy - the display
297 * win - the window to check for existance
298 * Return: GL_TRUE - window exists
299 * GL_FALSE - window doesn't exist
301 #ifndef XFree86Server
302 static GLboolean WindowExistsFlag
;
304 static int window_exists_err_handler( XMesaDisplay
* dpy
, XErrorEvent
* xerr
)
307 if (xerr
->error_code
== BadWindow
) {
308 WindowExistsFlag
= GL_FALSE
;
313 static GLboolean
window_exists( XMesaDisplay
*dpy
, Window win
)
315 XWindowAttributes wa
;
316 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
317 WindowExistsFlag
= GL_TRUE
;
318 old_handler
= XSetErrorHandler(window_exists_err_handler
);
319 XGetWindowAttributes( dpy
, win
, &wa
); /* dummy request */
320 XSetErrorHandler(old_handler
);
321 return WindowExistsFlag
;
327 /**********************************************************************/
328 /***** Linked list of XMesaBuffers *****/
329 /**********************************************************************/
331 static XMesaBuffer XMesaBufferList
= NULL
;
335 * Allocate a new XMesaBuffer, initialize basic fields and add to
336 * the list of all buffers.
339 alloc_xmesa_buffer(XMesaVisual vis
, BufferType type
, XMesaColormap cmap
)
341 XMesaBuffer b
= (XMesaBuffer
) CALLOC_STRUCT(xmesa_buffer
);
343 b
->display
= vis
->display
;
348 _mesa_initialize_framebuffer(&b
->mesa_buffer
, &vis
->mesa_visual
);
350 /* determine back buffer implementation */
351 if (vis
->mesa_visual
.doubleBufferMode
) {
352 if (vis
->ximage_flag
) {
353 b
->db_state
= BACK_XIMAGE
;
356 b
->db_state
= BACK_PIXMAP
;
363 /* Allocate the framebuffer's renderbuffers */
364 assert(!b
->mesa_buffer
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
365 assert(!b
->mesa_buffer
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
367 /* front renderbuffer */
368 b
->frontxrb
= xmesa_new_renderbuffer(NULL
, 0, vis
->mesa_visual
.rgbMode
);
369 _mesa_add_renderbuffer(&b
->mesa_buffer
, BUFFER_FRONT_LEFT
,
372 /* back renderbuffer */
373 if (vis
->mesa_visual
.doubleBufferMode
) {
374 b
->backxrb
=xmesa_new_renderbuffer(NULL
, 0, vis
->mesa_visual
.rgbMode
);
375 _mesa_add_renderbuffer(&b
->mesa_buffer
, BUFFER_BACK_LEFT
,
379 _mesa_add_soft_renderbuffers(&b
->mesa_buffer
,
380 GL_FALSE
, /* color */
381 vis
->mesa_visual
.haveDepthBuffer
,
382 vis
->mesa_visual
.haveStencilBuffer
,
383 vis
->mesa_visual
.haveAccumBuffer
,
384 vis
->mesa_visual
.alphaBits
> 0,
385 vis
->mesa_visual
.numAuxBuffers
> 0 );
387 /* insert into linked list */
388 b
->Next
= XMesaBufferList
;
396 * Find an XMesaBuffer by matching X display and colormap but NOT matching
397 * the notThis buffer.
399 static XMesaBuffer
find_xmesa_buffer(XMesaDisplay
*dpy
,
404 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
405 if (b
->display
==dpy
&& b
->cmap
==cmap
&& b
!=notThis
) {
414 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
417 static void free_xmesa_buffer(int client
, XMesaBuffer buffer
)
419 XMesaBuffer prev
= NULL
, b
;
421 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
423 /* unlink bufer from list */
425 prev
->Next
= buffer
->Next
;
427 XMesaBufferList
= buffer
->Next
;
428 /* Check to free X colors */
429 if (buffer
->num_alloced
>0) {
430 /* If no other buffer uses this X colormap then free the colors. */
431 if (!find_xmesa_buffer(buffer
->display
, buffer
->cmap
, buffer
)) {
433 (void)FreeColors(buffer
->cmap
, client
,
434 buffer
->num_alloced
, buffer
->alloced_colors
,
437 XFreeColors(buffer
->display
, buffer
->cmap
,
438 buffer
->alloced_colors
, buffer
->num_alloced
, 0);
443 _mesa_free_framebuffer_data(&buffer
->mesa_buffer
);
444 /* delete front/back renderbuffers */
445 buffer
->frontxrb
->Base
.Delete(&(buffer
->frontxrb
->Base
));
447 buffer
->backxrb
->Base
.Delete(&(buffer
->backxrb
->Base
));
452 /* continue search */
455 /* buffer not found in XMesaBufferList */
456 _mesa_problem(NULL
,"free_xmesa_buffer() - buffer not found\n");
460 /* Copy X color table stuff from one XMesaBuffer to another. */
461 static void copy_colortable_info(XMesaBuffer dst
, const XMesaBuffer src
)
463 MEMCPY(dst
->color_table
, src
->color_table
, sizeof(src
->color_table
));
464 MEMCPY(dst
->pixel_to_r
, src
->pixel_to_r
, sizeof(src
->pixel_to_r
));
465 MEMCPY(dst
->pixel_to_g
, src
->pixel_to_g
, sizeof(src
->pixel_to_g
));
466 MEMCPY(dst
->pixel_to_b
, src
->pixel_to_b
, sizeof(src
->pixel_to_b
));
467 dst
->num_alloced
= src
->num_alloced
;
468 MEMCPY(dst
->alloced_colors
, src
->alloced_colors
,
469 sizeof(src
->alloced_colors
));
474 /**********************************************************************/
475 /***** Misc Private Functions *****/
476 /**********************************************************************/
480 * Return number of bits set in n.
482 static int bitcount( unsigned long n
)
485 for (bits
=0; n
>0; n
=n
>>1) {
496 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
497 * Return: GL_TRUE if success, GL_FALSE if error
499 #ifndef XFree86Server
501 alloc_shm_back_buffer(XMesaBuffer b
, GLuint width
, GLuint height
)
505 * We have to do a _lot_ of error checking here to be sure we can
506 * really use the XSHM extension. It seems different servers trigger
507 * errors at different points if the extension won't work. Therefore
508 * we have to be very careful...
511 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
513 if (width
== 0 || height
== 0) {
514 /* this will be true the first time we're called on 'b' */
518 b
->backxrb
->ximage
= XShmCreateImage(b
->xm_visual
->display
,
519 b
->xm_visual
->visinfo
->visual
,
520 b
->xm_visual
->visinfo
->depth
,
521 ZPixmap
, NULL
, &b
->shminfo
,
523 if (b
->backxrb
->ximage
== NULL
) {
524 _mesa_warning(NULL
, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
529 b
->shminfo
.shmid
= shmget( IPC_PRIVATE
, b
->backxrb
->ximage
->bytes_per_line
530 * b
->backxrb
->ximage
->height
, IPC_CREAT
|0777 );
531 if (b
->shminfo
.shmid
< 0) {
532 _mesa_warning(NULL
, "shmget failed while allocating back buffer");
533 XDestroyImage( b
->backxrb
->ximage
);
534 b
->backxrb
->ximage
= NULL
;
535 _mesa_warning(NULL
, "alloc_back_buffer: Shared memory error (shmget), disabling.");
540 b
->shminfo
.shmaddr
= b
->backxrb
->ximage
->data
541 = (char*)shmat( b
->shminfo
.shmid
, 0, 0 );
542 if (b
->shminfo
.shmaddr
== (char *) -1) {
543 _mesa_warning(NULL
, "shmat() failed while allocating back buffer");
544 XDestroyImage( b
->backxrb
->ximage
);
545 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
546 b
->backxrb
->ximage
= NULL
;
547 _mesa_warning(NULL
, "alloc_back_buffer: Shared memory error (shmat), disabling.");
552 b
->shminfo
.readOnly
= False
;
554 old_handler
= XSetErrorHandler( mesaHandleXError
);
555 /* This may trigger the X protocol error we're ready to catch: */
556 XShmAttach( b
->xm_visual
->display
, &b
->shminfo
);
557 XSync( b
->xm_visual
->display
, False
);
559 if (mesaXErrorFlag
) {
560 /* we are on a remote display, this error is normal, don't print it */
561 XFlush( b
->xm_visual
->display
);
563 XDestroyImage( b
->backxrb
->ximage
);
564 shmdt( b
->shminfo
.shmaddr
);
565 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
566 b
->backxrb
->ximage
= NULL
;
568 (void) XSetErrorHandler( old_handler
);
572 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 ); /* nobody else needs it */
574 /* Finally, try an XShmPutImage to be really sure the extension works */
575 gc
= XCreateGC( b
->xm_visual
->display
, b
->frontxrb
->pixmap
, 0, NULL
);
576 XShmPutImage( b
->xm_visual
->display
, b
->frontxrb
->pixmap
, gc
,
577 b
->backxrb
->ximage
, 0, 0, 0, 0, 1, 1 /*one pixel*/, False
);
578 XSync( b
->xm_visual
->display
, False
);
579 XFreeGC( b
->xm_visual
->display
, gc
);
580 (void) XSetErrorHandler( old_handler
);
581 if (mesaXErrorFlag
) {
582 XFlush( b
->xm_visual
->display
);
584 XDestroyImage( b
->backxrb
->ximage
);
585 shmdt( b
->shminfo
.shmaddr
);
586 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
587 b
->backxrb
->ximage
= NULL
;
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
607 xmesa_alloc_back_buffer( XMesaBuffer b
, GLuint width
, GLuint height
)
609 if (width
== 0 || height
== 0)
612 if (b
->db_state
== BACK_XIMAGE
) {
613 /* Deallocate the old backxrb->ximage, if any */
614 if (b
->backxrb
->ximage
) {
615 #if defined(USE_XSHM) && !defined(XFree86Server)
617 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
618 XDestroyImage( b
->backxrb
->ximage
);
619 shmdt( b
->shminfo
.shmaddr
);
623 XMesaDestroyImage( b
->backxrb
->ximage
);
624 b
->backxrb
->ximage
= NULL
;
627 /* Allocate new back buffer */
630 /* Allocate a regular XImage for the back buffer. */
631 b
->backxrb
->ximage
= XMesaCreateImage(b
->xm_visual
->BitsPerPixel
,
632 width
, height
, NULL
);
634 if (b
->shm
== 0 || !alloc_shm_back_buffer(b
, width
, height
)) {
635 /* Allocate a regular XImage for the back buffer. */
636 b
->backxrb
->ximage
= XCreateImage( b
->xm_visual
->display
,
637 b
->xm_visual
->visinfo
->visual
,
638 GET_VISUAL_DEPTH(b
->xm_visual
),
639 ZPixmap
, 0, /* format, offset */
642 8, 0 ); /* pad, bytes_per_line */
644 if (!b
->backxrb
->ximage
) {
645 _mesa_warning(NULL
, "alloc_back_buffer: XCreateImage failed.");
647 b
->backxrb
->ximage
->data
= (char *) MALLOC( b
->backxrb
->ximage
->height
648 * b
->backxrb
->ximage
->bytes_per_line
);
649 if (!b
->backxrb
->ximage
->data
) {
650 _mesa_warning(NULL
, "alloc_back_buffer: MALLOC failed.");
651 XMesaDestroyImage( b
->backxrb
->ximage
);
652 b
->backxrb
->ximage
= NULL
;
655 b
->backxrb
->pixmap
= None
;
656 b
->backxrb
->ximage
= b
->backxrb
->ximage
;
658 else if (b
->db_state
==BACK_PIXMAP
) {
664 /* Free the old back pixmap */
665 if (b
->backxrb
->pixmap
) {
666 XMesaFreePixmap( b
->xm_visual
->display
, b
->backxrb
->pixmap
);
668 /* Allocate new back pixmap */
669 b
->backxrb
->pixmap
= XMesaCreatePixmap( b
->xm_visual
->display
, b
->frontxrb
->pixmap
,
671 GET_VISUAL_DEPTH(b
->xm_visual
) );
672 b
->backxrb
->ximage
= NULL
;
679 * A replacement for XAllocColor. This function should never
680 * fail to allocate a color. When XAllocColor fails, we return
681 * the nearest matching color. If we have to allocate many colors
682 * this function isn't too efficient; the XQueryColors() could be
684 * Written by Michael Pichler, Brian Paul, Mark Kilgard
685 * Input: dpy - X display
687 * cmapSize - size of colormap
688 * In/Out: color - the XColor struct
689 * Output: exact - 1=exact color match, 0=closest match
690 * alloced - 1=XAlloc worked, 0=XAlloc failed
693 noFaultXAllocColor( int client
,
698 int *exact
, int *alloced
)
704 /* we'll try to cache ctable for better remote display performance */
705 static Display
*prevDisplay
= NULL
;
706 static XMesaColormap prevCmap
= 0;
707 static int prevCmapSize
= 0;
708 static XMesaColor
*ctable
= NULL
;
712 double mindist
; /* 3*2^16^2 exceeds long int precision. */
716 /* First try just using XAllocColor. */
719 &color
->red
, &color
->green
, &color
->blue
,
721 client
) == Success
) {
723 if (XAllocColor(dpy
, cmap
, color
)) {
730 /* Alloc failed, search for closest match */
732 /* Retrieve color table entries. */
733 /* XXX alloca candidate. */
735 ppixIn
= (Pixel
*) MALLOC(cmapSize
* sizeof(Pixel
));
736 ctable
= (xrgb
*) MALLOC(cmapSize
* sizeof(xrgb
));
737 for (i
= 0; i
< cmapSize
; i
++) {
740 QueryColors(cmap
, cmapSize
, ppixIn
, ctable
);
742 if (prevDisplay
!= dpy
|| prevCmap
!= cmap
743 || prevCmapSize
!= cmapSize
|| !ctable
) {
744 /* free previously cached color table */
747 /* Get the color table from X */
748 ctable
= (XMesaColor
*) MALLOC(cmapSize
* sizeof(XMesaColor
));
750 for (i
= 0; i
< cmapSize
; i
++) {
753 XQueryColors(dpy
, cmap
, ctable
, cmapSize
);
756 prevCmapSize
= cmapSize
;
760 /* Find best match. */
763 for (i
= 0; i
< cmapSize
; i
++) {
764 double dr
= 0.30 * ((double) color
->red
- (double) ctable
[i
].red
);
765 double dg
= 0.59 * ((double) color
->green
- (double) ctable
[i
].green
);
766 double db
= 0.11 * ((double) color
->blue
- (double) ctable
[i
].blue
);
767 double dist
= dr
* dr
+ dg
* dg
+ db
* db
;
768 if (bestmatch
< 0 || dist
< mindist
) {
775 subColor
.red
= ctable
[bestmatch
].red
;
776 subColor
.green
= ctable
[bestmatch
].green
;
777 subColor
.blue
= ctable
[bestmatch
].blue
;
778 /* Try to allocate the closest match color. This should only
779 * fail if the cell is read/write. Otherwise, we're incrementing
780 * the cell's reference count.
784 &subColor
.red
, &subColor
.green
, &subColor
.blue
,
786 client
) == Success
) {
788 if (XAllocColor(dpy
, cmap
, &subColor
)) {
793 /* do this to work around a problem reported by Frank Ortega */
794 subColor
.pixel
= (unsigned long) bestmatch
;
795 subColor
.red
= ctable
[bestmatch
].red
;
796 subColor
.green
= ctable
[bestmatch
].green
;
797 subColor
.blue
= ctable
[bestmatch
].blue
;
798 subColor
.flags
= DoRed
| DoGreen
| DoBlue
;
805 /* don't free table, save it for next time */
816 * Do setup for PF_GRAYSCALE pixel format.
817 * Note that buffer may be NULL.
819 static GLboolean
setup_grayscale( int client
, XMesaVisual v
,
820 XMesaBuffer buffer
, XMesaColormap cmap
)
822 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
827 XMesaBuffer prevBuffer
;
833 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
835 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
836 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
837 /* Copy colormap stuff from previous XMesaBuffer which uses same
838 * X colormap. Do this to avoid time spent in noFaultXAllocColor.
840 copy_colortable_info(buffer
, prevBuffer
);
843 /* Allocate 256 shades of gray */
845 int colorsfailed
= 0;
846 for (gray
=0;gray
<256;gray
++) {
847 GLint r
= gamma_adjust( v
->RedGamma
, gray
, 255 );
848 GLint g
= gamma_adjust( v
->GreenGamma
, gray
, 255 );
849 GLint b
= gamma_adjust( v
->BlueGamma
, gray
, 255 );
852 xcol
.red
= (r
<< 8) | r
;
853 xcol
.green
= (g
<< 8) | g
;
854 xcol
.blue
= (b
<< 8) | b
;
855 noFaultXAllocColor( client
, v
->display
,
856 cmap
, GET_COLORMAP_SIZE(v
),
857 &xcol
, &exact
, &alloced
);
862 assert(buffer
->num_alloced
<256);
863 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
864 buffer
->num_alloced
++;
869 buffer->color_table[gray*3+0] = xcol.pixel;
870 buffer->color_table[gray*3+1] = xcol.pixel;
871 buffer->color_table[gray*3+2] = xcol.pixel;
872 assert(xcol.pixel < 65536);
873 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
874 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
875 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
877 buffer
->color_table
[gray
] = xcol
.pixel
;
878 assert(xcol
.pixel
< 65536);
879 buffer
->pixel_to_r
[xcol
.pixel
] = gray
;
880 buffer
->pixel_to_g
[xcol
.pixel
] = gray
;
881 buffer
->pixel_to_b
[xcol
.pixel
] = gray
;
884 if (colorsfailed
&& _mesa_getenv("MESA_DEBUG")) {
886 "Note: %d out of 256 needed colors do not match exactly.\n",
892 v
->dithered_pf
= PF_Grayscale
;
893 v
->undithered_pf
= PF_Grayscale
;
900 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
901 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
902 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
903 * color. While this function was originally designed just for 8-bit
904 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
905 * Dithering code contributed by Bob Mercier.
907 static GLboolean
setup_dithered_color( int client
, XMesaVisual v
,
908 XMesaBuffer buffer
, XMesaColormap cmap
)
910 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
915 XMesaBuffer prevBuffer
;
921 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
923 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
924 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
925 /* Copy colormap stuff from previous, matching XMesaBuffer.
926 * Do this to avoid time spent in noFaultXAllocColor.
928 copy_colortable_info(buffer
, prevBuffer
);
931 /* Allocate X colors and initialize color_table[], red_table[], etc */
933 int colorsfailed
= 0;
934 for (r
= 0; r
< DITH_R
; r
++) {
935 for (g
= 0; g
< DITH_G
; g
++) {
936 for (b
= 0; b
< DITH_B
; b
++) {
939 xcol
.red
=gamma_adjust(v
->RedGamma
, r
*65535/(DITH_R
-1),65535);
940 xcol
.green
=gamma_adjust(v
->GreenGamma
, g
*65535/(DITH_G
-1),65535);
941 xcol
.blue
=gamma_adjust(v
->BlueGamma
, b
*65535/(DITH_B
-1),65535);
942 noFaultXAllocColor( client
, v
->display
,
943 cmap
, GET_COLORMAP_SIZE(v
),
944 &xcol
, &exact
, &alloced
);
949 assert(buffer
->num_alloced
<256);
950 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
951 buffer
->num_alloced
++;
953 i
= DITH_MIX( r
, g
, b
);
955 buffer
->color_table
[i
] = xcol
.pixel
;
956 assert(xcol
.pixel
< 65536);
957 buffer
->pixel_to_r
[xcol
.pixel
] = r
* 255 / (DITH_R
-1);
958 buffer
->pixel_to_g
[xcol
.pixel
] = g
* 255 / (DITH_G
-1);
959 buffer
->pixel_to_b
[xcol
.pixel
] = b
* 255 / (DITH_B
-1);
964 if (colorsfailed
&& _mesa_getenv("MESA_DEBUG")) {
966 "Note: %d out of %d needed colors do not match exactly.\n",
967 colorsfailed
, DITH_R
* DITH_G
* DITH_B
);
972 v
->dithered_pf
= PF_Dither
;
973 v
->undithered_pf
= PF_Lookup
;
979 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
980 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
981 * Special dithering tables have to be initialized.
983 static void setup_8bit_hpcr( XMesaVisual v
)
985 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be)
986 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
987 * on the root window AND the colormap obtainable by XGetRGBColormaps
988 * for that atom must be set on the window. (see also tkInitWindow)
989 * If that colormap is not set, the output will look stripy.
992 /* Setup color tables with gamma correction */
996 g
= 1.0 / v
->RedGamma
;
997 for (i
=0; i
<256; i
++) {
998 GLint red
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[0][i
]/255.0, g
));
999 v
->hpcr_rgbTbl
[0][i
] = CLAMP( red
, 16, 239 );
1002 g
= 1.0 / v
->GreenGamma
;
1003 for (i
=0; i
<256; i
++) {
1004 GLint green
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[1][i
]/255.0, g
));
1005 v
->hpcr_rgbTbl
[1][i
] = CLAMP( green
, 16, 239 );
1008 g
= 1.0 / v
->BlueGamma
;
1009 for (i
=0; i
<256; i
++) {
1010 GLint blue
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[2][i
]/255.0, g
));
1011 v
->hpcr_rgbTbl
[2][i
] = CLAMP( blue
, 32, 223 );
1013 v
->undithered_pf
= PF_HPCR
; /* can't really disable dithering for now */
1014 v
->dithered_pf
= PF_HPCR
;
1016 /* which method should I use to clear */
1017 /* GL_FALSE: keep the ordinary method */
1018 /* GL_TRUE : clear with dither pattern */
1019 v
->hpcr_clear_flag
= _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE
: GL_FALSE
;
1021 if (v
->hpcr_clear_flag
) {
1022 v
->hpcr_clear_pixmap
= XMesaCreatePixmap(v
->display
,
1023 DefaultRootWindow(v
->display
),
1025 #ifndef XFree86Server
1026 v
->hpcr_clear_ximage
= XGetImage(v
->display
, v
->hpcr_clear_pixmap
,
1027 0, 0, 16, 2, AllPlanes
, ZPixmap
);
1034 * Setup RGB rendering for a window with a True/DirectColor visual.
1036 static void setup_truecolor( XMesaVisual v
, XMesaBuffer buffer
,
1037 XMesaColormap cmap
)
1039 unsigned long rmask
, gmask
, bmask
;
1043 /* Compute red multiplier (mask) and bit shift */
1045 rmask
= GET_REDMASK(v
);
1046 while ((rmask
& 1)==0) {
1051 /* Compute green multiplier (mask) and bit shift */
1053 gmask
= GET_GREENMASK(v
);
1054 while ((gmask
& 1)==0) {
1059 /* Compute blue multiplier (mask) and bit shift */
1061 bmask
= GET_BLUEMASK(v
);
1062 while ((bmask
& 1)==0) {
1068 * Compute component-to-pixel lookup tables and dithering kernel
1071 static GLubyte kernel
[16] = {
1072 0*16, 8*16, 2*16, 10*16,
1073 12*16, 4*16, 14*16, 6*16,
1074 3*16, 11*16, 1*16, 9*16,
1075 15*16, 7*16, 13*16, 5*16,
1077 GLint rBits
= bitcount(rmask
);
1078 GLint gBits
= bitcount(gmask
);
1079 GLint bBits
= bitcount(bmask
);
1083 /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1084 for (i
=0; i
<=rmask
; i
++)
1085 v
->PixelToR
[i
] = (unsigned char) ((i
* 255) / rmask
);
1086 for (i
=0; i
<=gmask
; i
++)
1087 v
->PixelToG
[i
] = (unsigned char) ((i
* 255) / gmask
);
1088 for (i
=0; i
<=bmask
; i
++)
1089 v
->PixelToB
[i
] = (unsigned char) ((i
* 255) / bmask
);
1091 /* convert RGB values from [0,255] to pixel components */
1093 for (i
=0;i
<256;i
++) {
1094 GLint r
= gamma_adjust(v
->RedGamma
, i
, 255);
1095 GLint g
= gamma_adjust(v
->GreenGamma
, i
, 255);
1096 GLint b
= gamma_adjust(v
->BlueGamma
, i
, 255);
1097 v
->RtoPixel
[i
] = (r
>> (8-rBits
)) << v
->rshift
;
1098 v
->GtoPixel
[i
] = (g
>> (8-gBits
)) << v
->gshift
;
1099 v
->BtoPixel
[i
] = (b
>> (8-bBits
)) << v
->bshift
;
1101 /* overflow protection */
1102 for (i
=256;i
<512;i
++) {
1103 v
->RtoPixel
[i
] = v
->RtoPixel
[255];
1104 v
->GtoPixel
[i
] = v
->GtoPixel
[255];
1105 v
->BtoPixel
[i
] = v
->BtoPixel
[255];
1108 /* setup dithering kernel */
1110 if (gBits
> maxBits
) maxBits
= gBits
;
1111 if (bBits
> maxBits
) maxBits
= bBits
;
1112 for (i
=0;i
<16;i
++) {
1113 v
->Kernel
[i
] = kernel
[i
] >> maxBits
;
1116 v
->undithered_pf
= PF_Truecolor
;
1117 v
->dithered_pf
= (GET_VISUAL_DEPTH(v
)<24) ? PF_Dither_True
: PF_Truecolor
;
1121 * Now check for TrueColor visuals which we can optimize.
1123 if ( GET_REDMASK(v
) ==0x0000ff
1124 && GET_GREENMASK(v
)==0x00ff00
1125 && GET_BLUEMASK(v
) ==0xff0000
1126 && CHECK_BYTE_ORDER(v
)
1127 && v
->BitsPerPixel
==32
1128 && sizeof(GLuint
)==4
1129 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1130 /* common 32 bpp config used on SGI, Sun */
1131 v
->undithered_pf
= v
->dithered_pf
= PF_8A8B8G8R
;
1133 else if (GET_REDMASK(v
) ==0xff0000
1134 && GET_GREENMASK(v
)==0x00ff00
1135 && GET_BLUEMASK(v
) ==0x0000ff
1136 && CHECK_BYTE_ORDER(v
)
1137 && v
->BitsPerPixel
==32
1138 && sizeof(GLuint
)==4
1139 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1140 /* common 32 bpp config used on Linux, HP, IBM */
1141 if (GET_VISUAL_DEPTH(v
)==32)
1142 v
->undithered_pf
= v
->dithered_pf
= PF_8A8R8G8B
;
1144 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B
;
1146 else if (GET_REDMASK(v
) ==0xff0000
1147 && GET_GREENMASK(v
)==0x00ff00
1148 && GET_BLUEMASK(v
) ==0x0000ff
1149 && CHECK_BYTE_ORDER(v
)
1150 && v
->BitsPerPixel
==24
1151 && sizeof(GLuint
)==4
1152 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1153 /* common packed 24 bpp config used on Linux */
1154 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B24
;
1156 else if (GET_REDMASK(v
) ==0xf800
1157 && GET_GREENMASK(v
)==0x07e0
1158 && GET_BLUEMASK(v
) ==0x001f
1159 && CHECK_BYTE_ORDER(v
)
1160 && v
->BitsPerPixel
==16
1161 && sizeof(GLushort
)==2
1162 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1163 /* 5-6-5 color weight on common PC VGA boards */
1164 v
->undithered_pf
= PF_5R6G5B
;
1165 v
->dithered_pf
= PF_Dither_5R6G5B
;
1167 else if (GET_REDMASK(v
) ==0xe0
1168 && GET_GREENMASK(v
)==0x1c
1169 && GET_BLUEMASK(v
) ==0x03
1170 && CHECK_FOR_HPCR(v
)) {
1171 setup_8bit_hpcr( v
);
1178 * Setup RGB rendering for a window with a monochrome visual.
1180 static void setup_monochrome( XMesaVisual v
, XMesaBuffer b
)
1183 v
->dithered_pf
= v
->undithered_pf
= PF_1Bit
;
1184 /* if black=1 then we must flip pixel values */
1185 v
->bitFlip
= (GET_BLACK_PIXEL(v
) != 0);
1191 * When a context is "made current" for the first time, we can finally
1192 * finish initializing the context's visual and buffer information.
1193 * Input: v - the XMesaVisual to initialize
1194 * b - the XMesaBuffer to initialize (may be NULL)
1195 * rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1196 * window - the window/pixmap we're rendering into
1197 * cmap - the colormap associated with the window/pixmap
1198 * Return: GL_TRUE=success, GL_FALSE=failure
1200 static GLboolean
initialize_visual_and_buffer( int client
,
1204 XMesaDrawable window
,
1205 XMesaColormap cmap
)
1207 #if NEW_RENDERBUFFER
1208 struct xmesa_renderbuffer
*front_xrb
, *back_xrb
;
1210 #ifndef XFree86Server
1215 assert(b
->xm_visual
== v
);
1218 #if NEW_RENDERBUFFER
1220 front_xrb
= b
->frontxrb
;
1221 back_xrb
= b
->backxrb
;
1224 front_xrb
= back_xrb
= NULL
;
1228 /* Save true bits/pixel */
1229 v
->BitsPerPixel
= bits_per_pixel(v
);
1230 assert(v
->BitsPerPixel
> 0);
1233 if (rgb_flag
==GL_FALSE
) {
1234 /* COLOR-INDEXED WINDOW:
1235 * Even if the visual is TrueColor or DirectColor we treat it as
1236 * being color indexed. This is weird but might be useful to someone.
1238 v
->dithered_pf
= v
->undithered_pf
= PF_Index
;
1239 v
->mesa_visual
.indexBits
= GET_VISUAL_DEPTH(v
);
1243 * We support RGB rendering into almost any kind of visual.
1245 const int xclass
= v
->mesa_visual
.visualType
;
1246 if (xclass
==GLX_TRUE_COLOR
|| xclass
==GLX_DIRECT_COLOR
) {
1247 setup_truecolor( v
, b
, cmap
);
1249 else if (xclass
==GLX_STATIC_GRAY
&& GET_VISUAL_DEPTH(v
)==1) {
1250 setup_monochrome( v
, b
);
1252 else if (xclass
==GLX_GRAY_SCALE
|| xclass
==GLX_STATIC_GRAY
) {
1253 if (!setup_grayscale( client
, v
, b
, cmap
)) {
1257 else if ((xclass
==GLX_PSEUDO_COLOR
|| xclass
==GLX_STATIC_COLOR
)
1258 && GET_VISUAL_DEPTH(v
)>=4 && GET_VISUAL_DEPTH(v
)<=16) {
1259 if (!setup_dithered_color( client
, v
, b
, cmap
)) {
1264 _mesa_warning(NULL
, "XMesa: RGB mode rendering not supported in given visual.");
1267 v
->mesa_visual
.indexBits
= 0;
1269 if (_mesa_getenv("MESA_NO_DITHER")) {
1270 v
->dithered_pf
= v
->undithered_pf
;
1276 * If MESA_INFO env var is set print out some debugging info
1277 * which can help Brian figure out what's going on when a user
1280 if (_mesa_getenv("MESA_INFO")) {
1281 _mesa_printf("X/Mesa visual = %p\n", (void *) v
);
1282 _mesa_printf("X/Mesa dithered pf = %u\n", v
->dithered_pf
);
1283 _mesa_printf("X/Mesa undithered pf = %u\n", v
->undithered_pf
);
1284 _mesa_printf("X/Mesa level = %d\n", v
->mesa_visual
.level
);
1285 _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v
));
1286 _mesa_printf("X/Mesa bits per pixel = %d\n", v
->BitsPerPixel
);
1290 /* Do window-specific initializations */
1292 b
->frontxrb
->pixmap
= window
;
1294 /* Setup for single/double buffering */
1295 if (v
->mesa_visual
.doubleBufferMode
) {
1296 /* Double buffered */
1297 #ifndef XFree86Server
1298 b
->shm
= check_for_xshm( v
->display
);
1300 xmesa_alloc_back_buffer(b
, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
);
1303 /* X11 graphics contexts */
1304 #ifdef XFree86Server
1305 b
->gc
= CreateScratchGC(v
->display
, window
->depth
);
1307 b
->gc
= XCreateGC( v
->display
, window
, 0, NULL
);
1309 XMesaSetFunction( v
->display
, b
->gc
, GXcopy
);
1311 /* cleargc - for glClear() */
1312 #ifdef XFree86Server
1313 b
->cleargc
= CreateScratchGC(v
->display
, window
->depth
);
1315 b
->cleargc
= XCreateGC( v
->display
, window
, 0, NULL
);
1317 XMesaSetFunction( v
->display
, b
->cleargc
, GXcopy
);
1320 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1321 * Patch contributed by Michael Pichler May 15, 1995.
1323 #ifdef XFree86Server
1324 b
->swapgc
= CreateScratchGC(v
->display
, window
->depth
);
1328 dixChangeGC(NullClient
, b
->swapgc
, GCGraphicsExposures
, v
, NULL
);
1331 gcvalues
.graphics_exposures
= False
;
1332 b
->swapgc
= XCreateGC( v
->display
, window
,
1333 GCGraphicsExposures
, &gcvalues
);
1335 XMesaSetFunction( v
->display
, b
->swapgc
, GXcopy
);
1337 * Set fill style and tile pixmap once for all for HPCR stuff
1338 * (instead of doing it each time in clear_color_HPCR_pixmap())
1339 * Initialize whole stuff
1340 * Patch contributed by Jacques Leroy March 8, 1998.
1342 if (v
->hpcr_clear_flag
&& back_xrb
->pixmap
) {
1344 for (i
=0; i
<16; i
++)
1346 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 0, 0);
1347 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 1, 0);
1349 XMesaPutImage(b
->display
, (XMesaDrawable
)v
->hpcr_clear_pixmap
,
1350 b
->cleargc
, v
->hpcr_clear_ximage
, 0, 0, 0, 0, 16, 2);
1351 XMesaSetFillStyle( v
->display
, b
->cleargc
, FillTiled
);
1352 XMesaSetTile( v
->display
, b
->cleargc
, v
->hpcr_clear_pixmap
);
1355 /* Initialize the row buffer XImage for use in write_color_span() */
1356 #ifdef XFree86Server
1357 b
->rowimage
= XMesaCreateImage(GET_VISUAL_DEPTH(v
), MAX_WIDTH
, 1,
1358 (char *)MALLOC(MAX_WIDTH
*4));
1360 b
->rowimage
= XCreateImage( v
->display
,
1363 ZPixmap
, 0, /*format, offset*/
1364 (char*) MALLOC(MAX_WIDTH
*4), /*data*/
1365 MAX_WIDTH
, 1, /*width, height*/
1367 0 /*bytes_per_line*/ );
1379 * Convert an RGBA color to a pixel value.
1382 xmesa_color_to_pixel(GLcontext
*ctx
,
1383 GLubyte r
, GLubyte g
, GLubyte b
, GLubyte a
,
1386 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
1387 switch (pixelFormat
) {
1393 PACK_TRUECOLOR( p
, r
, g
, b
);
1397 return PACK_8A8B8G8R( r
, g
, b
, a
);
1399 return PACK_8A8R8G8B( r
, g
, b
, a
);
1403 return PACK_8R8G8B( r
, g
, b
);
1405 return PACK_5R6G5B( r
, g
, b
);
1409 return DITHER( 1, 0, r
, g
, b
);
1412 /* 382 = (3*255)/2 */
1413 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
1415 return DITHER_HPCR(1, 1, r
, g
, b
);
1419 return LOOKUP( r
, g
, b
);
1422 return GRAY_RGB( r
, g
, b
);
1423 case PF_Dither_True
:
1425 case PF_Dither_5R6G5B
:
1428 PACK_TRUEDITHER(p
, 1, 0, r
, g
, b
);
1432 _mesa_problem(ctx
, "Bad pixel format in xmesa_color_to_pixel");
1438 #define NUM_VISUAL_TYPES 6
1441 * Convert an X visual type to a GLX visual type.
1443 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
1445 * \return If \c visualType is a valid X visual type, a GLX visual type will
1446 * be returned. Otherwise \c GLX_NONE will be returned.
1449 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
1453 xmesa_convert_from_x_visual_type( int visualType
)
1455 static const int glx_visual_types
[ NUM_VISUAL_TYPES
] = {
1456 GLX_STATIC_GRAY
, GLX_GRAY_SCALE
,
1457 GLX_STATIC_COLOR
, GLX_PSEUDO_COLOR
,
1458 GLX_TRUE_COLOR
, GLX_DIRECT_COLOR
1461 return ( (unsigned) visualType
< NUM_VISUAL_TYPES
)
1462 ? glx_visual_types
[ visualType
] : GLX_NONE
;
1466 /**********************************************************************/
1467 /***** Public Functions *****/
1468 /**********************************************************************/
1472 * Create a new X/Mesa visual.
1473 * Input: display - X11 display
1474 * visinfo - an XVisualInfo pointer
1475 * rgb_flag - GL_TRUE = RGB mode,
1476 * GL_FALSE = color index mode
1477 * alpha_flag - alpha buffer requested?
1478 * db_flag - GL_TRUE = double-buffered,
1479 * GL_FALSE = single buffered
1480 * stereo_flag - stereo visual?
1481 * ximage_flag - GL_TRUE = use an XImage for back buffer,
1482 * GL_FALSE = use an off-screen pixmap for back buffer
1483 * depth_size - requested bits/depth values, or zero
1484 * stencil_size - requested bits/stencil values, or zero
1485 * accum_red_size - requested bits/red accum values, or zero
1486 * accum_green_size - requested bits/green accum values, or zero
1487 * accum_blue_size - requested bits/blue accum values, or zero
1488 * accum_alpha_size - requested bits/alpha accum values, or zero
1489 * num_samples - number of samples/pixel if multisampling, or zero
1490 * level - visual level, usually 0
1491 * visualCaveat - ala the GLX extension, usually GLX_NONE
1492 * Return; a new XMesaVisual or 0 if error.
1494 XMesaVisual
XMesaCreateVisual( XMesaDisplay
*display
,
1495 XMesaVisualInfo visinfo
,
1497 GLboolean alpha_flag
,
1499 GLboolean stereo_flag
,
1500 GLboolean ximage_flag
,
1503 GLint accum_red_size
,
1504 GLint accum_green_size
,
1505 GLint accum_blue_size
,
1506 GLint accum_alpha_size
,
1509 GLint visualCaveat
)
1513 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1515 /* For debugging only */
1516 if (_mesa_getenv("MESA_XSYNC")) {
1517 /* This makes debugging X easier.
1518 * In your debugger, set a breakpoint on _XError to stop when an
1519 * X protocol error is generated.
1521 #ifdef XFree86Server
1524 XSynchronize( display
, 1 );
1528 v
= (XMesaVisual
) CALLOC_STRUCT(xmesa_visual
);
1534 * In the X server, NULL is passed in for the display. It will have
1535 * to be set before using this visual. See XMesaSetVisualDisplay()
1538 v
->display
= display
;
1540 /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
1541 * the struct but we may need some of the information contained in it
1544 #ifndef XFree86Server
1545 v
->visinfo
= (XVisualInfo
*) MALLOC(sizeof(*visinfo
));
1550 MEMCPY(v
->visinfo
, visinfo
, sizeof(*visinfo
));
1553 /* check for MESA_GAMMA environment variable */
1554 gamma
= _mesa_getenv("MESA_GAMMA");
1556 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 0.0;
1557 sscanf( gamma
, "%f %f %f", &v
->RedGamma
, &v
->GreenGamma
, &v
->BlueGamma
);
1558 if (v
->RedGamma
<=0.0) v
->RedGamma
= 1.0;
1559 if (v
->GreenGamma
<=0.0) v
->GreenGamma
= v
->RedGamma
;
1560 if (v
->BlueGamma
<=0.0) v
->BlueGamma
= v
->RedGamma
;
1563 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 1.0;
1566 v
->ximage_flag
= ximage_flag
;
1568 #ifdef XFree86Server
1569 /* We could calculate these values by ourselves. nplanes is either the sum
1570 * of the red, green, and blue bits or the number index bits.
1571 * ColormapEntries is either (1U << index_bits) or
1572 * (1U << max(redBits, greenBits, blueBits)).
1574 v
->nplanes
= visinfo
->nplanes
;
1575 v
->ColormapEntries
= visinfo
->ColormapEntries
;
1577 v
->mesa_visual
.redMask
= visinfo
->redMask
;
1578 v
->mesa_visual
.greenMask
= visinfo
->greenMask
;
1579 v
->mesa_visual
.blueMask
= visinfo
->blueMask
;
1580 v
->mesa_visual
.visualID
= visinfo
->vid
;
1581 v
->mesa_visual
.screen
= 0; /* FIXME: What should be done here? */
1583 v
->mesa_visual
.redMask
= visinfo
->red_mask
;
1584 v
->mesa_visual
.greenMask
= visinfo
->green_mask
;
1585 v
->mesa_visual
.blueMask
= visinfo
->blue_mask
;
1586 v
->mesa_visual
.visualID
= visinfo
->visualid
;
1587 v
->mesa_visual
.screen
= visinfo
->screen
;
1590 #if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
1591 v
->mesa_visual
.visualType
= xmesa_convert_from_x_visual_type(visinfo
->class);
1593 v
->mesa_visual
.visualType
= xmesa_convert_from_x_visual_type(visinfo
->c_class
);
1596 v
->mesa_visual
.visualRating
= visualCaveat
;
1598 (void) initialize_visual_and_buffer( 0, v
, NULL
, rgb_flag
, 0, 0 );
1601 const int xclass
= v
->mesa_visual
.visualType
;
1602 if (xclass
==GLX_TRUE_COLOR
|| xclass
==GLX_DIRECT_COLOR
) {
1603 red_bits
= bitcount(GET_REDMASK(v
));
1604 green_bits
= bitcount(GET_GREENMASK(v
));
1605 blue_bits
= bitcount(GET_BLUEMASK(v
));
1609 /* this is an approximation */
1611 depth
= GET_VISUAL_DEPTH(v
);
1612 red_bits
= depth
/ 3;
1614 green_bits
= depth
/ 2;
1615 depth
-= green_bits
;
1618 assert( red_bits
+ green_bits
+ blue_bits
== GET_VISUAL_DEPTH(v
) );
1622 if (alpha_flag
&& alpha_bits
== 0)
1625 _mesa_initialize_visual( &v
->mesa_visual
,
1626 rgb_flag
, db_flag
, stereo_flag
,
1627 red_bits
, green_bits
,
1628 blue_bits
, alpha_bits
,
1629 v
->mesa_visual
.indexBits
,
1632 accum_red_size
, accum_green_size
,
1633 accum_blue_size
, accum_alpha_size
,
1636 /* XXX minor hack */
1637 v
->mesa_visual
.level
= level
;
1642 void XMesaSetVisualDisplay( XMesaDisplay
*dpy
, XMesaVisual v
)
1648 void XMesaDestroyVisual( XMesaVisual v
)
1650 #ifndef XFree86Server
1651 _mesa_free(v
->visinfo
);
1659 * Create a new XMesaContext.
1660 * \param v the XMesaVisual
1661 * \param share_list another XMesaContext with which to share display
1662 * lists or NULL if no sharing is wanted.
1663 * \return an XMesaContext or NULL if error.
1665 XMesaContext
XMesaCreateContext( XMesaVisual v
, XMesaContext share_list
)
1667 static GLboolean firstTime
= GL_TRUE
;
1670 struct dd_function_table functions
;
1674 _glthread_INIT_MUTEX(_xmesa_lock
);
1675 firstTime
= GL_FALSE
;
1678 /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
1679 c
= (XMesaContext
) CALLOC_STRUCT(xmesa_context
);
1683 mesaCtx
= &(c
->mesa
);
1685 /* initialize with default driver functions, then plug in XMesa funcs */
1686 _mesa_init_driver_functions(&functions
);
1687 xmesa_init_driver_functions(v
, &functions
);
1688 if (!_mesa_initialize_context(mesaCtx
, &v
->mesa_visual
,
1689 share_list
? &(share_list
->mesa
) : (GLcontext
*) NULL
,
1690 &functions
, (void *) c
)) {
1695 _mesa_enable_sw_extensions(mesaCtx
);
1696 _mesa_enable_1_3_extensions(mesaCtx
);
1697 _mesa_enable_1_4_extensions(mesaCtx
);
1698 _mesa_enable_1_5_extensions(mesaCtx
);
1699 _mesa_enable_2_0_extensions(mesaCtx
);
1702 _mesa_enable_extension(c
, "GL_EXT_texture_compression_s3tc");
1703 _mesa_enable_extension(c
, "GL_S3_s3tc");
1705 _mesa_enable_extension(c
, "GL_3DFX_texture_compression_FXT1");
1708 /* finish up xmesa context initializations */
1709 c
->swapbytes
= CHECK_BYTE_ORDER(v
) ? GL_FALSE
: GL_TRUE
;
1711 c
->xm_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1712 c
->display
= v
->display
;
1713 c
->pixelformat
= v
->dithered_pf
; /* Dithering is enabled by default */
1715 /* Initialize the software rasterizer and helper modules.
1717 if (!_swrast_CreateContext( mesaCtx
) ||
1718 !_ac_CreateContext( mesaCtx
) ||
1719 !_tnl_CreateContext( mesaCtx
) ||
1720 !_swsetup_CreateContext( mesaCtx
)) {
1721 _mesa_free_context_data(&c
->mesa
);
1727 tnl
= TNL_CONTEXT(mesaCtx
);
1728 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
1730 xmesa_register_swrast_functions( mesaCtx
);
1731 _swsetup_Wakeup(mesaCtx
);
1738 void XMesaDestroyContext( XMesaContext c
)
1740 GLcontext
*mesaCtx
= &c
->mesa
;
1742 XMesaBuffer xmbuf
= XMESA_BUFFER(mesaCtx
->DrawBuffer
);
1744 if (xmbuf
&& xmbuf
->FXctx
)
1745 fxMesaDestroyContext(xmbuf
->FXctx
);
1747 _swsetup_DestroyContext( mesaCtx
);
1748 _swrast_DestroyContext( mesaCtx
);
1749 _tnl_DestroyContext( mesaCtx
);
1750 _ac_DestroyContext( mesaCtx
);
1751 _mesa_free_context_data( mesaCtx
);
1758 * XXX this isn't a public function! It's a hack for the 3Dfx driver.
1759 * Create a new XMesaBuffer from an X window.
1760 * Input: v - the XMesaVisual
1763 * Return: new XMesaBuffer or NULL if error
1766 XMesaCreateWindowBuffer2(XMesaVisual v
, XMesaWindow w
, XMesaContext c
)
1768 #ifndef XFree86Server
1769 XWindowAttributes attr
;
1781 /* Check that window depth matches visual depth */
1782 #ifdef XFree86Server
1783 client
= CLIENT_ID(((XMesaDrawable
)w
)->id
);
1785 if (GET_VISUAL_DEPTH(v
) != ((XMesaDrawable
)w
)->depth
) {
1786 _mesa_warning(NULL
, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1787 GET_VISUAL_DEPTH(v
), ((XMesaDrawable
) w
)->depth
);
1791 XGetWindowAttributes( v
->display
, w
, &attr
);
1793 if (GET_VISUAL_DEPTH(v
) != attr
.depth
) {
1794 _mesa_warning(NULL
, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1795 GET_VISUAL_DEPTH(v
), attr
.depth
);
1801 #ifdef XFree86Server
1802 cmap
= (ColormapPtr
)LookupIDByType(wColormap(w
), RT_COLORMAP
);
1804 if (attr
.colormap
) {
1805 cmap
= attr
.colormap
;
1808 _mesa_warning(NULL
, "Window %u has no colormap!\n", (unsigned int) w
);
1809 /* this is weird, a window w/out a colormap!? */
1810 /* OK, let's just allocate a new one and hope for the best */
1811 cmap
= XCreateColormap(v
->display
, w
, attr
.visual
, AllocNone
);
1815 b
= alloc_xmesa_buffer(v
, WINDOW
, cmap
);
1820 if (!initialize_visual_and_buffer( client
, v
, b
, v
->mesa_visual
.rgbMode
,
1821 (XMesaDrawable
)w
, cmap
)) {
1822 free_xmesa_buffer(client
, b
);
1827 fxEnvVar
= _mesa_getenv("MESA_GLX_FX");
1829 if (fxEnvVar
[0]!='d') {
1833 if (v
->mesa_visual
.depthBits
> 0) {
1834 attribs
[numAttribs
++] = FXMESA_DEPTH_SIZE
;
1835 attribs
[numAttribs
++] = v
->mesa_visual
.depthBits
;
1837 if (v
->mesa_visual
.doubleBufferMode
) {
1838 attribs
[numAttribs
++] = FXMESA_DOUBLEBUFFER
;
1840 if (v
->mesa_visual
.accumRedBits
> 0) {
1841 attribs
[numAttribs
++] = FXMESA_ACCUM_SIZE
;
1842 attribs
[numAttribs
++] = v
->mesa_visual
.accumRedBits
;
1844 if (v
->mesa_visual
.stencilBits
> 0) {
1845 attribs
[numAttribs
++] = FXMESA_STENCIL_SIZE
;
1846 attribs
[numAttribs
++] = v
->mesa_visual
.stencilBits
;
1848 if (v
->mesa_visual
.alphaBits
> 0) {
1849 attribs
[numAttribs
++] = FXMESA_ALPHA_SIZE
;
1850 attribs
[numAttribs
++] = v
->mesa_visual
.alphaBits
;
1853 attribs
[numAttribs
++] = FXMESA_SHARE_CONTEXT
;
1854 attribs
[numAttribs
++] = (int) &(c
->mesa
);
1856 attribs
[numAttribs
++] = FXMESA_NONE
;
1858 /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
1859 hw
= fxMesaSelectCurrentBoard(0);
1861 /* if these fail, there's a new bug somewhere */
1862 ASSERT(b
->mesa_buffer
.Width
> 0);
1863 ASSERT(b
->mesa_buffer
.Height
> 0);
1865 if ((hw
== GR_SSTTYPE_VOODOO
) || (hw
== GR_SSTTYPE_Voodoo2
)) {
1866 b
->FXctx
= fxMesaCreateBestContext(0, b
->mesa_buffer
.Width
,
1867 b
->mesa_buffer
.Height
, attribs
);
1868 if ((v
->undithered_pf
!=PF_Index
) && (b
->backxrb
->ximage
)) {
1869 b
->FXisHackUsable
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1870 if (b
->FXctx
&& (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')) {
1871 b
->FXwindowHack
= GL_TRUE
;
1872 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
1875 b
->FXwindowHack
= GL_FALSE
;
1880 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1881 b
->FXctx
= fxMesaCreateContext(w
, GR_RESOLUTION_NONE
,
1882 GR_REFRESH_75Hz
, attribs
);
1884 b
->FXctx
= fxMesaCreateBestContext(0, b
->mesa_buffer
.Width
,
1885 b
->mesa_buffer
.Height
, attribs
);
1886 b
->FXisHackUsable
= GL_FALSE
;
1887 b
->FXwindowHack
= GL_FALSE
;
1891 "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1892 hw, b->mesa_buffer.Width, b->mesa_buffer.Height,
1893 b->FXisHackUsable, b->FXwindowHack);
1898 _mesa_warning(NULL
, "WARNING: This Mesa Library includes the Glide driver but\n");
1899 _mesa_warning(NULL
, " you have not defined the MESA_GLX_FX env. var.\n");
1900 _mesa_warning(NULL
, " (check the README.3DFX file for more information).\n\n");
1901 _mesa_warning(NULL
, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1910 XMesaCreateWindowBuffer(XMesaVisual v
, XMesaWindow w
)
1912 return XMesaCreateWindowBuffer2( v
, w
, NULL
);
1917 * Create a new XMesaBuffer from an X pixmap.
1919 * \param v the XMesaVisual
1920 * \param p the pixmap
1921 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1922 * \c GLX_DIRECT_COLOR visual for the pixmap
1923 * \returns new XMesaBuffer or NULL if error
1926 XMesaCreatePixmapBuffer(XMesaVisual v
, XMesaPixmap p
, XMesaColormap cmap
)
1933 b
= alloc_xmesa_buffer(v
, PIXMAP
, cmap
);
1938 #ifdef XFree86Server
1939 client
= CLIENT_ID(((XMesaDrawable
)p
)->id
);
1942 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1943 (XMesaDrawable
)p
, cmap
)) {
1944 free_xmesa_buffer(client
, b
);
1954 XMesaCreatePBuffer(XMesaVisual v
, XMesaColormap cmap
,
1955 unsigned int width
, unsigned int height
)
1957 #ifdef XFree86Server
1962 XMesaDrawable drawable
; /* X Pixmap Drawable */
1965 b
= alloc_xmesa_buffer(v
, PBUFFER
, cmap
);
1970 /* allocate pixmap for front buffer */
1971 root
= RootWindow( v
->display
, v
->visinfo
->screen
);
1972 drawable
= XCreatePixmap( v
->display
, root
, width
, height
, v
->visinfo
->depth
);
1974 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1976 free_xmesa_buffer(client
, b
);
1987 * Deallocate an XMesaBuffer structure and all related info.
1989 void XMesaDestroyBuffer( XMesaBuffer b
)
1993 #ifdef XFree86Server
1994 if (b
->frontxrb
->pixmap
)
1995 client
= CLIENT_ID(b
->frontxrb
->pixmap
->id
);
1998 if (b
->gc
) XMesaFreeGC( b
->xm_visual
->display
, b
->gc
);
1999 if (b
->cleargc
) XMesaFreeGC( b
->xm_visual
->display
, b
->cleargc
);
2000 if (b
->swapgc
) XMesaFreeGC( b
->xm_visual
->display
, b
->swapgc
);
2002 if (b
->xm_visual
->mesa_visual
.doubleBufferMode
)
2004 if (b
->backxrb
->ximage
) {
2005 #if defined(USE_XSHM) && !defined(XFree86Server)
2007 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
2008 XDestroyImage( b
->backxrb
->ximage
);
2009 shmdt( b
->shminfo
.shmaddr
);
2013 XMesaDestroyImage( b
->backxrb
->ximage
);
2015 if (b
->backxrb
->pixmap
) {
2016 XMesaFreePixmap( b
->xm_visual
->display
, b
->backxrb
->pixmap
);
2017 if (b
->xm_visual
->hpcr_clear_flag
) {
2018 XMesaFreePixmap( b
->xm_visual
->display
,
2019 b
->xm_visual
->hpcr_clear_pixmap
);
2020 XMesaDestroyImage( b
->xm_visual
->hpcr_clear_ximage
);
2025 _mesa_free( b
->rowimage
->data
);
2026 b
->rowimage
->data
= NULL
;
2027 XMesaDestroyImage( b
->rowimage
);
2030 free_xmesa_buffer(client
, b
);
2036 * Bind buffer b to context c and make c the current rendering context.
2038 GLboolean
XMesaMakeCurrent( XMesaContext c
, XMesaBuffer b
)
2040 return XMesaMakeCurrent2( c
, b
, b
);
2045 * Bind buffer b to context c and make c the current rendering context.
2047 GLboolean
XMesaMakeCurrent2( XMesaContext c
, XMesaBuffer drawBuffer
,
2048 XMesaBuffer readBuffer
)
2051 if (!drawBuffer
|| !readBuffer
)
2052 return GL_FALSE
; /* must specify buffers! */
2055 if (drawBuffer
->FXctx
) {
2056 fxMesaMakeCurrent(drawBuffer
->FXctx
);
2058 c
->xm_buffer
= drawBuffer
;
2063 if (&(c
->mesa
) == _mesa_get_current_context()
2064 && c
->mesa
.DrawBuffer
== &drawBuffer
->mesa_buffer
2065 && c
->mesa
.ReadBuffer
== &readBuffer
->mesa_buffer
2066 && ((XMesaBuffer
) c
->mesa
.DrawBuffer
)->wasCurrent
) {
2067 /* same context and buffer, do nothing */
2071 c
->xm_buffer
= drawBuffer
;
2073 _mesa_make_current(&(c
->mesa
),
2074 &drawBuffer
->mesa_buffer
,
2075 &readBuffer
->mesa_buffer
);
2077 if (c
->xm_visual
->mesa_visual
.rgbMode
) {
2079 * Must recompute and set these pixel values because colormap
2080 * can be different for different windows.
2082 c
->clearpixel
= xmesa_color_to_pixel( &c
->mesa
,
2087 c
->xm_visual
->undithered_pf
);
2088 XMesaSetForeground(c
->display
, drawBuffer
->cleargc
, c
->clearpixel
);
2091 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2092 drawBuffer
->wasCurrent
= GL_TRUE
;
2096 _mesa_make_current( NULL
, NULL
, NULL
);
2103 * Unbind the context c from its buffer.
2105 GLboolean
XMesaUnbindContext( XMesaContext c
)
2107 /* A no-op for XFree86 integration purposes */
2112 XMesaContext
XMesaGetCurrentContext( void )
2114 GET_CURRENT_CONTEXT(ctx
);
2116 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
2125 XMesaBuffer
XMesaGetCurrentBuffer( void )
2127 GET_CURRENT_CONTEXT(ctx
);
2129 XMesaBuffer xmbuf
= XMESA_BUFFER(ctx
->DrawBuffer
);
2138 /* New in Mesa 3.1 */
2139 XMesaBuffer
XMesaGetCurrentReadBuffer( void )
2141 GET_CURRENT_CONTEXT(ctx
);
2143 return (XMesaBuffer
) (ctx
->ReadBuffer
);
2151 GLboolean
XMesaForceCurrent(XMesaContext c
)
2154 if (&(c
->mesa
) != _mesa_get_current_context()) {
2155 _mesa_make_current(&c
->mesa
, c
->mesa
.DrawBuffer
, c
->mesa
.ReadBuffer
);
2159 _mesa_make_current(NULL
, NULL
, NULL
);
2165 GLboolean
XMesaLoseCurrent(XMesaContext c
)
2168 _mesa_make_current(NULL
, 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 XMesaBuffer xmbuf
= XMESA_BUFFER(ctx
->DrawBuffer
);
2197 if (mode
== XMESA_FX_WINDOW
) {
2198 if (xmbuf
->FXisHackUsable
) {
2199 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
2200 xmbuf
->FXwindowHack
= GL_TRUE
;
2204 else if (mode
== XMESA_FX_FULLSCREEN
) {
2205 FX_grSstControl(GR_CONTROL_ACTIVATE
);
2206 xmbuf
->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
->frontxrb
->pixmap
->x
;
2239 y
= b
->frontxrb
->pixmap
->y
;
2240 width
= b
->frontxrb
->pixmap
->width
;
2241 height
= b
->frontxrb
->pixmap
->height
;
2242 depth
= b
->frontxrb
->pixmap
->depth
;
2244 XGetGeometry( b
->xm_visual
->display
, b
->frontxrb
->pixmap
,
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
, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
);
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
->backxrb
->ximage
->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
->backxrb
->ximage
->data
2270 + b
->backxrb
->ximage
->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
->backxrb
->ximage
,x
,y
,
2302 xmesa_color_to_pixel(ctx
,
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
)
2341 if (b
->backxrb
->ximage
) {
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
->frontxrb
->pixmap
,
2348 b
->backxrb
->ximage
, 0, 0,
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
->frontxrb
->pixmap
,
2359 b
->backxrb
->ximage
, 0, 0,
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
->backxrb
->pixmap
, /* source drawable */
2369 b
->frontxrb
->pixmap
, /* 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
)
2408 if (b
->backxrb
->ximage
) {
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
->frontxrb
->pixmap
,
2415 b
->backxrb
->ximage
, 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
->frontxrb
->pixmap
,
2425 b
->backxrb
->ximage
, x
, yTop
,
2426 x
, yTop
, width
, height
);
2430 /* Copy pixmap to window on server */
2431 XMesaCopyArea( b
->xm_visual
->display
,
2432 b
->backxrb
->pixmap
, /* source drawable */
2433 b
->frontxrb
->pixmap
, /* 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
->backxrb
->pixmap
;
2458 if (ximage
) *ximage
= b
->backxrb
->ximage
;
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 struct gl_renderbuffer
*rb
2481 = b
->mesa_buffer
.Attachment
[BUFFER_DEPTH
].Renderbuffer
;
2482 if (!rb
|| !rb
->Data
) {
2490 *width
= b
->mesa_buffer
.Width
;
2491 *height
= b
->mesa_buffer
.Height
;
2492 *bytesPerValue
= b
->mesa_buffer
.Visual
.depthBits
<= 16
2493 ? sizeof(GLushort
) : sizeof(GLuint
);
2500 void XMesaFlush( XMesaContext c
)
2502 if (c
&& c
->xm_visual
) {
2503 #ifdef XFree86Server
2506 XSync( c
->xm_visual
->display
, False
);
2513 const char *XMesaGetString( XMesaContext c
, int name
)
2516 if (name
==XMESA_VERSION
) {
2519 else if (name
==XMESA_EXTENSIONS
) {
2529 XMesaBuffer
XMesaFindBuffer( XMesaDisplay
*dpy
, XMesaDrawable d
)
2532 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
2533 if (b
->frontxrb
->pixmap
==d
&& b
->display
==dpy
) {
2543 * Look for XMesaBuffers whose X window has been destroyed.
2544 * Deallocate any such XMesaBuffers.
2546 void XMesaGarbageCollect( void )
2548 XMesaBuffer b
, next
;
2549 for (b
=XMesaBufferList
; b
; b
=next
) {
2551 if (b
->display
&& b
->frontxrb
->pixmap
&& b
->type
== WINDOW
) {
2552 #ifdef XFree86Server
2555 XSync(b
->display
, False
);
2556 if (!window_exists( b
->display
, b
->frontxrb
->pixmap
)) {
2557 /* found a dead window, free the ancillary info */
2558 XMesaDestroyBuffer( b
);
2566 void XMesaReset( void )
2568 while (XMesaBufferList
)
2569 XMesaDestroyBuffer(XMesaBufferList
);
2571 XMesaBufferList
= NULL
;
2575 unsigned long XMesaDitherColor( XMesaContext xmesa
, GLint x
, GLint y
,
2576 GLfloat red
, GLfloat green
,
2577 GLfloat blue
, GLfloat alpha
)
2579 GLcontext
*ctx
= &xmesa
->mesa
;
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_8A8R8G8B( r
, g
, b
, a
);
2599 return PACK_8R8G8B( r
, g
, b
);
2601 return PACK_5R6G5B( r
, g
, b
);
2605 return DITHER( x
, y
, r
, g
, b
);
2608 /* 382 = (3*255)/2 */
2609 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
2611 return DITHER_HPCR(x
, y
, r
, g
, b
);
2615 return LOOKUP( r
, g
, b
);
2618 return GRAY_RGB( r
, g
, b
);
2619 case PF_Dither_5R6G5B
:
2621 case PF_Dither_True
:
2624 PACK_TRUEDITHER(p
, x
, y
, r
, g
, b
);
2628 _mesa_problem(NULL
, "Bad pixel format in XMesaDitherColor");
2635 * This is typically called when the window size changes and we need
2636 * to reallocate the buffer's back/depth/stencil/accum buffers.
2638 void XMesaResizeBuffers( XMesaBuffer b
)
2640 #if OLD_RENDERBUFFER
2641 xmesa_resize_buffers(ctx
, &(b
->mesa_buffer
), 0, 0 );