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 static int check_for_xshm( XMesaDisplay
*display
)
201 #if defined(XFree86Server)
203 #elif defined(USE_XSHM)
204 int major
, minor
, ignore
;
207 if (XQueryExtension( display
, "MIT-SHM", &ignore
, &ignore
, &ignore
)) {
208 if (XShmQueryVersion( display
, &major
, &minor
, &pixmaps
)==True
) {
209 return (pixmaps
==True
) ? 2 : 1;
219 /* No 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
;
257 for (i
= 0; i
< screenInfo
.numPixmapFormats
; i
++) {
258 if (screenInfo
.formats
[i
].depth
== depth
)
259 return screenInfo
.formats
[i
].bitsPerPixel
;
261 return depth
; /* should never get here, but this should be safe */
266 static int bits_per_pixel( XMesaVisual xmv
)
268 XMesaDisplay
*dpy
= xmv
->display
;
269 XMesaVisualInfo visinfo
= xmv
->visinfo
;
272 /* Create a temporary XImage */
273 img
= XCreateImage( dpy
, visinfo
->visual
, visinfo
->depth
,
274 ZPixmap
, 0, /*format, offset*/
275 (char*) MALLOC(8), /*data*/
276 1, 1, /*width, height*/
281 /* grab the bits/pixel value */
282 bitsPerPixel
= img
->bits_per_pixel
;
283 /* free the XImage */
284 _mesa_free( img
->data
);
286 XMesaDestroyImage( img
);
294 * Determine if a given X window ID is valid (window exists).
295 * Do this by calling XGetWindowAttributes() for the window and
296 * checking if we catch an X error.
297 * Input: dpy - the display
298 * win - the window to check for existance
299 * Return: GL_TRUE - window exists
300 * GL_FALSE - window doesn't exist
302 #ifndef XFree86Server
303 static GLboolean WindowExistsFlag
;
305 static int window_exists_err_handler( XMesaDisplay
* dpy
, XErrorEvent
* xerr
)
308 if (xerr
->error_code
== BadWindow
) {
309 WindowExistsFlag
= GL_FALSE
;
314 static GLboolean
window_exists( XMesaDisplay
*dpy
, Window win
)
316 XWindowAttributes wa
;
317 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
318 WindowExistsFlag
= GL_TRUE
;
319 old_handler
= XSetErrorHandler(window_exists_err_handler
);
320 XGetWindowAttributes( dpy
, win
, &wa
); /* dummy request */
321 XSetErrorHandler(old_handler
);
322 return WindowExistsFlag
;
328 /**********************************************************************/
329 /***** Linked list of XMesaBuffers *****/
330 /**********************************************************************/
332 static XMesaBuffer XMesaBufferList
= NULL
;
336 * Allocate a new XMesaBuffer, initialize basic fields and add to
337 * the list of all buffers.
340 alloc_xmesa_buffer(XMesaVisual vis
, BufferType type
, XMesaColormap cmap
)
342 XMesaBuffer b
= (XMesaBuffer
) CALLOC_STRUCT(xmesa_buffer
);
346 b
->display
= vis
->display
;
351 _mesa_initialize_framebuffer(&b
->mesa_buffer
, &vis
->mesa_visual
);
353 /* Allocate the framebuffer's renderbuffers */
354 assert(!b
->mesa_buffer
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
355 assert(!b
->mesa_buffer
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
357 /* front renderbuffer */
358 b
->frontxrb
= xmesa_new_renderbuffer(NULL
, 0, vis
->mesa_visual
.rgbMode
,
360 _mesa_add_renderbuffer(&b
->mesa_buffer
, BUFFER_FRONT_LEFT
,
363 /* back renderbuffer */
364 if (vis
->mesa_visual
.doubleBufferMode
) {
365 b
->backxrb
= xmesa_new_renderbuffer(NULL
, 0,
366 vis
->mesa_visual
.rgbMode
,
368 /* determine back buffer implementation */
369 b
->db_mode
= vis
->ximage_flag
? BACK_XIMAGE
: BACK_PIXMAP
;
371 _mesa_add_renderbuffer(&b
->mesa_buffer
, BUFFER_BACK_LEFT
,
375 /* determine if we need software alpha planes */
376 if (vis
->mesa_visual
.alphaBits
> 0
377 && vis
->undithered_pf
!= PF_8A8B8G8R
378 && vis
->undithered_pf
!= PF_8A8R8G8B
) {
379 /* Visual has alpha, but pixel format doesn't support it.
380 * We'll use an alpha renderbuffer wrapper.
388 _mesa_add_soft_renderbuffers(&b
->mesa_buffer
,
389 GL_FALSE
, /* color */
390 vis
->mesa_visual
.haveDepthBuffer
,
391 vis
->mesa_visual
.haveStencilBuffer
,
392 vis
->mesa_visual
.haveAccumBuffer
,
394 vis
->mesa_visual
.numAuxBuffers
> 0 );
396 /* insert into linked list */
397 b
->Next
= XMesaBufferList
;
405 * Find an XMesaBuffer by matching X display and colormap but NOT matching
406 * the notThis buffer.
408 static XMesaBuffer
find_xmesa_buffer(XMesaDisplay
*dpy
,
413 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
414 if (b
->display
==dpy
&& b
->cmap
==cmap
&& b
!=notThis
) {
423 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
426 static void free_xmesa_buffer(int client
, XMesaBuffer buffer
)
428 XMesaBuffer prev
= NULL
, b
;
430 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
432 /* unlink bufer from list */
434 prev
->Next
= buffer
->Next
;
436 XMesaBufferList
= buffer
->Next
;
437 /* Check to free X colors */
438 if (buffer
->num_alloced
>0) {
439 /* If no other buffer uses this X colormap then free the colors. */
440 if (!find_xmesa_buffer(buffer
->display
, buffer
->cmap
, buffer
)) {
442 (void)FreeColors(buffer
->cmap
, client
,
443 buffer
->num_alloced
, buffer
->alloced_colors
,
446 XFreeColors(buffer
->display
, buffer
->cmap
,
447 buffer
->alloced_colors
, buffer
->num_alloced
, 0);
452 _mesa_free_framebuffer_data(&buffer
->mesa_buffer
);
457 /* continue search */
460 /* buffer not found in XMesaBufferList */
461 _mesa_problem(NULL
,"free_xmesa_buffer() - buffer not found\n");
465 /* Copy X color table stuff from one XMesaBuffer to another. */
466 static void copy_colortable_info(XMesaBuffer dst
, const XMesaBuffer src
)
468 MEMCPY(dst
->color_table
, src
->color_table
, sizeof(src
->color_table
));
469 MEMCPY(dst
->pixel_to_r
, src
->pixel_to_r
, sizeof(src
->pixel_to_r
));
470 MEMCPY(dst
->pixel_to_g
, src
->pixel_to_g
, sizeof(src
->pixel_to_g
));
471 MEMCPY(dst
->pixel_to_b
, src
->pixel_to_b
, sizeof(src
->pixel_to_b
));
472 dst
->num_alloced
= src
->num_alloced
;
473 MEMCPY(dst
->alloced_colors
, src
->alloced_colors
,
474 sizeof(src
->alloced_colors
));
479 /**********************************************************************/
480 /***** Misc Private Functions *****/
481 /**********************************************************************/
485 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
486 * Return: GL_TRUE if success, GL_FALSE if error
488 #ifndef XFree86Server
490 alloc_shm_back_buffer(XMesaBuffer b
, GLuint width
, GLuint height
)
494 * We have to do a _lot_ of error checking here to be sure we can
495 * really use the XSHM extension. It seems different servers trigger
496 * errors at different points if the extension won't work. Therefore
497 * we have to be very careful...
500 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
502 if (width
== 0 || height
== 0) {
503 /* this will be true the first time we're called on 'b' */
507 b
->backxrb
->ximage
= XShmCreateImage(b
->xm_visual
->display
,
508 b
->xm_visual
->visinfo
->visual
,
509 b
->xm_visual
->visinfo
->depth
,
510 ZPixmap
, NULL
, &b
->shminfo
,
512 if (b
->backxrb
->ximage
== NULL
) {
513 _mesa_warning(NULL
, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.\n");
518 b
->shminfo
.shmid
= shmget( IPC_PRIVATE
, b
->backxrb
->ximage
->bytes_per_line
519 * b
->backxrb
->ximage
->height
, IPC_CREAT
|0777 );
520 if (b
->shminfo
.shmid
< 0) {
521 _mesa_warning(NULL
, "shmget failed while allocating back buffer.\n");
522 XDestroyImage( b
->backxrb
->ximage
);
523 b
->backxrb
->ximage
= NULL
;
524 _mesa_warning(NULL
, "alloc_back_buffer: Shared memory error (shmget), disabling.\n");
529 b
->shminfo
.shmaddr
= b
->backxrb
->ximage
->data
530 = (char*)shmat( b
->shminfo
.shmid
, 0, 0 );
531 if (b
->shminfo
.shmaddr
== (char *) -1) {
532 _mesa_warning(NULL
, "shmat() failed while allocating back buffer.\n");
533 XDestroyImage( b
->backxrb
->ximage
);
534 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
535 b
->backxrb
->ximage
= NULL
;
536 _mesa_warning(NULL
, "alloc_back_buffer: Shared memory error (shmat), disabling.\n");
541 b
->shminfo
.readOnly
= False
;
543 old_handler
= XSetErrorHandler( mesaHandleXError
);
544 /* This may trigger the X protocol error we're ready to catch: */
545 XShmAttach( b
->xm_visual
->display
, &b
->shminfo
);
546 XSync( b
->xm_visual
->display
, False
);
548 if (mesaXErrorFlag
) {
549 /* we are on a remote display, this error is normal, don't print it */
550 XFlush( b
->xm_visual
->display
);
552 XDestroyImage( b
->backxrb
->ximage
);
553 shmdt( b
->shminfo
.shmaddr
);
554 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
555 b
->backxrb
->ximage
= NULL
;
557 (void) XSetErrorHandler( old_handler
);
561 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 ); /* nobody else needs it */
563 /* Finally, try an XShmPutImage to be really sure the extension works */
564 gc
= XCreateGC( b
->xm_visual
->display
, b
->frontxrb
->drawable
, 0, NULL
);
565 XShmPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
, gc
,
566 b
->backxrb
->ximage
, 0, 0, 0, 0, 1, 1 /*one pixel*/, False
);
567 XSync( b
->xm_visual
->display
, False
);
568 XFreeGC( b
->xm_visual
->display
, gc
);
569 (void) XSetErrorHandler( old_handler
);
570 if (mesaXErrorFlag
) {
571 XFlush( b
->xm_visual
->display
);
573 XDestroyImage( b
->backxrb
->ximage
);
574 shmdt( b
->shminfo
.shmaddr
);
575 shmctl( b
->shminfo
.shmid
, IPC_RMID
, 0 );
576 b
->backxrb
->ximage
= NULL
;
583 /* Can't compile XSHM support */
593 * Setup an off-screen pixmap or Ximage to use as the back buffer.
594 * Input: b - the X/Mesa buffer
597 xmesa_alloc_back_buffer( XMesaBuffer b
, GLuint width
, GLuint height
)
599 if (width
== 0 || height
== 0)
602 if (b
->db_mode
== BACK_XIMAGE
) {
603 /* Deallocate the old backxrb->ximage, if any */
604 if (b
->backxrb
->ximage
) {
605 #if defined(USE_XSHM) && !defined(XFree86Server)
607 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
608 XDestroyImage( b
->backxrb
->ximage
);
609 shmdt( b
->shminfo
.shmaddr
);
613 XMesaDestroyImage( b
->backxrb
->ximage
);
614 b
->backxrb
->ximage
= NULL
;
617 /* Allocate new back buffer */
619 /* Allocate a regular XImage for the back buffer. */
620 b
->backxrb
->ximage
= XMesaCreateImage(b
->xm_visual
->BitsPerPixel
,
621 width
, height
, NULL
);
624 if (b
->shm
== 0 || !alloc_shm_back_buffer(b
, width
, height
)) {
625 /* Allocate a regular XImage for the back buffer. */
626 b
->backxrb
->ximage
= XCreateImage( b
->xm_visual
->display
,
627 b
->xm_visual
->visinfo
->visual
,
628 GET_VISUAL_DEPTH(b
->xm_visual
),
629 ZPixmap
, 0, /* format, offset */
632 8, 0 ); /* pad, bytes_per_line */
634 if (!b
->backxrb
->ximage
) {
635 _mesa_warning(NULL
, "alloc_back_buffer: XCreateImage failed.\n");
638 b
->backxrb
->ximage
->data
= (char *) MALLOC( b
->backxrb
->ximage
->height
639 * b
->backxrb
->ximage
->bytes_per_line
);
640 if (!b
->backxrb
->ximage
->data
) {
641 _mesa_warning(NULL
, "alloc_back_buffer: MALLOC failed.\n");
642 XMesaDestroyImage( b
->backxrb
->ximage
);
643 b
->backxrb
->ximage
= NULL
;
646 /* this call just updates the width/origin fields in the xrb */
647 b
->backxrb
->Base
.AllocStorage(NULL
, &b
->backxrb
->Base
,
648 b
->backxrb
->Base
.InternalFormat
,
649 b
->backxrb
->ximage
->width
,
650 b
->backxrb
->ximage
->height
);
653 b
->backxrb
->pixmap
= None
;
655 else if (b
->db_mode
== BACK_PIXMAP
) {
661 /* Free the old back pixmap */
662 if (b
->backxrb
->pixmap
) {
663 XMesaFreePixmap( b
->xm_visual
->display
, b
->backxrb
->pixmap
);
665 /* Allocate new back pixmap */
666 b
->backxrb
->pixmap
= XMesaCreatePixmap( b
->xm_visual
->display
,
667 b
->frontxrb
->drawable
,
669 GET_VISUAL_DEPTH(b
->xm_visual
) );
670 b
->backxrb
->ximage
= NULL
;
677 * A replacement for XAllocColor. This function should never
678 * fail to allocate a color. When XAllocColor fails, we return
679 * the nearest matching color. If we have to allocate many colors
680 * this function isn't too efficient; the XQueryColors() could be
682 * Written by Michael Pichler, Brian Paul, Mark Kilgard
683 * Input: dpy - X display
685 * cmapSize - size of colormap
686 * In/Out: color - the XColor struct
687 * Output: exact - 1=exact color match, 0=closest match
688 * alloced - 1=XAlloc worked, 0=XAlloc failed
691 noFaultXAllocColor( int client
,
696 int *exact
, int *alloced
)
702 /* we'll try to cache ctable for better remote display performance */
703 static Display
*prevDisplay
= NULL
;
704 static XMesaColormap prevCmap
= 0;
705 static int prevCmapSize
= 0;
706 static XMesaColor
*ctable
= NULL
;
710 double mindist
; /* 3*2^16^2 exceeds long int precision. */
714 /* First try just using XAllocColor. */
717 &color
->red
, &color
->green
, &color
->blue
,
719 client
) == Success
) {
721 if (XAllocColor(dpy
, cmap
, color
)) {
728 /* Alloc failed, search for closest match */
730 /* Retrieve color table entries. */
731 /* XXX alloca candidate. */
733 ppixIn
= (Pixel
*) MALLOC(cmapSize
* sizeof(Pixel
));
734 ctable
= (xrgb
*) MALLOC(cmapSize
* sizeof(xrgb
));
735 for (i
= 0; i
< cmapSize
; i
++) {
738 QueryColors(cmap
, cmapSize
, ppixIn
, ctable
);
740 if (prevDisplay
!= dpy
|| prevCmap
!= cmap
741 || prevCmapSize
!= cmapSize
|| !ctable
) {
742 /* free previously cached color table */
745 /* Get the color table from X */
746 ctable
= (XMesaColor
*) MALLOC(cmapSize
* sizeof(XMesaColor
));
748 for (i
= 0; i
< cmapSize
; i
++) {
751 XQueryColors(dpy
, cmap
, ctable
, cmapSize
);
754 prevCmapSize
= cmapSize
;
758 /* Find best match. */
761 for (i
= 0; i
< cmapSize
; i
++) {
762 double dr
= 0.30 * ((double) color
->red
- (double) ctable
[i
].red
);
763 double dg
= 0.59 * ((double) color
->green
- (double) ctable
[i
].green
);
764 double db
= 0.11 * ((double) color
->blue
- (double) ctable
[i
].blue
);
765 double dist
= dr
* dr
+ dg
* dg
+ db
* db
;
766 if (bestmatch
< 0 || dist
< mindist
) {
773 subColor
.red
= ctable
[bestmatch
].red
;
774 subColor
.green
= ctable
[bestmatch
].green
;
775 subColor
.blue
= ctable
[bestmatch
].blue
;
776 /* Try to allocate the closest match color. This should only
777 * fail if the cell is read/write. Otherwise, we're incrementing
778 * the cell's reference count.
782 &subColor
.red
, &subColor
.green
, &subColor
.blue
,
784 client
) == Success
) {
786 if (XAllocColor(dpy
, cmap
, &subColor
)) {
791 /* do this to work around a problem reported by Frank Ortega */
792 subColor
.pixel
= (unsigned long) bestmatch
;
793 subColor
.red
= ctable
[bestmatch
].red
;
794 subColor
.green
= ctable
[bestmatch
].green
;
795 subColor
.blue
= ctable
[bestmatch
].blue
;
796 subColor
.flags
= DoRed
| DoGreen
| DoBlue
;
803 /* don't free table, save it for next time */
814 * Do setup for PF_GRAYSCALE pixel format.
815 * Note that buffer may be NULL.
817 static GLboolean
setup_grayscale( int client
, XMesaVisual v
,
818 XMesaBuffer buffer
, XMesaColormap cmap
)
820 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
825 XMesaBuffer prevBuffer
;
831 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
833 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
834 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
835 /* Copy colormap stuff from previous XMesaBuffer which uses same
836 * X colormap. Do this to avoid time spent in noFaultXAllocColor.
838 copy_colortable_info(buffer
, prevBuffer
);
841 /* Allocate 256 shades of gray */
843 int colorsfailed
= 0;
844 for (gray
=0;gray
<256;gray
++) {
845 GLint r
= gamma_adjust( v
->RedGamma
, gray
, 255 );
846 GLint g
= gamma_adjust( v
->GreenGamma
, gray
, 255 );
847 GLint b
= gamma_adjust( v
->BlueGamma
, gray
, 255 );
850 xcol
.red
= (r
<< 8) | r
;
851 xcol
.green
= (g
<< 8) | g
;
852 xcol
.blue
= (b
<< 8) | b
;
853 noFaultXAllocColor( client
, v
->display
,
854 cmap
, GET_COLORMAP_SIZE(v
),
855 &xcol
, &exact
, &alloced
);
860 assert(buffer
->num_alloced
<256);
861 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
862 buffer
->num_alloced
++;
867 buffer->color_table[gray*3+0] = xcol.pixel;
868 buffer->color_table[gray*3+1] = xcol.pixel;
869 buffer->color_table[gray*3+2] = xcol.pixel;
870 assert(xcol.pixel < 65536);
871 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
872 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
873 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
875 buffer
->color_table
[gray
] = xcol
.pixel
;
876 assert(xcol
.pixel
< 65536);
877 buffer
->pixel_to_r
[xcol
.pixel
] = gray
;
878 buffer
->pixel_to_g
[xcol
.pixel
] = gray
;
879 buffer
->pixel_to_b
[xcol
.pixel
] = gray
;
882 if (colorsfailed
&& _mesa_getenv("MESA_DEBUG")) {
884 "Note: %d out of 256 needed colors do not match exactly.\n",
890 v
->dithered_pf
= PF_Grayscale
;
891 v
->undithered_pf
= PF_Grayscale
;
898 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
899 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
900 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
901 * color. While this function was originally designed just for 8-bit
902 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
903 * Dithering code contributed by Bob Mercier.
905 static GLboolean
setup_dithered_color( int client
, XMesaVisual v
,
906 XMesaBuffer buffer
, XMesaColormap cmap
)
908 if (GET_VISUAL_DEPTH(v
)<4 || GET_VISUAL_DEPTH(v
)>16) {
913 XMesaBuffer prevBuffer
;
919 prevBuffer
= find_xmesa_buffer(v
->display
, cmap
, buffer
);
921 (buffer
->xm_visual
->mesa_visual
.rgbMode
==
922 prevBuffer
->xm_visual
->mesa_visual
.rgbMode
)) {
923 /* Copy colormap stuff from previous, matching XMesaBuffer.
924 * Do this to avoid time spent in noFaultXAllocColor.
926 copy_colortable_info(buffer
, prevBuffer
);
929 /* Allocate X colors and initialize color_table[], red_table[], etc */
931 int colorsfailed
= 0;
932 for (r
= 0; r
< DITH_R
; r
++) {
933 for (g
= 0; g
< DITH_G
; g
++) {
934 for (b
= 0; b
< DITH_B
; b
++) {
937 xcol
.red
=gamma_adjust(v
->RedGamma
, r
*65535/(DITH_R
-1),65535);
938 xcol
.green
=gamma_adjust(v
->GreenGamma
, g
*65535/(DITH_G
-1),65535);
939 xcol
.blue
=gamma_adjust(v
->BlueGamma
, b
*65535/(DITH_B
-1),65535);
940 noFaultXAllocColor( client
, v
->display
,
941 cmap
, GET_COLORMAP_SIZE(v
),
942 &xcol
, &exact
, &alloced
);
947 assert(buffer
->num_alloced
<256);
948 buffer
->alloced_colors
[buffer
->num_alloced
] = xcol
.pixel
;
949 buffer
->num_alloced
++;
951 i
= DITH_MIX( r
, g
, b
);
953 buffer
->color_table
[i
] = xcol
.pixel
;
954 assert(xcol
.pixel
< 65536);
955 buffer
->pixel_to_r
[xcol
.pixel
] = r
* 255 / (DITH_R
-1);
956 buffer
->pixel_to_g
[xcol
.pixel
] = g
* 255 / (DITH_G
-1);
957 buffer
->pixel_to_b
[xcol
.pixel
] = b
* 255 / (DITH_B
-1);
962 if (colorsfailed
&& _mesa_getenv("MESA_DEBUG")) {
964 "Note: %d out of %d needed colors do not match exactly.\n",
965 colorsfailed
, DITH_R
* DITH_G
* DITH_B
);
970 v
->dithered_pf
= PF_Dither
;
971 v
->undithered_pf
= PF_Lookup
;
977 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
978 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
979 * Special dithering tables have to be initialized.
981 static void setup_8bit_hpcr( XMesaVisual v
)
983 /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be)
984 * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
985 * on the root window AND the colormap obtainable by XGetRGBColormaps
986 * for that atom must be set on the window. (see also tkInitWindow)
987 * If that colormap is not set, the output will look stripy.
990 /* Setup color tables with gamma correction */
994 g
= 1.0 / v
->RedGamma
;
995 for (i
=0; i
<256; i
++) {
996 GLint red
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[0][i
]/255.0, g
));
997 v
->hpcr_rgbTbl
[0][i
] = CLAMP( red
, 16, 239 );
1000 g
= 1.0 / v
->GreenGamma
;
1001 for (i
=0; i
<256; i
++) {
1002 GLint green
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[1][i
]/255.0, g
));
1003 v
->hpcr_rgbTbl
[1][i
] = CLAMP( green
, 16, 239 );
1006 g
= 1.0 / v
->BlueGamma
;
1007 for (i
=0; i
<256; i
++) {
1008 GLint blue
= IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl
[2][i
]/255.0, g
));
1009 v
->hpcr_rgbTbl
[2][i
] = CLAMP( blue
, 32, 223 );
1011 v
->undithered_pf
= PF_HPCR
; /* can't really disable dithering for now */
1012 v
->dithered_pf
= PF_HPCR
;
1014 /* which method should I use to clear */
1015 /* GL_FALSE: keep the ordinary method */
1016 /* GL_TRUE : clear with dither pattern */
1017 v
->hpcr_clear_flag
= _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE
: GL_FALSE
;
1019 if (v
->hpcr_clear_flag
) {
1020 v
->hpcr_clear_pixmap
= XMesaCreatePixmap(v
->display
,
1021 DefaultRootWindow(v
->display
),
1023 #ifndef XFree86Server
1024 v
->hpcr_clear_ximage
= XGetImage(v
->display
, v
->hpcr_clear_pixmap
,
1025 0, 0, 16, 2, AllPlanes
, ZPixmap
);
1032 * Setup RGB rendering for a window with a True/DirectColor visual.
1034 static void setup_truecolor( XMesaVisual v
, XMesaBuffer buffer
,
1035 XMesaColormap cmap
)
1037 unsigned long rmask
, gmask
, bmask
;
1041 /* Compute red multiplier (mask) and bit shift */
1043 rmask
= GET_REDMASK(v
);
1044 while ((rmask
& 1)==0) {
1049 /* Compute green multiplier (mask) and bit shift */
1051 gmask
= GET_GREENMASK(v
);
1052 while ((gmask
& 1)==0) {
1057 /* Compute blue multiplier (mask) and bit shift */
1059 bmask
= GET_BLUEMASK(v
);
1060 while ((bmask
& 1)==0) {
1066 * Compute component-to-pixel lookup tables and dithering kernel
1069 static GLubyte kernel
[16] = {
1070 0*16, 8*16, 2*16, 10*16,
1071 12*16, 4*16, 14*16, 6*16,
1072 3*16, 11*16, 1*16, 9*16,
1073 15*16, 7*16, 13*16, 5*16,
1075 GLint rBits
= _mesa_bitcount(rmask
);
1076 GLint gBits
= _mesa_bitcount(gmask
);
1077 GLint bBits
= _mesa_bitcount(bmask
);
1081 /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1082 for (i
=0; i
<=rmask
; i
++)
1083 v
->PixelToR
[i
] = (unsigned char) ((i
* 255) / rmask
);
1084 for (i
=0; i
<=gmask
; i
++)
1085 v
->PixelToG
[i
] = (unsigned char) ((i
* 255) / gmask
);
1086 for (i
=0; i
<=bmask
; i
++)
1087 v
->PixelToB
[i
] = (unsigned char) ((i
* 255) / bmask
);
1089 /* convert RGB values from [0,255] to pixel components */
1091 for (i
=0;i
<256;i
++) {
1092 GLint r
= gamma_adjust(v
->RedGamma
, i
, 255);
1093 GLint g
= gamma_adjust(v
->GreenGamma
, i
, 255);
1094 GLint b
= gamma_adjust(v
->BlueGamma
, i
, 255);
1095 v
->RtoPixel
[i
] = (r
>> (8-rBits
)) << v
->rshift
;
1096 v
->GtoPixel
[i
] = (g
>> (8-gBits
)) << v
->gshift
;
1097 v
->BtoPixel
[i
] = (b
>> (8-bBits
)) << v
->bshift
;
1099 /* overflow protection */
1100 for (i
=256;i
<512;i
++) {
1101 v
->RtoPixel
[i
] = v
->RtoPixel
[255];
1102 v
->GtoPixel
[i
] = v
->GtoPixel
[255];
1103 v
->BtoPixel
[i
] = v
->BtoPixel
[255];
1106 /* setup dithering kernel */
1108 if (gBits
> maxBits
) maxBits
= gBits
;
1109 if (bBits
> maxBits
) maxBits
= bBits
;
1110 for (i
=0;i
<16;i
++) {
1111 v
->Kernel
[i
] = kernel
[i
] >> maxBits
;
1114 v
->undithered_pf
= PF_Truecolor
;
1115 v
->dithered_pf
= (GET_VISUAL_DEPTH(v
)<24) ? PF_Dither_True
: PF_Truecolor
;
1119 * Now check for TrueColor visuals which we can optimize.
1121 if ( GET_REDMASK(v
) ==0x0000ff
1122 && GET_GREENMASK(v
)==0x00ff00
1123 && GET_BLUEMASK(v
) ==0xff0000
1124 && CHECK_BYTE_ORDER(v
)
1125 && v
->BitsPerPixel
==32
1126 && sizeof(GLuint
)==4
1127 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1128 /* common 32 bpp config used on SGI, Sun */
1129 v
->undithered_pf
= v
->dithered_pf
= PF_8A8B8G8R
;
1131 else if (GET_REDMASK(v
) ==0xff0000
1132 && GET_GREENMASK(v
)==0x00ff00
1133 && GET_BLUEMASK(v
) ==0x0000ff
1134 && CHECK_BYTE_ORDER(v
)
1135 && v
->BitsPerPixel
==32
1136 && sizeof(GLuint
)==4
1137 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1138 /* common 32 bpp config used on Linux, HP, IBM */
1139 if (GET_VISUAL_DEPTH(v
)==32)
1140 v
->undithered_pf
= v
->dithered_pf
= PF_8A8R8G8B
;
1142 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B
;
1144 else if (GET_REDMASK(v
) ==0xff0000
1145 && GET_GREENMASK(v
)==0x00ff00
1146 && GET_BLUEMASK(v
) ==0x0000ff
1147 && CHECK_BYTE_ORDER(v
)
1148 && v
->BitsPerPixel
==24
1149 && sizeof(GLuint
)==4
1150 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1151 /* common packed 24 bpp config used on Linux */
1152 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B24
;
1154 else if (GET_REDMASK(v
) ==0xf800
1155 && GET_GREENMASK(v
)==0x07e0
1156 && GET_BLUEMASK(v
) ==0x001f
1157 && CHECK_BYTE_ORDER(v
)
1158 && v
->BitsPerPixel
==16
1159 && sizeof(GLushort
)==2
1160 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
1161 /* 5-6-5 color weight on common PC VGA boards */
1162 v
->undithered_pf
= PF_5R6G5B
;
1163 v
->dithered_pf
= PF_Dither_5R6G5B
;
1165 else if (GET_REDMASK(v
) ==0xe0
1166 && GET_GREENMASK(v
)==0x1c
1167 && GET_BLUEMASK(v
) ==0x03
1168 && CHECK_FOR_HPCR(v
)) {
1169 setup_8bit_hpcr( v
);
1176 * Setup RGB rendering for a window with a monochrome visual.
1178 static void setup_monochrome( XMesaVisual v
, XMesaBuffer b
)
1181 v
->dithered_pf
= v
->undithered_pf
= PF_1Bit
;
1182 /* if black=1 then we must flip pixel values */
1183 v
->bitFlip
= (GET_BLACK_PIXEL(v
) != 0);
1189 * When a context is "made current" for the first time, we can finally
1190 * finish initializing the context's visual and buffer information.
1191 * Input: v - the XMesaVisual to initialize
1192 * b - the XMesaBuffer to initialize (may be NULL)
1193 * rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1194 * window - the window/pixmap we're rendering into
1195 * cmap - the colormap associated with the window/pixmap
1196 * Return: GL_TRUE=success, GL_FALSE=failure
1198 static GLboolean
initialize_visual_and_buffer( int client
,
1202 XMesaDrawable window
,
1203 XMesaColormap cmap
)
1205 struct xmesa_renderbuffer
*front_xrb
, *back_xrb
;
1206 #ifndef XFree86Server
1211 assert(b
->xm_visual
== v
);
1215 front_xrb
= b
->frontxrb
;
1216 back_xrb
= b
->backxrb
;
1219 front_xrb
= back_xrb
= NULL
;
1222 /* Save true bits/pixel */
1223 v
->BitsPerPixel
= bits_per_pixel(v
);
1224 assert(v
->BitsPerPixel
> 0);
1227 if (rgb_flag
==GL_FALSE
) {
1228 /* COLOR-INDEXED WINDOW:
1229 * Even if the visual is TrueColor or DirectColor we treat it as
1230 * being color indexed. This is weird but might be useful to someone.
1232 v
->dithered_pf
= v
->undithered_pf
= PF_Index
;
1233 v
->mesa_visual
.indexBits
= GET_VISUAL_DEPTH(v
);
1237 * We support RGB rendering into almost any kind of visual.
1239 const int xclass
= v
->mesa_visual
.visualType
;
1240 if (xclass
==GLX_TRUE_COLOR
|| xclass
==GLX_DIRECT_COLOR
) {
1241 setup_truecolor( v
, b
, cmap
);
1243 else if (xclass
==GLX_STATIC_GRAY
&& GET_VISUAL_DEPTH(v
)==1) {
1244 setup_monochrome( v
, b
);
1246 else if (xclass
==GLX_GRAY_SCALE
|| xclass
==GLX_STATIC_GRAY
) {
1247 if (!setup_grayscale( client
, v
, b
, cmap
)) {
1251 else if ((xclass
==GLX_PSEUDO_COLOR
|| xclass
==GLX_STATIC_COLOR
)
1252 && GET_VISUAL_DEPTH(v
)>=4 && GET_VISUAL_DEPTH(v
)<=16) {
1253 if (!setup_dithered_color( client
, v
, b
, cmap
)) {
1258 _mesa_warning(NULL
, "XMesa: RGB mode rendering not supported in given visual.\n");
1261 v
->mesa_visual
.indexBits
= 0;
1263 if (_mesa_getenv("MESA_NO_DITHER")) {
1264 v
->dithered_pf
= v
->undithered_pf
;
1270 * If MESA_INFO env var is set print out some debugging info
1271 * which can help Brian figure out what's going on when a user
1274 if (_mesa_getenv("MESA_INFO")) {
1275 _mesa_printf("X/Mesa visual = %p\n", (void *) v
);
1276 _mesa_printf("X/Mesa dithered pf = %u\n", v
->dithered_pf
);
1277 _mesa_printf("X/Mesa undithered pf = %u\n", v
->undithered_pf
);
1278 _mesa_printf("X/Mesa level = %d\n", v
->mesa_visual
.level
);
1279 _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v
));
1280 _mesa_printf("X/Mesa bits per pixel = %d\n", v
->BitsPerPixel
);
1284 /* Do window-specific initializations */
1286 b
->frontxrb
->drawable
= window
;
1287 b
->frontxrb
->pixmap
= (XMesaPixmap
) window
;
1289 /* Setup for single/double buffering */
1290 if (v
->mesa_visual
.doubleBufferMode
) {
1291 /* Double buffered */
1292 b
->shm
= check_for_xshm( v
->display
);
1293 xmesa_alloc_back_buffer(b
, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
);
1296 /* X11 graphics contexts */
1297 #ifdef XFree86Server
1298 b
->gc
= CreateScratchGC(v
->display
, window
->depth
);
1300 b
->gc
= XCreateGC( v
->display
, window
, 0, NULL
);
1302 XMesaSetFunction( v
->display
, b
->gc
, GXcopy
);
1304 /* cleargc - for glClear() */
1305 #ifdef XFree86Server
1306 b
->cleargc
= CreateScratchGC(v
->display
, window
->depth
);
1308 b
->cleargc
= XCreateGC( v
->display
, window
, 0, NULL
);
1310 XMesaSetFunction( v
->display
, b
->cleargc
, GXcopy
);
1313 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1314 * Patch contributed by Michael Pichler May 15, 1995.
1316 #ifdef XFree86Server
1317 b
->swapgc
= CreateScratchGC(v
->display
, window
->depth
);
1321 dixChangeGC(NullClient
, b
->swapgc
, GCGraphicsExposures
, v
, NULL
);
1324 gcvalues
.graphics_exposures
= False
;
1325 b
->swapgc
= XCreateGC( v
->display
, window
,
1326 GCGraphicsExposures
, &gcvalues
);
1328 XMesaSetFunction( v
->display
, b
->swapgc
, GXcopy
);
1330 * Set fill style and tile pixmap once for all for HPCR stuff
1331 * (instead of doing it each time in clear_color_HPCR_pixmap())
1332 * Initialize whole stuff
1333 * Patch contributed by Jacques Leroy March 8, 1998.
1335 if (v
->hpcr_clear_flag
&& back_xrb
->pixmap
) {
1337 for (i
=0; i
<16; i
++)
1339 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 0, 0);
1340 XMesaPutPixel(v
->hpcr_clear_ximage
, i
, 1, 0);
1342 XMesaPutImage(b
->display
, (XMesaDrawable
) v
->hpcr_clear_pixmap
,
1343 b
->cleargc
, v
->hpcr_clear_ximage
, 0, 0, 0, 0, 16, 2);
1344 XMesaSetFillStyle( v
->display
, b
->cleargc
, FillTiled
);
1345 XMesaSetTile( v
->display
, b
->cleargc
, v
->hpcr_clear_pixmap
);
1348 /* Initialize the row buffer XImage for use in write_color_span() */
1349 #ifdef XFree86Server
1350 b
->rowimage
= XMesaCreateImage(GET_VISUAL_DEPTH(v
), MAX_WIDTH
, 1,
1351 (char *)MALLOC(MAX_WIDTH
*4));
1353 b
->rowimage
= XCreateImage( v
->display
,
1356 ZPixmap
, 0, /*format, offset*/
1357 (char*) MALLOC(MAX_WIDTH
*4), /*data*/
1358 MAX_WIDTH
, 1, /*width, height*/
1360 0 /*bytes_per_line*/ );
1372 * Convert an RGBA color to a pixel value.
1375 xmesa_color_to_pixel(GLcontext
*ctx
,
1376 GLubyte r
, GLubyte g
, GLubyte b
, GLubyte a
,
1379 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
1380 switch (pixelFormat
) {
1386 PACK_TRUECOLOR( p
, r
, g
, b
);
1390 return PACK_8A8B8G8R( r
, g
, b
, a
);
1392 return PACK_8A8R8G8B( r
, g
, b
, a
);
1396 return PACK_8R8G8B( r
, g
, b
);
1398 return PACK_5R6G5B( r
, g
, b
);
1402 return DITHER( 1, 0, r
, g
, b
);
1405 /* 382 = (3*255)/2 */
1406 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
1408 return DITHER_HPCR(1, 1, r
, g
, b
);
1412 return LOOKUP( r
, g
, b
);
1415 return GRAY_RGB( r
, g
, b
);
1416 case PF_Dither_True
:
1418 case PF_Dither_5R6G5B
:
1421 PACK_TRUEDITHER(p
, 1, 0, r
, g
, b
);
1425 _mesa_problem(ctx
, "Bad pixel format in xmesa_color_to_pixel");
1431 #define NUM_VISUAL_TYPES 6
1434 * Convert an X visual type to a GLX visual type.
1436 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
1438 * \return If \c visualType is a valid X visual type, a GLX visual type will
1439 * be returned. Otherwise \c GLX_NONE will be returned.
1442 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
1446 xmesa_convert_from_x_visual_type( int visualType
)
1448 static const int glx_visual_types
[ NUM_VISUAL_TYPES
] = {
1449 GLX_STATIC_GRAY
, GLX_GRAY_SCALE
,
1450 GLX_STATIC_COLOR
, GLX_PSEUDO_COLOR
,
1451 GLX_TRUE_COLOR
, GLX_DIRECT_COLOR
1454 return ( (unsigned) visualType
< NUM_VISUAL_TYPES
)
1455 ? glx_visual_types
[ visualType
] : GLX_NONE
;
1459 /**********************************************************************/
1460 /***** Public Functions *****/
1461 /**********************************************************************/
1465 * Create a new X/Mesa visual.
1466 * Input: display - X11 display
1467 * visinfo - an XVisualInfo pointer
1468 * rgb_flag - GL_TRUE = RGB mode,
1469 * GL_FALSE = color index mode
1470 * alpha_flag - alpha buffer requested?
1471 * db_flag - GL_TRUE = double-buffered,
1472 * GL_FALSE = single buffered
1473 * stereo_flag - stereo visual?
1474 * ximage_flag - GL_TRUE = use an XImage for back buffer,
1475 * GL_FALSE = use an off-screen pixmap for back buffer
1476 * depth_size - requested bits/depth values, or zero
1477 * stencil_size - requested bits/stencil values, or zero
1478 * accum_red_size - requested bits/red accum values, or zero
1479 * accum_green_size - requested bits/green accum values, or zero
1480 * accum_blue_size - requested bits/blue accum values, or zero
1481 * accum_alpha_size - requested bits/alpha accum values, or zero
1482 * num_samples - number of samples/pixel if multisampling, or zero
1483 * level - visual level, usually 0
1484 * visualCaveat - ala the GLX extension, usually GLX_NONE
1485 * Return; a new XMesaVisual or 0 if error.
1487 XMesaVisual
XMesaCreateVisual( XMesaDisplay
*display
,
1488 XMesaVisualInfo visinfo
,
1490 GLboolean alpha_flag
,
1492 GLboolean stereo_flag
,
1493 GLboolean ximage_flag
,
1496 GLint accum_red_size
,
1497 GLint accum_green_size
,
1498 GLint accum_blue_size
,
1499 GLint accum_alpha_size
,
1502 GLint visualCaveat
)
1506 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1508 /* For debugging only */
1509 if (_mesa_getenv("MESA_XSYNC")) {
1510 /* This makes debugging X easier.
1511 * In your debugger, set a breakpoint on _XError to stop when an
1512 * X protocol error is generated.
1514 #ifdef XFree86Server
1517 XSynchronize( display
, 1 );
1521 v
= (XMesaVisual
) CALLOC_STRUCT(xmesa_visual
);
1527 * In the X server, NULL is passed in for the display. It will have
1528 * to be set before using this visual. See XMesaSetVisualDisplay()
1531 v
->display
= display
;
1533 /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
1534 * the struct but we may need some of the information contained in it
1537 #ifndef XFree86Server
1538 v
->visinfo
= (XVisualInfo
*) MALLOC(sizeof(*visinfo
));
1543 MEMCPY(v
->visinfo
, visinfo
, sizeof(*visinfo
));
1546 /* check for MESA_GAMMA environment variable */
1547 gamma
= _mesa_getenv("MESA_GAMMA");
1549 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 0.0;
1550 sscanf( gamma
, "%f %f %f", &v
->RedGamma
, &v
->GreenGamma
, &v
->BlueGamma
);
1551 if (v
->RedGamma
<=0.0) v
->RedGamma
= 1.0;
1552 if (v
->GreenGamma
<=0.0) v
->GreenGamma
= v
->RedGamma
;
1553 if (v
->BlueGamma
<=0.0) v
->BlueGamma
= v
->RedGamma
;
1556 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 1.0;
1559 v
->ximage_flag
= ximage_flag
;
1561 #ifdef XFree86Server
1562 /* We could calculate these values by ourselves. nplanes is either the sum
1563 * of the red, green, and blue bits or the number index bits.
1564 * ColormapEntries is either (1U << index_bits) or
1565 * (1U << max(redBits, greenBits, blueBits)).
1567 assert(visinfo
->nplanes
> 0);
1568 v
->nplanes
= visinfo
->nplanes
;
1569 v
->ColormapEntries
= visinfo
->ColormapEntries
;
1571 v
->mesa_visual
.redMask
= visinfo
->redMask
;
1572 v
->mesa_visual
.greenMask
= visinfo
->greenMask
;
1573 v
->mesa_visual
.blueMask
= visinfo
->blueMask
;
1574 v
->mesa_visual
.visualID
= visinfo
->vid
;
1575 v
->mesa_visual
.screen
= 0; /* FIXME: What should be done here? */
1577 v
->mesa_visual
.redMask
= visinfo
->red_mask
;
1578 v
->mesa_visual
.greenMask
= visinfo
->green_mask
;
1579 v
->mesa_visual
.blueMask
= visinfo
->blue_mask
;
1580 v
->mesa_visual
.visualID
= visinfo
->visualid
;
1581 v
->mesa_visual
.screen
= visinfo
->screen
;
1584 #if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
1585 v
->mesa_visual
.visualType
= xmesa_convert_from_x_visual_type(visinfo
->class);
1587 v
->mesa_visual
.visualType
= xmesa_convert_from_x_visual_type(visinfo
->c_class
);
1590 v
->mesa_visual
.visualRating
= visualCaveat
;
1592 (void) initialize_visual_and_buffer( 0, v
, NULL
, rgb_flag
, 0, 0 );
1595 const int xclass
= v
->mesa_visual
.visualType
;
1596 if (xclass
==GLX_TRUE_COLOR
|| xclass
==GLX_DIRECT_COLOR
) {
1597 red_bits
= _mesa_bitcount(GET_REDMASK(v
));
1598 green_bits
= _mesa_bitcount(GET_GREENMASK(v
));
1599 blue_bits
= _mesa_bitcount(GET_BLUEMASK(v
));
1603 /* this is an approximation */
1605 depth
= GET_VISUAL_DEPTH(v
);
1606 red_bits
= depth
/ 3;
1608 green_bits
= depth
/ 2;
1609 depth
-= green_bits
;
1612 assert( red_bits
+ green_bits
+ blue_bits
== GET_VISUAL_DEPTH(v
) );
1616 if (alpha_flag
&& alpha_bits
== 0)
1619 _mesa_initialize_visual( &v
->mesa_visual
,
1620 rgb_flag
, db_flag
, stereo_flag
,
1621 red_bits
, green_bits
,
1622 blue_bits
, alpha_bits
,
1623 v
->mesa_visual
.indexBits
,
1626 accum_red_size
, accum_green_size
,
1627 accum_blue_size
, accum_alpha_size
,
1630 /* XXX minor hack */
1631 v
->mesa_visual
.level
= level
;
1636 void XMesaSetVisualDisplay( XMesaDisplay
*dpy
, XMesaVisual v
)
1642 void XMesaDestroyVisual( XMesaVisual v
)
1644 #ifndef XFree86Server
1645 _mesa_free(v
->visinfo
);
1653 * Create a new XMesaContext.
1654 * \param v the XMesaVisual
1655 * \param share_list another XMesaContext with which to share display
1656 * lists or NULL if no sharing is wanted.
1657 * \return an XMesaContext or NULL if error.
1659 XMesaContext
XMesaCreateContext( XMesaVisual v
, XMesaContext share_list
)
1661 static GLboolean firstTime
= GL_TRUE
;
1664 struct dd_function_table functions
;
1668 _glthread_INIT_MUTEX(_xmesa_lock
);
1669 firstTime
= GL_FALSE
;
1672 /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
1673 c
= (XMesaContext
) CALLOC_STRUCT(xmesa_context
);
1677 mesaCtx
= &(c
->mesa
);
1679 /* initialize with default driver functions, then plug in XMesa funcs */
1680 _mesa_init_driver_functions(&functions
);
1681 xmesa_init_driver_functions(v
, &functions
);
1682 if (!_mesa_initialize_context(mesaCtx
, &v
->mesa_visual
,
1683 share_list
? &(share_list
->mesa
) : (GLcontext
*) NULL
,
1684 &functions
, (void *) c
)) {
1689 _mesa_enable_sw_extensions(mesaCtx
);
1690 _mesa_enable_1_3_extensions(mesaCtx
);
1691 _mesa_enable_1_4_extensions(mesaCtx
);
1692 _mesa_enable_1_5_extensions(mesaCtx
);
1693 _mesa_enable_2_0_extensions(mesaCtx
);
1694 #if ENABLE_EXT_texure_compression_s3tc
1696 _mesa_enable_extension(mesaCtx
, "GL_EXT_texture_compression_s3tc");
1697 _mesa_enable_extension(mesaCtx
, "GL_S3_s3tc");
1699 _mesa_enable_extension(mesaCtx
, "GL_3DFX_texture_compression_FXT1");
1701 #if ENABLE_EXT_timer_query
1702 _mesa_enable_extension(mesaCtx
, "GL_EXT_timer_query");
1705 /* finish up xmesa context initializations */
1706 c
->swapbytes
= CHECK_BYTE_ORDER(v
) ? GL_FALSE
: GL_TRUE
;
1708 c
->xm_buffer
= NULL
; /* set later by XMesaMakeCurrent */
1709 c
->display
= v
->display
;
1710 c
->pixelformat
= v
->dithered_pf
; /* Dithering is enabled by default */
1712 /* Initialize the software rasterizer and helper modules.
1714 if (!_swrast_CreateContext( mesaCtx
) ||
1715 !_ac_CreateContext( mesaCtx
) ||
1716 !_tnl_CreateContext( mesaCtx
) ||
1717 !_swsetup_CreateContext( mesaCtx
)) {
1718 _mesa_free_context_data(&c
->mesa
);
1724 tnl
= TNL_CONTEXT(mesaCtx
);
1725 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
1727 xmesa_register_swrast_functions( mesaCtx
);
1728 _swsetup_Wakeup(mesaCtx
);
1735 void XMesaDestroyContext( XMesaContext c
)
1737 GLcontext
*mesaCtx
= &c
->mesa
;
1739 XMesaBuffer xmbuf
= XMESA_BUFFER(mesaCtx
->DrawBuffer
);
1741 if (xmbuf
&& xmbuf
->FXctx
)
1742 fxMesaDestroyContext(xmbuf
->FXctx
);
1744 _swsetup_DestroyContext( mesaCtx
);
1745 _swrast_DestroyContext( mesaCtx
);
1746 _tnl_DestroyContext( mesaCtx
);
1747 _ac_DestroyContext( mesaCtx
);
1748 _mesa_free_context_data( mesaCtx
);
1755 * XXX this isn't a public function! It's a hack for the 3Dfx driver.
1756 * Create a new XMesaBuffer from an X window.
1757 * Input: v - the XMesaVisual
1760 * Return: new XMesaBuffer or NULL if error
1763 XMesaCreateWindowBuffer2(XMesaVisual v
, XMesaWindow w
, XMesaContext c
)
1765 #ifndef XFree86Server
1766 XWindowAttributes attr
;
1778 /* Check that window depth matches visual depth */
1779 #ifdef XFree86Server
1780 client
= CLIENT_ID(((XMesaDrawable
)w
)->id
);
1782 if (GET_VISUAL_DEPTH(v
) != ((XMesaDrawable
)w
)->depth
) {
1783 _mesa_warning(NULL
, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1784 GET_VISUAL_DEPTH(v
), ((XMesaDrawable
) w
)->depth
);
1788 XGetWindowAttributes( v
->display
, w
, &attr
);
1790 if (GET_VISUAL_DEPTH(v
) != attr
.depth
) {
1791 _mesa_warning(NULL
, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1792 GET_VISUAL_DEPTH(v
), attr
.depth
);
1798 #ifdef XFree86Server
1799 cmap
= (ColormapPtr
)LookupIDByType(wColormap(w
), RT_COLORMAP
);
1801 if (attr
.colormap
) {
1802 cmap
= attr
.colormap
;
1805 _mesa_warning(NULL
, "Window %u has no colormap!\n", (unsigned int) w
);
1806 /* this is weird, a window w/out a colormap!? */
1807 /* OK, let's just allocate a new one and hope for the best */
1808 cmap
= XCreateColormap(v
->display
, w
, attr
.visual
, AllocNone
);
1812 b
= alloc_xmesa_buffer(v
, WINDOW
, cmap
);
1817 if (!initialize_visual_and_buffer( client
, v
, b
, v
->mesa_visual
.rgbMode
,
1818 (XMesaDrawable
) w
, cmap
)) {
1819 free_xmesa_buffer(client
, b
);
1824 fxEnvVar
= _mesa_getenv("MESA_GLX_FX");
1826 if (fxEnvVar
[0]!='d') {
1830 if (v
->mesa_visual
.depthBits
> 0) {
1831 attribs
[numAttribs
++] = FXMESA_DEPTH_SIZE
;
1832 attribs
[numAttribs
++] = v
->mesa_visual
.depthBits
;
1834 if (v
->mesa_visual
.doubleBufferMode
) {
1835 attribs
[numAttribs
++] = FXMESA_DOUBLEBUFFER
;
1837 if (v
->mesa_visual
.accumRedBits
> 0) {
1838 attribs
[numAttribs
++] = FXMESA_ACCUM_SIZE
;
1839 attribs
[numAttribs
++] = v
->mesa_visual
.accumRedBits
;
1841 if (v
->mesa_visual
.stencilBits
> 0) {
1842 attribs
[numAttribs
++] = FXMESA_STENCIL_SIZE
;
1843 attribs
[numAttribs
++] = v
->mesa_visual
.stencilBits
;
1845 if (v
->mesa_visual
.alphaBits
> 0) {
1846 attribs
[numAttribs
++] = FXMESA_ALPHA_SIZE
;
1847 attribs
[numAttribs
++] = v
->mesa_visual
.alphaBits
;
1850 attribs
[numAttribs
++] = FXMESA_SHARE_CONTEXT
;
1851 attribs
[numAttribs
++] = (int) &(c
->mesa
);
1853 attribs
[numAttribs
++] = FXMESA_NONE
;
1855 /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
1856 hw
= fxMesaSelectCurrentBoard(0);
1858 /* if these fail, there's a new bug somewhere */
1859 ASSERT(b
->mesa_buffer
.Width
> 0);
1860 ASSERT(b
->mesa_buffer
.Height
> 0);
1862 if ((hw
== GR_SSTTYPE_VOODOO
) || (hw
== GR_SSTTYPE_Voodoo2
)) {
1863 b
->FXctx
= fxMesaCreateBestContext(0, b
->mesa_buffer
.Width
,
1864 b
->mesa_buffer
.Height
, attribs
);
1865 if ((v
->undithered_pf
!=PF_Index
) && (b
->backxrb
->ximage
)) {
1866 b
->FXisHackUsable
= b
->FXctx
? GL_TRUE
: GL_FALSE
;
1867 if (b
->FXctx
&& (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')) {
1868 b
->FXwindowHack
= GL_TRUE
;
1869 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
1872 b
->FXwindowHack
= GL_FALSE
;
1877 if (fxEnvVar
[0]=='w' || fxEnvVar
[0]=='W')
1878 b
->FXctx
= fxMesaCreateContext(w
, GR_RESOLUTION_NONE
,
1879 GR_REFRESH_75Hz
, attribs
);
1881 b
->FXctx
= fxMesaCreateBestContext(0, b
->mesa_buffer
.Width
,
1882 b
->mesa_buffer
.Height
, attribs
);
1883 b
->FXisHackUsable
= GL_FALSE
;
1884 b
->FXwindowHack
= GL_FALSE
;
1888 "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1889 hw, b->mesa_buffer.Width, b->mesa_buffer.Height,
1890 b->FXisHackUsable, b->FXwindowHack);
1895 _mesa_warning(NULL
, "WARNING: This Mesa Library includes the Glide driver but\n");
1896 _mesa_warning(NULL
, " you have not defined the MESA_GLX_FX env. var.\n");
1897 _mesa_warning(NULL
, " (check the README.3DFX file for more information).\n\n");
1898 _mesa_warning(NULL
, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1907 XMesaCreateWindowBuffer(XMesaVisual v
, XMesaWindow w
)
1909 return XMesaCreateWindowBuffer2( v
, w
, NULL
);
1914 * Create a new XMesaBuffer from an X pixmap.
1916 * \param v the XMesaVisual
1917 * \param p the pixmap
1918 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1919 * \c GLX_DIRECT_COLOR visual for the pixmap
1920 * \returns new XMesaBuffer or NULL if error
1923 XMesaCreatePixmapBuffer(XMesaVisual v
, XMesaPixmap p
, XMesaColormap cmap
)
1930 b
= alloc_xmesa_buffer(v
, PIXMAP
, cmap
);
1935 #ifdef XFree86Server
1936 client
= CLIENT_ID(((XMesaDrawable
)p
)->id
);
1939 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1940 (XMesaDrawable
) p
, cmap
)) {
1941 free_xmesa_buffer(client
, b
);
1951 XMesaCreatePBuffer(XMesaVisual v
, XMesaColormap cmap
,
1952 unsigned int width
, unsigned int height
)
1954 #ifdef XFree86Server
1959 XMesaDrawable drawable
; /* X Pixmap Drawable */
1962 b
= alloc_xmesa_buffer(v
, PBUFFER
, cmap
);
1967 /* allocate pixmap for front buffer */
1968 root
= RootWindow( v
->display
, v
->visinfo
->screen
);
1969 drawable
= XCreatePixmap( v
->display
, root
, width
, height
, v
->visinfo
->depth
);
1971 if (!initialize_visual_and_buffer(client
, v
, b
, v
->mesa_visual
.rgbMode
,
1973 free_xmesa_buffer(client
, b
);
1984 * Deallocate an XMesaBuffer structure and all related info.
1986 void XMesaDestroyBuffer( XMesaBuffer b
)
1990 #ifdef XFree86Server
1991 if (b
->frontxrb
->drawable
)
1992 client
= CLIENT_ID(b
->frontxrb
->drawable
->id
);
1995 if (b
->gc
) XMesaFreeGC( b
->xm_visual
->display
, b
->gc
);
1996 if (b
->cleargc
) XMesaFreeGC( b
->xm_visual
->display
, b
->cleargc
);
1997 if (b
->swapgc
) XMesaFreeGC( b
->xm_visual
->display
, b
->swapgc
);
1999 if (b
->xm_visual
->mesa_visual
.doubleBufferMode
)
2001 if (b
->backxrb
->ximage
) {
2002 #if defined(USE_XSHM) && !defined(XFree86Server)
2004 XShmDetach( b
->xm_visual
->display
, &b
->shminfo
);
2005 XDestroyImage( b
->backxrb
->ximage
);
2006 shmdt( b
->shminfo
.shmaddr
);
2010 XMesaDestroyImage( b
->backxrb
->ximage
);
2012 if (b
->backxrb
->pixmap
) {
2013 XMesaFreePixmap( b
->xm_visual
->display
, b
->backxrb
->pixmap
);
2014 if (b
->xm_visual
->hpcr_clear_flag
) {
2015 XMesaFreePixmap( b
->xm_visual
->display
,
2016 b
->xm_visual
->hpcr_clear_pixmap
);
2017 XMesaDestroyImage( b
->xm_visual
->hpcr_clear_ximage
);
2022 _mesa_free( b
->rowimage
->data
);
2023 b
->rowimage
->data
= NULL
;
2024 XMesaDestroyImage( b
->rowimage
);
2027 free_xmesa_buffer(client
, b
);
2033 * Bind buffer b to context c and make c the current rendering context.
2035 GLboolean
XMesaMakeCurrent( XMesaContext c
, XMesaBuffer b
)
2037 return XMesaMakeCurrent2( c
, b
, b
);
2042 * Bind buffer b to context c and make c the current rendering context.
2044 GLboolean
XMesaMakeCurrent2( XMesaContext c
, XMesaBuffer drawBuffer
,
2045 XMesaBuffer readBuffer
)
2048 if (!drawBuffer
|| !readBuffer
)
2049 return GL_FALSE
; /* must specify buffers! */
2052 if (drawBuffer
->FXctx
) {
2053 fxMesaMakeCurrent(drawBuffer
->FXctx
);
2055 c
->xm_buffer
= drawBuffer
;
2060 if (&(c
->mesa
) == _mesa_get_current_context()
2061 && c
->mesa
.DrawBuffer
== &drawBuffer
->mesa_buffer
2062 && c
->mesa
.ReadBuffer
== &readBuffer
->mesa_buffer
2063 && ((XMesaBuffer
) c
->mesa
.DrawBuffer
)->wasCurrent
) {
2064 /* same context and buffer, do nothing */
2068 c
->xm_buffer
= drawBuffer
;
2070 _mesa_make_current(&(c
->mesa
),
2071 &drawBuffer
->mesa_buffer
,
2072 &readBuffer
->mesa_buffer
);
2074 if (c
->xm_visual
->mesa_visual
.rgbMode
) {
2076 * Must recompute and set these pixel values because colormap
2077 * can be different for different windows.
2079 c
->clearpixel
= xmesa_color_to_pixel( &c
->mesa
,
2084 c
->xm_visual
->undithered_pf
);
2085 XMesaSetForeground(c
->display
, drawBuffer
->cleargc
, c
->clearpixel
);
2088 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2089 drawBuffer
->wasCurrent
= GL_TRUE
;
2093 _mesa_make_current( NULL
, NULL
, NULL
);
2100 * Unbind the context c from its buffer.
2102 GLboolean
XMesaUnbindContext( XMesaContext c
)
2104 /* A no-op for XFree86 integration purposes */
2109 XMesaContext
XMesaGetCurrentContext( void )
2111 GET_CURRENT_CONTEXT(ctx
);
2113 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
2122 XMesaBuffer
XMesaGetCurrentBuffer( void )
2124 GET_CURRENT_CONTEXT(ctx
);
2126 XMesaBuffer xmbuf
= XMESA_BUFFER(ctx
->DrawBuffer
);
2135 /* New in Mesa 3.1 */
2136 XMesaBuffer
XMesaGetCurrentReadBuffer( void )
2138 GET_CURRENT_CONTEXT(ctx
);
2140 return (XMesaBuffer
) (ctx
->ReadBuffer
);
2148 GLboolean
XMesaForceCurrent(XMesaContext c
)
2151 if (&(c
->mesa
) != _mesa_get_current_context()) {
2152 _mesa_make_current(&c
->mesa
, c
->mesa
.DrawBuffer
, c
->mesa
.ReadBuffer
);
2156 _mesa_make_current(NULL
, NULL
, NULL
);
2162 GLboolean
XMesaLoseCurrent(XMesaContext c
)
2165 _mesa_make_current(NULL
, NULL
, NULL
);
2171 * Switch 3Dfx support hack between window and full-screen mode.
2173 GLboolean
XMesaSetFXmode( GLint mode
)
2176 const char *fx
= _mesa_getenv("MESA_GLX_FX");
2177 if (fx
&& fx
[0] != 'd') {
2178 GET_CURRENT_CONTEXT(ctx
);
2179 GrHwConfiguration hw
;
2180 if (!FX_grSstQueryHardware(&hw
)) {
2181 /*fprintf(stderr, "!grSstQueryHardware\n");*/
2184 if (hw
.num_sst
< 1) {
2185 /*fprintf(stderr, "hw.num_sst < 1\n");*/
2189 /* [dBorca] Hack alert:
2190 * oh, this is sooo wrong: ctx above is
2191 * really an fxMesaContext, not an XMesaContext
2193 XMesaBuffer xmbuf
= XMESA_BUFFER(ctx
->DrawBuffer
);
2194 if (mode
== XMESA_FX_WINDOW
) {
2195 if (xmbuf
->FXisHackUsable
) {
2196 FX_grSstControl(GR_CONTROL_DEACTIVATE
);
2197 xmbuf
->FXwindowHack
= GL_TRUE
;
2201 else if (mode
== XMESA_FX_FULLSCREEN
) {
2202 FX_grSstControl(GR_CONTROL_ACTIVATE
);
2203 xmbuf
->FXwindowHack
= GL_FALSE
;
2207 /* Error: Bad mode value */
2211 /*fprintf(stderr, "fallthrough\n");*/
2222 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2224 static void FXgetImage( XMesaBuffer b
)
2226 GET_CURRENT_CONTEXT(ctx
);
2227 static unsigned short pixbuf
[MAX_WIDTH
];
2231 unsigned int bw
, depth
, width
, height
;
2232 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
2234 #ifdef XFree86Server
2235 x
= b
->frontxrb
->pixmap
->x
;
2236 y
= b
->frontxrb
->pixmap
->y
;
2237 width
= b
->frontxrb
->pixmap
->width
;
2238 height
= b
->frontxrb
->pixmap
->height
;
2239 depth
= b
->frontxrb
->pixmap
->depth
;
2241 XGetGeometry( b
->xm_visual
->display
, b
->frontxrb
->pixmap
,
2242 &root
, &xpos
, &ypos
, &width
, &height
, &bw
, &depth
);
2244 if (b
->mesa_buffer
.Width
!= width
|| b
->mesa_buffer
.Height
!= height
) {
2245 b
->mesa_buffer
.Width
= MIN2((int)width
, b
->FXctx
->width
);
2246 b
->mesa_buffer
.Height
= MIN2((int)height
, b
->FXctx
->height
);
2247 if (b
->mesa_buffer
.Width
& 1)
2248 b
->mesa_buffer
.Width
--; /* prevent odd width */
2249 xmesa_alloc_back_buffer(b
, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
);
2252 /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
2253 /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
2254 if (b
->xm_visual
->undithered_pf
==PF_5R6G5B
) {
2255 /* Special case: 16bpp RGB */
2256 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
, /* src buffer */
2257 0, b
->FXctx
->height
- b
->mesa_buffer
.Height
, /*pos*/
2258 b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
, /* size */
2259 b
->mesa_buffer
.Width
* sizeof(GLushort
), /* stride */
2260 b
->backxrb
->ximage
->data
); /* dest buffer */
2262 else if (b
->xm_visual
->dithered_pf
==PF_Dither
2263 && GET_VISUAL_DEPTH(b
->xm_visual
)==8) {
2264 /* Special case: 8bpp RGB */
2265 for (y
=0;y
<b
->mesa_buffer
.Height
;y
++) {
2266 GLubyte
*ptr
= (GLubyte
*) b
->backxrb
->ximage
->data
2267 + b
->backxrb
->ximage
->bytes_per_line
* y
;
2270 /* read row from 3Dfx frame buffer */
2271 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
,
2272 0, b
->FXctx
->height
-(b
->mesa_buffer
.Height
-y
),
2273 b
->mesa_buffer
.Width
, 1,
2277 /* write to XImage back buffer */
2278 for (x
=0;x
<b
->mesa_buffer
.Width
;x
++) {
2279 GLubyte r
= (pixbuf
[x
] & 0xf800) >> 8;
2280 GLubyte g
= (pixbuf
[x
] & 0x07e0) >> 3;
2281 GLubyte b
= (pixbuf
[x
] & 0x001f) << 3;
2282 *ptr
++ = XDITHER( x
, r
, g
, b
);
2287 /* General case: slow! */
2288 for (y
=0;y
<b
->mesa_buffer
.Height
;y
++) {
2289 /* read row from 3Dfx frame buffer */
2290 grLfbReadRegion( GR_BUFFER_FRONTBUFFER
,
2291 0, b
->FXctx
->height
-(b
->mesa_buffer
.Height
-y
),
2292 b
->mesa_buffer
.Width
, 1,
2296 /* write to XImage back buffer */
2297 for (x
=0;x
<b
->mesa_buffer
.Width
;x
++) {
2298 XMesaPutPixel(b
->backxrb
->ximage
,x
,y
,
2299 xmesa_color_to_pixel(ctx
,
2300 (pixbuf
[x
] & 0xf800) >> 8,
2301 (pixbuf
[x
] & 0x07e0) >> 3,
2302 (pixbuf
[x
] & 0x001f) << 3,
2304 b
->xm_visual
->undithered_pf
));
2308 /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
2314 * Copy the back buffer to the front buffer. If there's no back buffer
2317 void XMesaSwapBuffers( XMesaBuffer b
)
2319 GET_CURRENT_CONTEXT(ctx
);
2322 /* single buffered */
2326 /* If we're swapping the buffer associated with the current context
2327 * we have to flush any pending rendering commands first.
2329 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
2330 _mesa_notifySwapBuffers(ctx
);
2335 fxMesaSwapBuffers();
2337 if (b
->FXwindowHack
)
2343 if (b
->backxrb
->ximage
) {
2344 /* Copy Ximage from host's memory to server's window */
2345 #if defined(USE_XSHM) && !defined(XFree86Server)
2347 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2348 XShmPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
,
2350 b
->backxrb
->ximage
, 0, 0,
2351 0, 0, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
,
2353 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2358 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2359 XMesaPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
,
2361 b
->backxrb
->ximage
, 0, 0,
2362 0, 0, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
);
2363 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2367 /* Copy pixmap to window on server */
2368 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2369 XMesaCopyArea( b
->xm_visual
->display
,
2370 b
->backxrb
->pixmap
, /* source drawable */
2371 b
->frontxrb
->drawable
, /* dest. drawable */
2373 0, 0, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
,
2374 0, 0 /* dest region */
2376 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2379 #if !defined(XFree86Server)
2380 XSync( b
->xm_visual
->display
, False
);
2387 * Copy sub-region of back buffer to front buffer
2389 void XMesaCopySubBuffer( XMesaBuffer b
, int x
, int y
, int width
, int height
)
2391 GET_CURRENT_CONTEXT(ctx
);
2393 /* If we're swapping the buffer associated with the current context
2394 * we have to flush any pending rendering commands first.
2396 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
2397 _mesa_notifySwapBuffers(ctx
);
2400 /* single buffered */
2405 int yTop
= b
->mesa_buffer
.Height
- y
- height
;
2408 fxMesaSwapBuffers();
2409 if (b
->FXwindowHack
)
2415 if (b
->backxrb
->ximage
) {
2416 /* Copy Ximage from host's memory to server's window */
2417 #if defined(USE_XSHM) && !defined(XFree86Server)
2419 /* XXX assuming width and height aren't too large! */
2420 XShmPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
,
2422 b
->backxrb
->ximage
, x
, yTop
,
2423 x
, yTop
, width
, height
, False
);
2424 /* wait for finished event??? */
2429 /* XXX assuming width and height aren't too large! */
2430 XMesaPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
,
2432 b
->backxrb
->ximage
, x
, yTop
,
2433 x
, yTop
, width
, height
);
2437 /* Copy pixmap to window on server */
2438 XMesaCopyArea( b
->xm_visual
->display
,
2439 b
->backxrb
->pixmap
, /* source drawable */
2440 b
->frontxrb
->drawable
, /* dest. drawable */
2442 x
, yTop
, width
, height
, /* source region */
2443 x
, yTop
/* dest region */
2451 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
2452 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2453 * back buffer directly.
2454 * Output: pixmap - pointer to back buffer's Pixmap, or 0
2455 * ximage - pointer to back buffer's XImage, or NULL
2456 * Return: GL_TRUE = context is double buffered
2457 * GL_FALSE = context is single buffered
2459 #ifndef XFree86Server
2460 GLboolean
XMesaGetBackBuffer( XMesaBuffer b
,
2461 XMesaPixmap
*pixmap
,
2462 XMesaImage
**ximage
)
2466 *pixmap
= b
->backxrb
->pixmap
;
2468 *ximage
= b
->backxrb
->ximage
;
2477 #endif /* XFree86Server */
2481 * Return the depth buffer associated with an XMesaBuffer.
2482 * Input: b - the XMesa buffer handle
2483 * Output: width, height - size of buffer in pixels
2484 * bytesPerValue - bytes per depth value (2 or 4)
2485 * buffer - pointer to depth buffer values
2486 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
2488 GLboolean
XMesaGetDepthBuffer( XMesaBuffer b
, GLint
*width
, GLint
*height
,
2489 GLint
*bytesPerValue
, void **buffer
)
2491 struct gl_renderbuffer
*rb
2492 = b
->mesa_buffer
.Attachment
[BUFFER_DEPTH
].Renderbuffer
;
2493 if (!rb
|| !rb
->Data
) {
2501 *width
= b
->mesa_buffer
.Width
;
2502 *height
= b
->mesa_buffer
.Height
;
2503 *bytesPerValue
= b
->mesa_buffer
.Visual
.depthBits
<= 16
2504 ? sizeof(GLushort
) : sizeof(GLuint
);
2511 void XMesaFlush( XMesaContext c
)
2513 if (c
&& c
->xm_visual
) {
2514 #ifdef XFree86Server
2517 XSync( c
->xm_visual
->display
, False
);
2524 const char *XMesaGetString( XMesaContext c
, int name
)
2527 if (name
==XMESA_VERSION
) {
2530 else if (name
==XMESA_EXTENSIONS
) {
2540 XMesaBuffer
XMesaFindBuffer( XMesaDisplay
*dpy
, XMesaDrawable d
)
2543 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
2544 if (b
->frontxrb
->drawable
== d
&& b
->display
== dpy
) {
2554 * Look for XMesaBuffers whose X window has been destroyed.
2555 * Deallocate any such XMesaBuffers.
2557 void XMesaGarbageCollect( void )
2559 XMesaBuffer b
, next
;
2560 for (b
=XMesaBufferList
; b
; b
=next
) {
2562 if (b
->display
&& b
->frontxrb
->drawable
&& b
->type
== WINDOW
) {
2563 #ifdef XFree86Server
2566 XSync(b
->display
, False
);
2567 if (!window_exists( b
->display
, b
->frontxrb
->drawable
)) {
2568 /* found a dead window, free the ancillary info */
2569 XMesaDestroyBuffer( b
);
2577 void XMesaReset( void )
2579 while (XMesaBufferList
)
2580 XMesaDestroyBuffer(XMesaBufferList
);
2582 XMesaBufferList
= NULL
;
2586 unsigned long XMesaDitherColor( XMesaContext xmesa
, GLint x
, GLint y
,
2587 GLfloat red
, GLfloat green
,
2588 GLfloat blue
, GLfloat alpha
)
2590 GLcontext
*ctx
= &xmesa
->mesa
;
2591 GLint r
= (GLint
) (red
* 255.0F
);
2592 GLint g
= (GLint
) (green
* 255.0F
);
2593 GLint b
= (GLint
) (blue
* 255.0F
);
2594 GLint a
= (GLint
) (alpha
* 255.0F
);
2596 switch (xmesa
->pixelformat
) {
2602 PACK_TRUECOLOR( p
, r
, g
, b
);
2606 return PACK_8A8B8G8R( r
, g
, b
, a
);
2608 return PACK_8A8R8G8B( r
, g
, b
, a
);
2610 return PACK_8R8G8B( r
, g
, b
);
2612 return PACK_5R6G5B( r
, g
, b
);
2616 return DITHER( x
, y
, r
, g
, b
);
2619 /* 382 = (3*255)/2 */
2620 return ((r
+g
+b
) > 382) ^ xmesa
->xm_visual
->bitFlip
;
2622 return DITHER_HPCR(x
, y
, r
, g
, b
);
2626 return LOOKUP( r
, g
, b
);
2629 return GRAY_RGB( r
, g
, b
);
2630 case PF_Dither_5R6G5B
:
2632 case PF_Dither_True
:
2635 PACK_TRUEDITHER(p
, x
, y
, r
, g
, b
);
2639 _mesa_problem(NULL
, "Bad pixel format in XMesaDitherColor");
2646 * This is typically called when the window size changes and we need
2647 * to reallocate the buffer's back/depth/stencil/accum buffers.
2649 void XMesaResizeBuffers( XMesaBuffer b
)
2651 #ifdef XFree86Server
2652 GLuint winwidth
, winheight
;
2653 GET_CURRENT_CONTEXT(ctx
);
2655 winwidth
= MIN2(b
->frontxrb
->drawable
->width
, MAX_WIDTH
);
2656 winheight
= MIN2(b
->frontxrb
->drawable
->height
, MAX_HEIGHT
);
2658 xmesa_resize_buffers(ctx
, &(b
->mesa_buffer
), winwidth
, winheight
);
2662 unsigned int width
, height
, bw
, depth
;
2663 GET_CURRENT_CONTEXT(ctx
);
2664 XGetGeometry( b
->xm_visual
->display
, b
->frontxrb
->pixmap
,
2665 &root
, &xpos
, &ypos
, &width
, &height
, &bw
, &depth
);
2666 xmesa_resize_buffers(ctx
, &(b
->mesa_buffer
), width
, height
);