xm_api.c revision e5fce1694cdfca615022bf7b987835384902aceb
153f17a9db278d33517d9888dd77848f554522a38JP Abgrall/*
253f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Mesa 3-D graphics library
353f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Version:  6.5
453f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
553f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
653f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
753f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Permission is hereby granted, free of charge, to any person obtaining a
853f17a9db278d33517d9888dd77848f554522a38JP Abgrall * copy of this software and associated documentation files (the "Software"),
953f17a9db278d33517d9888dd77848f554522a38JP Abgrall * to deal in the Software without restriction, including without limitation
1053f17a9db278d33517d9888dd77848f554522a38JP Abgrall * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1153f17a9db278d33517d9888dd77848f554522a38JP Abgrall * and/or sell copies of the Software, and to permit persons to whom the
1253f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Software is furnished to do so, subject to the following conditions:
1353f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
1453f17a9db278d33517d9888dd77848f554522a38JP Abgrall * The above copyright notice and this permission notice shall be included
1553f17a9db278d33517d9888dd77848f554522a38JP Abgrall * in all copies or substantial portions of the Software.
1653f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
1753f17a9db278d33517d9888dd77848f554522a38JP Abgrall * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1853f17a9db278d33517d9888dd77848f554522a38JP Abgrall * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1953f17a9db278d33517d9888dd77848f554522a38JP Abgrall * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2053f17a9db278d33517d9888dd77848f554522a38JP Abgrall * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2153f17a9db278d33517d9888dd77848f554522a38JP Abgrall * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2253f17a9db278d33517d9888dd77848f554522a38JP Abgrall * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2353f17a9db278d33517d9888dd77848f554522a38JP Abgrall */
2453f17a9db278d33517d9888dd77848f554522a38JP Abgrall
2553f17a9db278d33517d9888dd77848f554522a38JP Abgrall/*
2653f17a9db278d33517d9888dd77848f554522a38JP Abgrall * This file contains the implementations of all the XMesa* functions.
2753f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
2853f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
2953f17a9db278d33517d9888dd77848f554522a38JP Abgrall * NOTES:
3053f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
3153f17a9db278d33517d9888dd77848f554522a38JP Abgrall * The window coordinate system origin (0,0) is in the lower-left corner
3253f17a9db278d33517d9888dd77848f554522a38JP Abgrall * of the window.  X11's window coordinate origin is in the upper-left
3353f17a9db278d33517d9888dd77848f554522a38JP Abgrall * corner of the window.  Therefore, most drawing functions in this
3453f17a9db278d33517d9888dd77848f554522a38JP Abgrall * file have to flip Y coordinates.
3553f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
3653f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
3753f17a9db278d33517d9888dd77848f554522a38JP Abgrall * in support for the MIT Shared Memory extension.  If enabled, when you
3853f17a9db278d33517d9888dd77848f554522a38JP Abgrall * use an Ximage for the back buffer in double buffered mode, the "swap"
3953f17a9db278d33517d9888dd77848f554522a38JP Abgrall * operation will be faster.  You must also link with -lXext.
4053f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
4153f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Byte swapping:  If the Mesa host and the X display use a different
4253f17a9db278d33517d9888dd77848f554522a38JP Abgrall * byte order then there's some trickiness to be aware of when using
4353f17a9db278d33517d9888dd77848f554522a38JP Abgrall * XImages.  The byte ordering used for the XImage is that of the X
4453f17a9db278d33517d9888dd77848f554522a38JP Abgrall * display, not the Mesa host.
4553f17a9db278d33517d9888dd77848f554522a38JP Abgrall * The color-to-pixel encoding for True/DirectColor must be done
4653f17a9db278d33517d9888dd77848f554522a38JP Abgrall * according to the display's visual red_mask, green_mask, and blue_mask.
4753f17a9db278d33517d9888dd77848f554522a38JP Abgrall * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
4853f17a9db278d33517d9888dd77848f554522a38JP Abgrall * do byte swapping if needed.  If one wants to directly "poke" the pixel
4953f17a9db278d33517d9888dd77848f554522a38JP Abgrall * into the XImage's buffer then the pixel must be byte swapped first.  In
5053f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
5153f17a9db278d33517d9888dd77848f554522a38JP Abgrall * and use XPutPixel everywhere except in the implementation of
5253f17a9db278d33517d9888dd77848f554522a38JP Abgrall * glClear(GL_COLOR_BUFFER_BIT).  We want this function to be fast so
5353f17a9db278d33517d9888dd77848f554522a38JP Abgrall * instead of using XPutPixel we "poke" our values after byte-swapping
5453f17a9db278d33517d9888dd77848f554522a38JP Abgrall * the clear pixel value if needed.
5553f17a9db278d33517d9888dd77848f554522a38JP Abgrall *
5653f17a9db278d33517d9888dd77848f554522a38JP Abgrall */
5753f17a9db278d33517d9888dd77848f554522a38JP Abgrall
5853f17a9db278d33517d9888dd77848f554522a38JP Abgrall#ifdef __CYGWIN__
5953f17a9db278d33517d9888dd77848f554522a38JP Abgrall#undef WIN32
6053f17a9db278d33517d9888dd77848f554522a38JP Abgrall#undef __WIN32__
6153f17a9db278d33517d9888dd77848f554522a38JP Abgrall#endif
6253f17a9db278d33517d9888dd77848f554522a38JP Abgrall
6353f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "glxheader.h"
6453f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "GL/xmesa.h"
6553f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "xmesaP.h"
6653f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "context.h"
6753f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "extensions.h"
6853f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "framebuffer.h"
6953f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "glthread.h"
7053f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "imports.h"
7153f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "matrix.h"
7253f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "mtypes.h"
7353f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "macros.h"
7453f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "renderbuffer.h"
7553f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "texformat.h"
7653f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "texobj.h"
7753f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "texstore.h"
7853f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "swrast/swrast.h"
7953f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "swrast_setup/swrast_setup.h"
8053f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "array_cache/acache.h"
8153f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "tnl/tnl.h"
8253f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "tnl/t_context.h"
8353f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "tnl/t_pipeline.h"
8453f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include "drivers/common/driverfuncs.h"
8553f17a9db278d33517d9888dd77848f554522a38JP Abgrall
8653f17a9db278d33517d9888dd77848f554522a38JP Abgrall#ifdef XFree86Server
8753f17a9db278d33517d9888dd77848f554522a38JP Abgrall#include <GL/glxtokens.h>
8853f17a9db278d33517d9888dd77848f554522a38JP Abgrall#endif
8953f17a9db278d33517d9888dd77848f554522a38JP Abgrall
9053f17a9db278d33517d9888dd77848f554522a38JP Abgrall/*
9153f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Global X driver lock
9253f17a9db278d33517d9888dd77848f554522a38JP Abgrall */
9353f17a9db278d33517d9888dd77848f554522a38JP Abgrall_glthread_Mutex _xmesa_lock;
9453f17a9db278d33517d9888dd77848f554522a38JP Abgrall
9553f17a9db278d33517d9888dd77848f554522a38JP Abgrall
9653f17a9db278d33517d9888dd77848f554522a38JP Abgrall
9753f17a9db278d33517d9888dd77848f554522a38JP Abgrall/*
9853f17a9db278d33517d9888dd77848f554522a38JP Abgrall * Lookup tables for HPCR pixel format:
9953f17a9db278d33517d9888dd77848f554522a38JP Abgrall */
10053f17a9db278d33517d9888dd77848f554522a38JP Abgrallstatic short hpcr_rgbTbl[3][256] = {
10153f17a9db278d33517d9888dd77848f554522a38JP Abgrall{
10253f17a9db278d33517d9888dd77848f554522a38JP Abgrall 16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
10353f17a9db278d33517d9888dd77848f554522a38JP Abgrall 24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
10453f17a9db278d33517d9888dd77848f554522a38JP Abgrall 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
10553f17a9db278d33517d9888dd77848f554522a38JP Abgrall 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
10653f17a9db278d33517d9888dd77848f554522a38JP Abgrall 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
10753f17a9db278d33517d9888dd77848f554522a38JP Abgrall 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
10853f17a9db278d33517d9888dd77848f554522a38JP Abgrall 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
10953f17a9db278d33517d9888dd77848f554522a38JP Abgrall 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
11053f17a9db278d33517d9888dd77848f554522a38JP Abgrall112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
11153f17a9db278d33517d9888dd77848f554522a38JP Abgrall128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
11253f17a9db278d33517d9888dd77848f554522a38JP Abgrall144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
11353f17a9db278d33517d9888dd77848f554522a38JP Abgrall160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
11453f17a9db278d33517d9888dd77848f554522a38JP Abgrall176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
11553f17a9db278d33517d9888dd77848f554522a38JP Abgrall192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
11653f17a9db278d33517d9888dd77848f554522a38JP Abgrall208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
11753f17a9db278d33517d9888dd77848f554522a38JP Abgrall224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
11853f17a9db278d33517d9888dd77848f554522a38JP Abgrall},
11953f17a9db278d33517d9888dd77848f554522a38JP Abgrall{
12053f17a9db278d33517d9888dd77848f554522a38JP Abgrall 16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
12153f17a9db278d33517d9888dd77848f554522a38JP Abgrall 24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
12253f17a9db278d33517d9888dd77848f554522a38JP Abgrall 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
12353f17a9db278d33517d9888dd77848f554522a38JP Abgrall 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
12453f17a9db278d33517d9888dd77848f554522a38JP Abgrall 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
12553f17a9db278d33517d9888dd77848f554522a38JP Abgrall 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
12653f17a9db278d33517d9888dd77848f554522a38JP Abgrall 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
12753f17a9db278d33517d9888dd77848f554522a38JP Abgrall 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
12853f17a9db278d33517d9888dd77848f554522a38JP Abgrall112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
12953f17a9db278d33517d9888dd77848f554522a38JP Abgrall128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
13053f17a9db278d33517d9888dd77848f554522a38JP Abgrall144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
13153f17a9db278d33517d9888dd77848f554522a38JP Abgrall160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
13253f17a9db278d33517d9888dd77848f554522a38JP Abgrall176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
13353f17a9db278d33517d9888dd77848f554522a38JP Abgrall192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
13453f17a9db278d33517d9888dd77848f554522a38JP Abgrall208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
13553f17a9db278d33517d9888dd77848f554522a38JP Abgrall224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
13653f17a9db278d33517d9888dd77848f554522a38JP Abgrall},
13753f17a9db278d33517d9888dd77848f554522a38JP Abgrall{
13853f17a9db278d33517d9888dd77848f554522a38JP Abgrall 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
13953f17a9db278d33517d9888dd77848f554522a38JP Abgrall 40,  40,  41,  41,  42,  42,  43,  43,  44,  44,  45,  45,  46,  46,  47,  47,
14053f17a9db278d33517d9888dd77848f554522a38JP Abgrall 48,  48,  49,  49,  50,  50,  51,  51,  52,  52,  53,  53,  54,  54,  55,  55,
14153f17a9db278d33517d9888dd77848f554522a38JP Abgrall 56,  56,  57,  57,  58,  58,  59,  59,  60,  60,  61,  61,  62,  62,  63,  63,
14253f17a9db278d33517d9888dd77848f554522a38JP Abgrall 64,  64,  65,  65,  66,  66,  67,  67,  68,  68,  69,  69,  70,  70,  71,  71,
14353f17a9db278d33517d9888dd77848f554522a38JP Abgrall 72,  72,  73,  73,  74,  74,  75,  75,  76,  76,  77,  77,  78,  78,  79,  79,
14453f17a9db278d33517d9888dd77848f554522a38JP Abgrall 80,  80,  81,  81,  82,  82,  83,  83,  84,  84,  85,  85,  86,  86,  87,  87,
14553f17a9db278d33517d9888dd77848f554522a38JP Abgrall 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
14653f17a9db278d33517d9888dd77848f554522a38JP Abgrall 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
14753f17a9db278d33517d9888dd77848f554522a38JP Abgrall112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
14853f17a9db278d33517d9888dd77848f554522a38JP Abgrall128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
14953f17a9db278d33517d9888dd77848f554522a38JP Abgrall144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
15053f17a9db278d33517d9888dd77848f554522a38JP Abgrall160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
15153f17a9db278d33517d9888dd77848f554522a38JP Abgrall176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
15253f17a9db278d33517d9888dd77848f554522a38JP Abgrall192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
15353f17a9db278d33517d9888dd77848f554522a38JP Abgrall208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
15453f17a9db278d33517d9888dd77848f554522a38JP Abgrall}
15553f17a9db278d33517d9888dd77848f554522a38JP Abgrall};
15653f17a9db278d33517d9888dd77848f554522a38JP Abgrall
15753f17a9db278d33517d9888dd77848f554522a38JP Abgrall
15853f17a9db278d33517d9888dd77848f554522a38JP Abgrall
15953f17a9db278d33517d9888dd77848f554522a38JP Abgrall/**********************************************************************/
16053f17a9db278d33517d9888dd77848f554522a38JP Abgrall/*****                     X Utility Functions                    *****/
16153f17a9db278d33517d9888dd77848f554522a38JP Abgrall/**********************************************************************/
162
163
164/*
165 * Return the host's byte order as LSBFirst or MSBFirst ala X.
166 */
167#ifndef XFree86Server
168static int host_byte_order( void )
169{
170   int i = 1;
171   char *cptr = (char *) &i;
172   return (*cptr==1) ? LSBFirst : MSBFirst;
173}
174#endif
175
176
177/*
178 * Error handling.
179 */
180#ifndef XFree86Server
181static volatile int mesaXErrorFlag = 0;
182
183static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event )
184{
185   (void) dpy;
186   (void) event;
187   mesaXErrorFlag = 1;
188   return 0;
189}
190#endif
191
192
193/*
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
198 */
199static int check_for_xshm( XMesaDisplay *display )
200{
201#if defined(XFree86Server)
202   return 0;
203#elif defined(USE_XSHM)
204   int major, minor, ignore;
205   Bool pixmaps;
206
207   if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
208      if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
209	 return (pixmaps==True) ? 2 : 1;
210      }
211      else {
212	 return 0;
213      }
214   }
215   else {
216      return 0;
217   }
218#else
219   /* No  XSHM support */
220   return 0;
221#endif
222}
223
224
225/*
226 * Apply gamma correction to an intensity value in [0..max].  Return the
227 * new intensity value.
228 */
229static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max )
230{
231   if (gamma == 1.0) {
232      return value;
233   }
234   else {
235      double x = (double) value / (double) max;
236      return IROUND_POS((GLfloat) max * _mesa_pow(x, 1.0F/gamma));
237   }
238}
239
240
241
242/*
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
249 */
250#ifdef XFree86Server
251
252static int bits_per_pixel( XMesaVisual xmv )
253{
254   const int depth = xmv->nplanes;
255   int i;
256   for (i = 0; i < screenInfo.numPixmapFormats; i++) {
257      if (screenInfo.formats[i].depth == depth)
258         return screenInfo.formats[i].bitsPerPixel;
259   }
260   return depth;  /* should never get here, but this should be safe */
261}
262
263#else
264
265static int bits_per_pixel( XMesaVisual xmv )
266{
267   XMesaDisplay *dpy = xmv->display;
268   XMesaVisualInfo visinfo = xmv->visinfo;
269   XMesaImage *img;
270   int bitsPerPixel;
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*/
276		       32,                   /*bitmap_pad*/
277		       0                     /*bytes_per_line*/
278                     );
279   assert(img);
280   /* grab the bits/pixel value */
281   bitsPerPixel = img->bits_per_pixel;
282   /* free the XImage */
283   _mesa_free( img->data );
284   img->data = NULL;
285   XMesaDestroyImage( img );
286   return bitsPerPixel;
287}
288#endif
289
290
291
292/*
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
300 */
301#ifndef XFree86Server
302static GLboolean WindowExistsFlag;
303
304static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
305{
306   (void) dpy;
307   if (xerr->error_code == BadWindow) {
308      WindowExistsFlag = GL_FALSE;
309   }
310   return 0;
311}
312
313static GLboolean window_exists( XMesaDisplay *dpy, Window win )
314{
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;
322}
323#endif
324
325
326
327/**********************************************************************/
328/*****                Linked list of XMesaBuffers                 *****/
329/**********************************************************************/
330
331static XMesaBuffer XMesaBufferList = NULL;
332
333
334/**
335 * Allocate a new XMesaBuffer, initialize basic fields and add to
336 * the list of all buffers.
337 */
338static XMesaBuffer
339alloc_xmesa_buffer(XMesaVisual vis, BufferType type, XMesaColormap cmap)
340{
341   XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
342   if (b) {
343      GLboolean swAlpha;
344
345      b->display = vis->display;
346      b->xm_visual = vis;
347      b->type = type;
348      b->cmap = cmap;
349
350      _mesa_initialize_framebuffer(&b->mesa_buffer, &vis->mesa_visual);
351
352      /* Allocate the framebuffer's renderbuffers */
353      assert(!b->mesa_buffer.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
354      assert(!b->mesa_buffer.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
355
356      /* front renderbuffer */
357      b->frontxrb = xmesa_new_renderbuffer(NULL, 0, vis->mesa_visual.rgbMode,
358                                           GL_FALSE);
359      _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_FRONT_LEFT,
360                             &b->frontxrb->Base);
361
362      /* back renderbuffer */
363      if (vis->mesa_visual.doubleBufferMode) {
364         b->backxrb = xmesa_new_renderbuffer(NULL, 0,
365                                             vis->mesa_visual.rgbMode,
366                                             GL_TRUE);
367         /* determine back buffer implementation */
368         b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP;
369
370         _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_BACK_LEFT,
371                                &b->backxrb->Base);
372      }
373
374      /* determine if we need software alpha planes */
375      if (vis->mesa_visual.alphaBits > 0
376          && vis->undithered_pf != PF_8A8B8G8R
377          && vis->undithered_pf != PF_8A8R8G8B) {
378         /* Visual has alpha, but pixel format doesn't support it.
379          * We'll use an alpha renderbuffer wrapper.
380          */
381         swAlpha = GL_TRUE;
382      }
383      else {
384         swAlpha = GL_FALSE;
385      }
386
387      _mesa_add_soft_renderbuffers(&b->mesa_buffer,
388                                   GL_FALSE,  /* color */
389                                   vis->mesa_visual.haveDepthBuffer,
390                                   vis->mesa_visual.haveStencilBuffer,
391                                   vis->mesa_visual.haveAccumBuffer,
392                                   swAlpha,
393                                   vis->mesa_visual.numAuxBuffers > 0 );
394
395      /* insert into linked list */
396      b->Next = XMesaBufferList;
397      XMesaBufferList = b;
398   }
399   return b;
400}
401
402
403/*
404 * Find an XMesaBuffer by matching X display and colormap but NOT matching
405 * the notThis buffer.
406 */
407static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy,
408                                     XMesaColormap cmap,
409                                     XMesaBuffer notThis)
410{
411   XMesaBuffer b;
412   for (b=XMesaBufferList; b; b=b->Next) {
413      if (b->display==dpy && b->cmap==cmap && b!=notThis) {
414         return b;
415      }
416   }
417   return NULL;
418}
419
420
421/*
422 * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
423 * entries.
424 */
425static void free_xmesa_buffer(int client, XMesaBuffer buffer)
426{
427   XMesaBuffer prev = NULL, b;
428   (void) client;
429   for (b=XMesaBufferList; b; b=b->Next) {
430      if (b==buffer) {
431         /* unlink bufer from list */
432         if (prev)
433            prev->Next = buffer->Next;
434         else
435            XMesaBufferList = buffer->Next;
436         /* Check to free X colors */
437         if (buffer->num_alloced>0) {
438            /* If no other buffer uses this X colormap then free the colors. */
439            if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) {
440#ifdef XFree86Server
441               (void)FreeColors(buffer->cmap, client,
442				buffer->num_alloced, buffer->alloced_colors,
443				0);
444#else
445               XFreeColors(buffer->display, buffer->cmap,
446                           buffer->alloced_colors, buffer->num_alloced, 0);
447#endif
448            }
449         }
450
451         _mesa_free_framebuffer_data(&buffer->mesa_buffer);
452         _mesa_free(buffer);
453
454         return;
455      }
456      /* continue search */
457      prev = b;
458   }
459   /* buffer not found in XMesaBufferList */
460   _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n");
461}
462
463
464/* Copy X color table stuff from one XMesaBuffer to another. */
465static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src)
466{
467   MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table));
468   MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r));
469   MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g));
470   MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b));
471   dst->num_alloced = src->num_alloced;
472   MEMCPY(dst->alloced_colors, src->alloced_colors,
473          sizeof(src->alloced_colors));
474}
475
476
477
478/**********************************************************************/
479/*****                   Misc Private Functions                   *****/
480/**********************************************************************/
481
482
483/**
484 * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
485 * Return:  GL_TRUE if success, GL_FALSE if error
486 */
487#ifndef XFree86Server
488static GLboolean
489alloc_shm_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
490{
491#ifdef USE_XSHM
492   /*
493    * We have to do a _lot_ of error checking here to be sure we can
494    * really use the XSHM extension.  It seems different servers trigger
495    * errors at different points if the extension won't work.  Therefore
496    * we have to be very careful...
497    */
498   GC gc;
499   int (*old_handler)( XMesaDisplay *, XErrorEvent * );
500
501   if (width == 0 || height == 0) {
502      /* this will be true the first time we're called on 'b' */
503      return GL_FALSE;
504   }
505
506   b->backxrb->ximage = XShmCreateImage(b->xm_visual->display,
507                                        b->xm_visual->visinfo->visual,
508                                        b->xm_visual->visinfo->depth,
509                                        ZPixmap, NULL, &b->shminfo,
510                                        width, height);
511   if (b->backxrb->ximage == NULL) {
512      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
513      b->shm = 0;
514      return GL_FALSE;
515   }
516
517   b->shminfo.shmid = shmget( IPC_PRIVATE, b->backxrb->ximage->bytes_per_line
518			     * b->backxrb->ximage->height, IPC_CREAT|0777 );
519   if (b->shminfo.shmid < 0) {
520      _mesa_warning(NULL, "shmget failed while allocating back buffer");
521      XDestroyImage( b->backxrb->ximage );
522      b->backxrb->ximage = NULL;
523      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.");
524      b->shm = 0;
525      return GL_FALSE;
526   }
527
528   b->shminfo.shmaddr = b->backxrb->ximage->data
529                      = (char*)shmat( b->shminfo.shmid, 0, 0 );
530   if (b->shminfo.shmaddr == (char *) -1) {
531      _mesa_warning(NULL, "shmat() failed while allocating back buffer");
532      XDestroyImage( b->backxrb->ximage );
533      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
534      b->backxrb->ximage = NULL;
535      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.");
536      b->shm = 0;
537      return GL_FALSE;
538   }
539
540   b->shminfo.readOnly = False;
541   mesaXErrorFlag = 0;
542   old_handler = XSetErrorHandler( mesaHandleXError );
543   /* This may trigger the X protocol error we're ready to catch: */
544   XShmAttach( b->xm_visual->display, &b->shminfo );
545   XSync( b->xm_visual->display, False );
546
547   if (mesaXErrorFlag) {
548      /* we are on a remote display, this error is normal, don't print it */
549      XFlush( b->xm_visual->display );
550      mesaXErrorFlag = 0;
551      XDestroyImage( b->backxrb->ximage );
552      shmdt( b->shminfo.shmaddr );
553      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
554      b->backxrb->ximage = NULL;
555      b->shm = 0;
556      (void) XSetErrorHandler( old_handler );
557      return GL_FALSE;
558   }
559
560   shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */
561
562   /* Finally, try an XShmPutImage to be really sure the extension works */
563   gc = XCreateGC( b->xm_visual->display, b->frontxrb->pixmap, 0, NULL );
564   XShmPutImage( b->xm_visual->display, b->frontxrb->pixmap, gc,
565		 b->backxrb->ximage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False );
566   XSync( b->xm_visual->display, False );
567   XFreeGC( b->xm_visual->display, gc );
568   (void) XSetErrorHandler( old_handler );
569   if (mesaXErrorFlag) {
570      XFlush( b->xm_visual->display );
571      mesaXErrorFlag = 0;
572      XDestroyImage( b->backxrb->ximage );
573      shmdt( b->shminfo.shmaddr );
574      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
575      b->backxrb->ximage = NULL;
576      b->shm = 0;
577      return GL_FALSE;
578   }
579
580   return GL_TRUE;
581#else
582   /* Can't compile XSHM support */
583   return GL_FALSE;
584#endif
585}
586#endif
587
588
589
590/*
591 * Setup an off-screen pixmap or Ximage to use as the back buffer.
592 * Input:  b - the X/Mesa buffer
593 */
594void
595xmesa_alloc_back_buffer( XMesaBuffer b, GLuint width, GLuint height )
596{
597   if (width == 0 || height == 0)
598      return;
599
600   if (b->db_mode == BACK_XIMAGE) {
601      /* Deallocate the old backxrb->ximage, if any */
602      if (b->backxrb->ximage) {
603#if defined(USE_XSHM) && !defined(XFree86Server)
604	 if (b->shm) {
605	    XShmDetach( b->xm_visual->display, &b->shminfo );
606	    XDestroyImage( b->backxrb->ximage );
607	    shmdt( b->shminfo.shmaddr );
608	 }
609	 else
610#endif
611	   XMesaDestroyImage( b->backxrb->ximage );
612	 b->backxrb->ximage = NULL;
613      }
614
615      /* Allocate new back buffer */
616#ifdef XFree86Server
617      /* Allocate a regular XImage for the back buffer. */
618      b->backxrb->ximage = XMesaCreateImage(b->xm_visual->BitsPerPixel,
619                                            width, height, NULL);
620      {
621#else
622      if (b->shm == 0 || !alloc_shm_back_buffer(b, width, height)) {
623	 /* Allocate a regular XImage for the back buffer. */
624	 b->backxrb->ximage = XCreateImage( b->xm_visual->display,
625                                      b->xm_visual->visinfo->visual,
626                                      GET_VISUAL_DEPTH(b->xm_visual),
627				      ZPixmap, 0,   /* format, offset */
628				      NULL,
629                                      width, height,
630				      8, 0 );  /* pad, bytes_per_line */
631#endif
632	 if (!b->backxrb->ximage) {
633	    _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.");
634            return;
635	 }
636         b->backxrb->ximage->data = (char *) MALLOC( b->backxrb->ximage->height
637                                        * b->backxrb->ximage->bytes_per_line );
638         if (!b->backxrb->ximage->data) {
639            _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.");
640            XMesaDestroyImage( b->backxrb->ximage );
641            b->backxrb->ximage = NULL;
642         }
643      }
644      b->backxrb->pixmap = None;
645   }
646   else if (b->db_mode == BACK_PIXMAP) {
647      if (!width)
648         width = 1;
649      if (!height)
650         height = 1;
651
652      /* Free the old back pixmap */
653      if (b->backxrb->pixmap) {
654	 XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
655      }
656      /* Allocate new back pixmap */
657      b->backxrb->pixmap = XMesaCreatePixmap( b->xm_visual->display,
658                                              b->frontxrb->pixmap,
659                                              width, height,
660                                              GET_VISUAL_DEPTH(b->xm_visual) );
661      b->backxrb->ximage = NULL;
662   }
663}
664
665
666
667/*
668 * A replacement for XAllocColor.  This function should never
669 * fail to allocate a color.  When XAllocColor fails, we return
670 * the nearest matching color.  If we have to allocate many colors
671 * this function isn't too efficient; the XQueryColors() could be
672 * done just once.
673 * Written by Michael Pichler, Brian Paul, Mark Kilgard
674 * Input:  dpy - X display
675 *         cmap - X colormap
676 *         cmapSize - size of colormap
677 * In/Out: color - the XColor struct
678 * Output:  exact - 1=exact color match, 0=closest match
679 *          alloced - 1=XAlloc worked, 0=XAlloc failed
680 */
681static void
682noFaultXAllocColor( int client,
683                    XMesaDisplay *dpy,
684                    XMesaColormap cmap,
685                    int cmapSize,
686                    XMesaColor *color,
687                    int *exact, int *alloced )
688{
689#ifdef XFree86Server
690   Pixel *ppixIn;
691   xrgb *ctable;
692#else
693   /* we'll try to cache ctable for better remote display performance */
694   static Display *prevDisplay = NULL;
695   static XMesaColormap prevCmap = 0;
696   static int prevCmapSize = 0;
697   static XMesaColor *ctable = NULL;
698#endif
699   XMesaColor subColor;
700   int i, bestmatch;
701   double mindist;       /* 3*2^16^2 exceeds long int precision. */
702
703   (void) client;
704
705   /* First try just using XAllocColor. */
706#ifdef XFree86Server
707   if (AllocColor(cmap,
708		  &color->red, &color->green, &color->blue,
709		  &color->pixel,
710		  client) == Success) {
711#else
712   if (XAllocColor(dpy, cmap, color)) {
713#endif
714      *exact = 1;
715      *alloced = 1;
716      return;
717   }
718
719   /* Alloc failed, search for closest match */
720
721   /* Retrieve color table entries. */
722   /* XXX alloca candidate. */
723#ifdef XFree86Server
724   ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel));
725   ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb));
726   for (i = 0; i < cmapSize; i++) {
727      ppixIn[i] = i;
728   }
729   QueryColors(cmap, cmapSize, ppixIn, ctable);
730#else
731   if (prevDisplay != dpy || prevCmap != cmap
732       || prevCmapSize != cmapSize || !ctable) {
733      /* free previously cached color table */
734      if (ctable)
735         _mesa_free(ctable);
736      /* Get the color table from X */
737      ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor));
738      assert(ctable);
739      for (i = 0; i < cmapSize; i++) {
740         ctable[i].pixel = i;
741      }
742      XQueryColors(dpy, cmap, ctable, cmapSize);
743      prevDisplay = dpy;
744      prevCmap = cmap;
745      prevCmapSize = cmapSize;
746   }
747#endif
748
749   /* Find best match. */
750   bestmatch = -1;
751   mindist = 0.0;
752   for (i = 0; i < cmapSize; i++) {
753      double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
754      double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
755      double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
756      double dist = dr * dr + dg * dg + db * db;
757      if (bestmatch < 0 || dist < mindist) {
758         bestmatch = i;
759         mindist = dist;
760      }
761   }
762
763   /* Return result. */
764   subColor.red   = ctable[bestmatch].red;
765   subColor.green = ctable[bestmatch].green;
766   subColor.blue  = ctable[bestmatch].blue;
767   /* Try to allocate the closest match color.  This should only
768    * fail if the cell is read/write.  Otherwise, we're incrementing
769    * the cell's reference count.
770    */
771#ifdef XFree86Server
772   if (AllocColor(cmap,
773		  &subColor.red, &subColor.green, &subColor.blue,
774		  &subColor.pixel,
775		  client) == Success) {
776#else
777   if (XAllocColor(dpy, cmap, &subColor)) {
778#endif
779      *alloced = 1;
780   }
781   else {
782      /* do this to work around a problem reported by Frank Ortega */
783      subColor.pixel = (unsigned long) bestmatch;
784      subColor.red   = ctable[bestmatch].red;
785      subColor.green = ctable[bestmatch].green;
786      subColor.blue  = ctable[bestmatch].blue;
787      subColor.flags = DoRed | DoGreen | DoBlue;
788      *alloced = 0;
789   }
790#ifdef XFree86Server
791   _mesa_free(ppixIn);
792   _mesa_free(ctable);
793#else
794   /* don't free table, save it for next time */
795#endif
796
797   *color = subColor;
798   *exact = 0;
799}
800
801
802
803
804/*
805 * Do setup for PF_GRAYSCALE pixel format.
806 * Note that buffer may be NULL.
807 */
808static GLboolean setup_grayscale( int client, XMesaVisual v,
809                                  XMesaBuffer buffer, XMesaColormap cmap )
810{
811   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
812      return GL_FALSE;
813   }
814
815   if (buffer) {
816      XMesaBuffer prevBuffer;
817
818      if (!cmap) {
819         return GL_FALSE;
820      }
821
822      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
823      if (prevBuffer &&
824          (buffer->xm_visual->mesa_visual.rgbMode ==
825           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
826         /* Copy colormap stuff from previous XMesaBuffer which uses same
827          * X colormap.  Do this to avoid time spent in noFaultXAllocColor.
828          */
829         copy_colortable_info(buffer, prevBuffer);
830      }
831      else {
832         /* Allocate 256 shades of gray */
833         int gray;
834         int colorsfailed = 0;
835         for (gray=0;gray<256;gray++) {
836            GLint r = gamma_adjust( v->RedGamma,   gray, 255 );
837            GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
838            GLint b = gamma_adjust( v->BlueGamma,  gray, 255 );
839            int exact, alloced;
840            XMesaColor xcol;
841            xcol.red   = (r << 8) | r;
842            xcol.green = (g << 8) | g;
843            xcol.blue  = (b << 8) | b;
844            noFaultXAllocColor( client, v->display,
845                                cmap, GET_COLORMAP_SIZE(v),
846                                &xcol, &exact, &alloced );
847            if (!exact) {
848               colorsfailed++;
849            }
850            if (alloced) {
851               assert(buffer->num_alloced<256);
852               buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
853               buffer->num_alloced++;
854            }
855
856            /*OLD
857            assert(gray < 576);
858            buffer->color_table[gray*3+0] = xcol.pixel;
859            buffer->color_table[gray*3+1] = xcol.pixel;
860            buffer->color_table[gray*3+2] = xcol.pixel;
861            assert(xcol.pixel < 65536);
862            buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
863            buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
864            buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
865            */
866            buffer->color_table[gray] = xcol.pixel;
867            assert(xcol.pixel < 65536);
868            buffer->pixel_to_r[xcol.pixel] = gray;
869            buffer->pixel_to_g[xcol.pixel] = gray;
870            buffer->pixel_to_b[xcol.pixel] = gray;
871         }
872
873         if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
874            _mesa_warning(NULL,
875                  "Note: %d out of 256 needed colors do not match exactly.\n",
876                  colorsfailed );
877         }
878      }
879   }
880
881   v->dithered_pf = PF_Grayscale;
882   v->undithered_pf = PF_Grayscale;
883   return GL_TRUE;
884}
885
886
887
888/*
889 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
890 * or 8-bit TrueColor visual visual.  We try to allocate a palette of 225
891 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
892 * color.  While this function was originally designed just for 8-bit
893 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
894 * Dithering code contributed by Bob Mercier.
895 */
896static GLboolean setup_dithered_color( int client, XMesaVisual v,
897                                       XMesaBuffer buffer, XMesaColormap cmap )
898{
899   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
900      return GL_FALSE;
901   }
902
903   if (buffer) {
904      XMesaBuffer prevBuffer;
905
906      if (!cmap) {
907         return GL_FALSE;
908      }
909
910      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
911      if (prevBuffer &&
912          (buffer->xm_visual->mesa_visual.rgbMode ==
913           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
914         /* Copy colormap stuff from previous, matching XMesaBuffer.
915          * Do this to avoid time spent in noFaultXAllocColor.
916          */
917         copy_colortable_info(buffer, prevBuffer);
918      }
919      else {
920         /* Allocate X colors and initialize color_table[], red_table[], etc */
921         int r, g, b, i;
922         int colorsfailed = 0;
923         for (r = 0; r < DITH_R; r++) {
924            for (g = 0; g < DITH_G; g++) {
925               for (b = 0; b < DITH_B; b++) {
926                  XMesaColor xcol;
927                  int exact, alloced;
928                  xcol.red  =gamma_adjust(v->RedGamma,   r*65535/(DITH_R-1),65535);
929                  xcol.green=gamma_adjust(v->GreenGamma, g*65535/(DITH_G-1),65535);
930                  xcol.blue =gamma_adjust(v->BlueGamma,  b*65535/(DITH_B-1),65535);
931                  noFaultXAllocColor( client, v->display,
932                                      cmap, GET_COLORMAP_SIZE(v),
933                                      &xcol, &exact, &alloced );
934                  if (!exact) {
935                     colorsfailed++;
936                  }
937                  if (alloced) {
938                     assert(buffer->num_alloced<256);
939                     buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
940                     buffer->num_alloced++;
941                  }
942                  i = DITH_MIX( r, g, b );
943                  assert(i < 576);
944                  buffer->color_table[i] = xcol.pixel;
945                  assert(xcol.pixel < 65536);
946                  buffer->pixel_to_r[xcol.pixel] = r * 255 / (DITH_R-1);
947                  buffer->pixel_to_g[xcol.pixel] = g * 255 / (DITH_G-1);
948                  buffer->pixel_to_b[xcol.pixel] = b * 255 / (DITH_B-1);
949               }
950            }
951         }
952
953         if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
954            _mesa_warning(NULL,
955                  "Note: %d out of %d needed colors do not match exactly.\n",
956                  colorsfailed, DITH_R * DITH_G * DITH_B );
957         }
958      }
959   }
960
961   v->dithered_pf = PF_Dither;
962   v->undithered_pf = PF_Lookup;
963   return GL_TRUE;
964}
965
966
967/*
968 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
969 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
970 * Special dithering tables have to be initialized.
971 */
972static void setup_8bit_hpcr( XMesaVisual v )
973{
974   /* HP Color Recovery contributed by:  Alex De Bruyn (ad@lms.be)
975    * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
976    * on the root window AND the colormap obtainable by XGetRGBColormaps
977    * for that atom must be set on the window.  (see also tkInitWindow)
978    * If that colormap is not set, the output will look stripy.
979    */
980
981   /* Setup color tables with gamma correction */
982   int i;
983   double g;
984
985   g = 1.0 / v->RedGamma;
986   for (i=0; i<256; i++) {
987      GLint red = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[0][i]/255.0, g ));
988      v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 );
989   }
990
991   g = 1.0 / v->GreenGamma;
992   for (i=0; i<256; i++) {
993      GLint green = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[1][i]/255.0, g ));
994      v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 );
995   }
996
997   g = 1.0 / v->BlueGamma;
998   for (i=0; i<256; i++) {
999      GLint blue = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[2][i]/255.0, g ));
1000      v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 );
1001   }
1002   v->undithered_pf = PF_HPCR;  /* can't really disable dithering for now */
1003   v->dithered_pf = PF_HPCR;
1004
1005   /* which method should I use to clear */
1006   /* GL_FALSE: keep the ordinary method  */
1007   /* GL_TRUE : clear with dither pattern */
1008   v->hpcr_clear_flag = _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE;
1009
1010   if (v->hpcr_clear_flag) {
1011      v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display,
1012                                               DefaultRootWindow(v->display),
1013                                               16, 2, 8);
1014#ifndef XFree86Server
1015      v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap,
1016                                       0, 0, 16, 2, AllPlanes, ZPixmap);
1017#endif
1018   }
1019}
1020
1021
1022/*
1023 * Setup RGB rendering for a window with a True/DirectColor visual.
1024 */
1025static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer,
1026                             XMesaColormap cmap )
1027{
1028   unsigned long rmask, gmask, bmask;
1029   (void) buffer;
1030   (void) cmap;
1031
1032   /* Compute red multiplier (mask) and bit shift */
1033   v->rshift = 0;
1034   rmask = GET_REDMASK(v);
1035   while ((rmask & 1)==0) {
1036      v->rshift++;
1037      rmask = rmask >> 1;
1038   }
1039
1040   /* Compute green multiplier (mask) and bit shift */
1041   v->gshift = 0;
1042   gmask = GET_GREENMASK(v);
1043   while ((gmask & 1)==0) {
1044      v->gshift++;
1045      gmask = gmask >> 1;
1046   }
1047
1048   /* Compute blue multiplier (mask) and bit shift */
1049   v->bshift = 0;
1050   bmask = GET_BLUEMASK(v);
1051   while ((bmask & 1)==0) {
1052      v->bshift++;
1053      bmask = bmask >> 1;
1054   }
1055
1056   /*
1057    * Compute component-to-pixel lookup tables and dithering kernel
1058    */
1059   {
1060      static GLubyte kernel[16] = {
1061          0*16,  8*16,  2*16, 10*16,
1062         12*16,  4*16, 14*16,  6*16,
1063          3*16, 11*16,  1*16,  9*16,
1064         15*16,  7*16, 13*16,  5*16,
1065      };
1066      GLint rBits = _mesa_bitcount(rmask);
1067      GLint gBits = _mesa_bitcount(gmask);
1068      GLint bBits = _mesa_bitcount(bmask);
1069      GLint maxBits;
1070      GLuint i;
1071
1072      /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1073      for (i=0; i<=rmask; i++)
1074         v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
1075      for (i=0; i<=gmask; i++)
1076         v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
1077      for (i=0; i<=bmask; i++)
1078         v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
1079
1080      /* convert RGB values from [0,255] to pixel components */
1081
1082      for (i=0;i<256;i++) {
1083         GLint r = gamma_adjust(v->RedGamma,   i, 255);
1084         GLint g = gamma_adjust(v->GreenGamma, i, 255);
1085         GLint b = gamma_adjust(v->BlueGamma,  i, 255);
1086         v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
1087         v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
1088         v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
1089      }
1090      /* overflow protection */
1091      for (i=256;i<512;i++) {
1092         v->RtoPixel[i] = v->RtoPixel[255];
1093         v->GtoPixel[i] = v->GtoPixel[255];
1094         v->BtoPixel[i] = v->BtoPixel[255];
1095      }
1096
1097      /* setup dithering kernel */
1098      maxBits = rBits;
1099      if (gBits > maxBits)  maxBits = gBits;
1100      if (bBits > maxBits)  maxBits = bBits;
1101      for (i=0;i<16;i++) {
1102         v->Kernel[i] = kernel[i] >> maxBits;
1103      }
1104
1105      v->undithered_pf = PF_Truecolor;
1106      v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor;
1107   }
1108
1109   /*
1110    * Now check for TrueColor visuals which we can optimize.
1111    */
1112   if (   GET_REDMASK(v)  ==0x0000ff
1113       && GET_GREENMASK(v)==0x00ff00
1114       && GET_BLUEMASK(v) ==0xff0000
1115       && CHECK_BYTE_ORDER(v)
1116       && v->BitsPerPixel==32
1117       && sizeof(GLuint)==4
1118       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1119      /* common 32 bpp config used on SGI, Sun */
1120      v->undithered_pf = v->dithered_pf = PF_8A8B8G8R;
1121   }
1122   else if (GET_REDMASK(v)  ==0xff0000
1123       &&   GET_GREENMASK(v)==0x00ff00
1124       &&   GET_BLUEMASK(v) ==0x0000ff
1125       && CHECK_BYTE_ORDER(v)
1126       && v->BitsPerPixel==32
1127       && sizeof(GLuint)==4
1128       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1129      /* common 32 bpp config used on Linux, HP, IBM */
1130      if (GET_VISUAL_DEPTH(v)==32)
1131	  v->undithered_pf = v->dithered_pf = PF_8A8R8G8B;
1132      else
1133	  v->undithered_pf = v->dithered_pf = PF_8R8G8B;
1134   }
1135   else if (GET_REDMASK(v)  ==0xff0000
1136       &&   GET_GREENMASK(v)==0x00ff00
1137       &&   GET_BLUEMASK(v) ==0x0000ff
1138       && CHECK_BYTE_ORDER(v)
1139       && v->BitsPerPixel==24
1140       && sizeof(GLuint)==4
1141       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1142      /* common packed 24 bpp config used on Linux */
1143      v->undithered_pf = v->dithered_pf = PF_8R8G8B24;
1144   }
1145   else if (GET_REDMASK(v)  ==0xf800
1146       &&   GET_GREENMASK(v)==0x07e0
1147       &&   GET_BLUEMASK(v) ==0x001f
1148       && CHECK_BYTE_ORDER(v)
1149       && v->BitsPerPixel==16
1150       && sizeof(GLushort)==2
1151       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1152      /* 5-6-5 color weight on common PC VGA boards */
1153      v->undithered_pf = PF_5R6G5B;
1154      v->dithered_pf = PF_Dither_5R6G5B;
1155   }
1156   else if (GET_REDMASK(v)  ==0xe0
1157       &&   GET_GREENMASK(v)==0x1c
1158       &&   GET_BLUEMASK(v) ==0x03
1159       && CHECK_FOR_HPCR(v)) {
1160      setup_8bit_hpcr( v );
1161   }
1162}
1163
1164
1165
1166/*
1167 * Setup RGB rendering for a window with a monochrome visual.
1168 */
1169static void setup_monochrome( XMesaVisual v, XMesaBuffer b )
1170{
1171   (void) b;
1172   v->dithered_pf = v->undithered_pf = PF_1Bit;
1173   /* if black=1 then we must flip pixel values */
1174   v->bitFlip = (GET_BLACK_PIXEL(v) != 0);
1175}
1176
1177
1178
1179/*
1180 * When a context is "made current" for the first time, we can finally
1181 * finish initializing the context's visual and buffer information.
1182 * Input:  v - the XMesaVisual to initialize
1183 *         b - the XMesaBuffer to initialize (may be NULL)
1184 *         rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1185 *         window - the window/pixmap we're rendering into
1186 *         cmap - the colormap associated with the window/pixmap
1187 * Return:  GL_TRUE=success, GL_FALSE=failure
1188 */
1189static GLboolean initialize_visual_and_buffer( int client,
1190                                               XMesaVisual v,
1191                                               XMesaBuffer b,
1192                                               GLboolean rgb_flag,
1193                                               XMesaDrawable window,
1194                                               XMesaColormap cmap )
1195{
1196   struct xmesa_renderbuffer *front_xrb, *back_xrb;
1197#ifndef XFree86Server
1198   XGCValues gcvalues;
1199#endif
1200
1201   if (b) {
1202      assert(b->xm_visual == v);
1203   }
1204
1205   if (b) {
1206      front_xrb = b->frontxrb;
1207      back_xrb = b->backxrb;
1208   }
1209   else {
1210      front_xrb = back_xrb = NULL;
1211   }
1212
1213   /* Save true bits/pixel */
1214   v->BitsPerPixel = bits_per_pixel(v);
1215   assert(v->BitsPerPixel > 0);
1216
1217
1218   if (rgb_flag==GL_FALSE) {
1219      /* COLOR-INDEXED WINDOW:
1220       * Even if the visual is TrueColor or DirectColor we treat it as
1221       * being color indexed.  This is weird but might be useful to someone.
1222       */
1223      v->dithered_pf = v->undithered_pf = PF_Index;
1224      v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v);
1225   }
1226   else {
1227      /* RGB WINDOW:
1228       * We support RGB rendering into almost any kind of visual.
1229       */
1230      const int xclass = v->mesa_visual.visualType;
1231      if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
1232	 setup_truecolor( v, b, cmap );
1233      }
1234      else if (xclass==GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v)==1) {
1235	 setup_monochrome( v, b );
1236      }
1237      else if (xclass==GLX_GRAY_SCALE || xclass==GLX_STATIC_GRAY) {
1238         if (!setup_grayscale( client, v, b, cmap )) {
1239            return GL_FALSE;
1240         }
1241      }
1242      else if ((xclass==GLX_PSEUDO_COLOR || xclass==GLX_STATIC_COLOR)
1243               && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
1244	 if (!setup_dithered_color( client, v, b, cmap )) {
1245            return GL_FALSE;
1246         }
1247      }
1248      else {
1249	 _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.");
1250	 return GL_FALSE;
1251      }
1252      v->mesa_visual.indexBits = 0;
1253
1254      if (_mesa_getenv("MESA_NO_DITHER")) {
1255	 v->dithered_pf = v->undithered_pf;
1256      }
1257   }
1258
1259
1260   /*
1261    * If MESA_INFO env var is set print out some debugging info
1262    * which can help Brian figure out what's going on when a user
1263    * reports bugs.
1264    */
1265   if (_mesa_getenv("MESA_INFO")) {
1266      _mesa_printf("X/Mesa visual = %p\n", (void *) v);
1267      _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf);
1268      _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf);
1269      _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
1270      _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
1271      _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
1272   }
1273
1274   if (b && window) {
1275      /* Do window-specific initializations */
1276
1277      b->frontxrb->pixmap = window;
1278
1279      /* Setup for single/double buffering */
1280      if (v->mesa_visual.doubleBufferMode) {
1281         /* Double buffered */
1282         b->shm = check_for_xshm( v->display );
1283         xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height);
1284      }
1285
1286      /* X11 graphics contexts */
1287#ifdef XFree86Server
1288      b->gc = CreateScratchGC(v->display, window->depth);
1289#else
1290      b->gc = XCreateGC( v->display, window, 0, NULL );
1291#endif
1292      XMesaSetFunction( v->display, b->gc, GXcopy );
1293
1294      /* cleargc - for glClear() */
1295#ifdef XFree86Server
1296      b->cleargc = CreateScratchGC(v->display, window->depth);
1297#else
1298      b->cleargc = XCreateGC( v->display, window, 0, NULL );
1299#endif
1300      XMesaSetFunction( v->display, b->cleargc, GXcopy );
1301
1302      /*
1303       * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1304       * Patch contributed by Michael Pichler May 15, 1995.
1305       */
1306#ifdef XFree86Server
1307      b->swapgc = CreateScratchGC(v->display, window->depth);
1308      {
1309         CARD32 v[1];
1310         v[0] = FALSE;
1311         dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL);
1312      }
1313#else
1314      gcvalues.graphics_exposures = False;
1315      b->swapgc = XCreateGC( v->display, window,
1316                              GCGraphicsExposures, &gcvalues);
1317#endif
1318      XMesaSetFunction( v->display, b->swapgc, GXcopy );
1319      /*
1320       * Set fill style and tile pixmap once for all for HPCR stuff
1321       * (instead of doing it each time in clear_color_HPCR_pixmap())
1322       * Initialize whole stuff
1323       * Patch contributed by Jacques Leroy March 8, 1998.
1324       */
1325      if (v->hpcr_clear_flag && back_xrb->pixmap) {
1326	int i;
1327	for (i=0; i<16; i++)
1328        {
1329	   XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0);
1330	   XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0);
1331        }
1332        XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap,
1333		      b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
1334	XMesaSetFillStyle( v->display, b->cleargc, FillTiled);
1335	XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap );
1336      }
1337
1338      /* Initialize the row buffer XImage for use in write_color_span() */
1339#ifdef XFree86Server
1340      b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1,
1341				     (char *)MALLOC(MAX_WIDTH*4));
1342#else
1343      b->rowimage = XCreateImage( v->display,
1344                                  v->visinfo->visual,
1345                                  v->visinfo->depth,
1346                                  ZPixmap, 0,           /*format, offset*/
1347                                  (char*) MALLOC(MAX_WIDTH*4),  /*data*/
1348                                  MAX_WIDTH, 1,         /*width, height*/
1349                                  32,                   /*bitmap_pad*/
1350                                  0                     /*bytes_per_line*/ );
1351#endif
1352      if (!b->rowimage)
1353         return GL_FALSE;
1354   }
1355
1356   return GL_TRUE;
1357}
1358
1359
1360
1361/*
1362 * Convert an RGBA color to a pixel value.
1363 */
1364unsigned long
1365xmesa_color_to_pixel(GLcontext *ctx,
1366                     GLubyte r, GLubyte g, GLubyte b, GLubyte a,
1367                     GLuint pixelFormat)
1368{
1369   XMesaContext xmesa = XMESA_CONTEXT(ctx);
1370   switch (pixelFormat) {
1371      case PF_Index:
1372         return 0;
1373      case PF_Truecolor:
1374         {
1375            unsigned long p;
1376            PACK_TRUECOLOR( p, r, g, b );
1377            return p;
1378         }
1379      case PF_8A8B8G8R:
1380         return PACK_8A8B8G8R( r, g, b, a );
1381      case PF_8A8R8G8B:
1382         return PACK_8A8R8G8B( r, g, b, a );
1383      case PF_8R8G8B:
1384         /* fall through */
1385      case PF_8R8G8B24:
1386         return PACK_8R8G8B( r, g, b );
1387      case PF_5R6G5B:
1388         return PACK_5R6G5B( r, g, b );
1389      case PF_Dither:
1390         {
1391            DITHER_SETUP;
1392            return DITHER( 1, 0, r, g, b );
1393         }
1394      case PF_1Bit:
1395         /* 382 = (3*255)/2 */
1396         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
1397      case PF_HPCR:
1398         return DITHER_HPCR(1, 1, r, g, b);
1399      case PF_Lookup:
1400         {
1401            LOOKUP_SETUP;
1402            return LOOKUP( r, g, b );
1403         }
1404      case PF_Grayscale:
1405         return GRAY_RGB( r, g, b );
1406      case PF_Dither_True:
1407         /* fall through */
1408      case PF_Dither_5R6G5B:
1409         {
1410            unsigned long p;
1411            PACK_TRUEDITHER(p, 1, 0, r, g, b);
1412            return p;
1413         }
1414      default:
1415         _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel");
1416   }
1417   return 0;
1418}
1419
1420
1421#define NUM_VISUAL_TYPES   6
1422
1423/**
1424 * Convert an X visual type to a GLX visual type.
1425 *
1426 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
1427 *        to be converted.
1428 * \return If \c visualType is a valid X visual type, a GLX visual type will
1429 *         be returned.  Otherwise \c GLX_NONE will be returned.
1430 *
1431 * \note
1432 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
1433 * DRI CVS tree.
1434 */
1435static GLint
1436xmesa_convert_from_x_visual_type( int visualType )
1437{
1438    static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
1439	GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
1440	GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
1441	GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
1442    };
1443
1444    return ( (unsigned) visualType < NUM_VISUAL_TYPES )
1445	? glx_visual_types[ visualType ] : GLX_NONE;
1446}
1447
1448
1449/**********************************************************************/
1450/*****                       Public Functions                     *****/
1451/**********************************************************************/
1452
1453
1454/*
1455 * Create a new X/Mesa visual.
1456 * Input:  display - X11 display
1457 *         visinfo - an XVisualInfo pointer
1458 *         rgb_flag - GL_TRUE = RGB mode,
1459 *                    GL_FALSE = color index mode
1460 *         alpha_flag - alpha buffer requested?
1461 *         db_flag - GL_TRUE = double-buffered,
1462 *                   GL_FALSE = single buffered
1463 *         stereo_flag - stereo visual?
1464 *         ximage_flag - GL_TRUE = use an XImage for back buffer,
1465 *                       GL_FALSE = use an off-screen pixmap for back buffer
1466 *         depth_size - requested bits/depth values, or zero
1467 *         stencil_size - requested bits/stencil values, or zero
1468 *         accum_red_size - requested bits/red accum values, or zero
1469 *         accum_green_size - requested bits/green accum values, or zero
1470 *         accum_blue_size - requested bits/blue accum values, or zero
1471 *         accum_alpha_size - requested bits/alpha accum values, or zero
1472 *         num_samples - number of samples/pixel if multisampling, or zero
1473 *         level - visual level, usually 0
1474 *         visualCaveat - ala the GLX extension, usually GLX_NONE
1475 * Return;  a new XMesaVisual or 0 if error.
1476 */
1477XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
1478                               XMesaVisualInfo visinfo,
1479                               GLboolean rgb_flag,
1480                               GLboolean alpha_flag,
1481                               GLboolean db_flag,
1482                               GLboolean stereo_flag,
1483                               GLboolean ximage_flag,
1484                               GLint depth_size,
1485                               GLint stencil_size,
1486                               GLint accum_red_size,
1487                               GLint accum_green_size,
1488                               GLint accum_blue_size,
1489                               GLint accum_alpha_size,
1490                               GLint num_samples,
1491                               GLint level,
1492                               GLint visualCaveat )
1493{
1494   char *gamma;
1495   XMesaVisual v;
1496   GLint red_bits, green_bits, blue_bits, alpha_bits;
1497
1498   /* For debugging only */
1499   if (_mesa_getenv("MESA_XSYNC")) {
1500      /* This makes debugging X easier.
1501       * In your debugger, set a breakpoint on _XError to stop when an
1502       * X protocol error is generated.
1503       */
1504#ifdef XFree86Server
1505      /* NOT_NEEDED */
1506#else
1507      XSynchronize( display, 1 );
1508#endif
1509   }
1510
1511   v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
1512   if (!v) {
1513      return NULL;
1514   }
1515
1516   /*
1517    * In the X server, NULL is passed in for the display.  It will have
1518    * to be set before using this visual.  See XMesaSetVisualDisplay()
1519    * below.
1520    */
1521   v->display = display;
1522
1523   /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
1524    * the struct but we may need some of the information contained in it
1525    * at a later time.
1526    */
1527#ifndef XFree86Server
1528   v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
1529   if(!v->visinfo) {
1530      _mesa_free(v);
1531      return NULL;
1532   }
1533   MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
1534#endif
1535
1536   /* check for MESA_GAMMA environment variable */
1537   gamma = _mesa_getenv("MESA_GAMMA");
1538   if (gamma) {
1539      v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
1540      sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
1541      if (v->RedGamma<=0.0)    v->RedGamma = 1.0;
1542      if (v->GreenGamma<=0.0)  v->GreenGamma = v->RedGamma;
1543      if (v->BlueGamma<=0.0)   v->BlueGamma = v->RedGamma;
1544   }
1545   else {
1546      v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
1547   }
1548
1549   v->ximage_flag = ximage_flag;
1550
1551#ifdef XFree86Server
1552   /* We could calculate these values by ourselves.  nplanes is either the sum
1553    * of the red, green, and blue bits or the number index bits.
1554    * ColormapEntries is either (1U << index_bits) or
1555    * (1U << max(redBits, greenBits, blueBits)).
1556    */
1557   v->nplanes = visinfo->nplanes;
1558   v->ColormapEntries = visinfo->ColormapEntries;
1559
1560   v->mesa_visual.redMask = visinfo->redMask;
1561   v->mesa_visual.greenMask = visinfo->greenMask;
1562   v->mesa_visual.blueMask = visinfo->blueMask;
1563   v->mesa_visual.visualID = visinfo->vid;
1564   v->mesa_visual.screen = 0; /* FIXME: What should be done here? */
1565#else
1566   v->mesa_visual.redMask = visinfo->red_mask;
1567   v->mesa_visual.greenMask = visinfo->green_mask;
1568   v->mesa_visual.blueMask = visinfo->blue_mask;
1569   v->mesa_visual.visualID = visinfo->visualid;
1570   v->mesa_visual.screen = visinfo->screen;
1571#endif
1572
1573#if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
1574   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
1575#else
1576   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
1577#endif
1578
1579   v->mesa_visual.visualRating = visualCaveat;
1580
1581   (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 );
1582
1583   {
1584      const int xclass = v->mesa_visual.visualType;
1585      if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
1586         red_bits   = _mesa_bitcount(GET_REDMASK(v));
1587         green_bits = _mesa_bitcount(GET_GREENMASK(v));
1588         blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
1589         alpha_bits = 0;
1590      }
1591      else {
1592         /* this is an approximation */
1593         int depth;
1594         depth = GET_VISUAL_DEPTH(v);
1595         red_bits = depth / 3;
1596         depth -= red_bits;
1597         green_bits = depth / 2;
1598         depth -= green_bits;
1599         blue_bits = depth;
1600         alpha_bits = 0;
1601         assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
1602      }
1603   }
1604
1605   if (alpha_flag && alpha_bits == 0)
1606      alpha_bits = 8;
1607
1608   _mesa_initialize_visual( &v->mesa_visual,
1609                            rgb_flag, db_flag, stereo_flag,
1610                            red_bits, green_bits,
1611                            blue_bits, alpha_bits,
1612                            v->mesa_visual.indexBits,
1613                            depth_size,
1614                            stencil_size,
1615                            accum_red_size, accum_green_size,
1616                            accum_blue_size, accum_alpha_size,
1617                            0 );
1618
1619   /* XXX minor hack */
1620   v->mesa_visual.level = level;
1621   return v;
1622}
1623
1624
1625void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v )
1626{
1627    v->display = dpy;
1628}
1629
1630
1631void XMesaDestroyVisual( XMesaVisual v )
1632{
1633#ifndef XFree86Server
1634   _mesa_free(v->visinfo);
1635#endif
1636   _mesa_free(v);
1637}
1638
1639
1640
1641/**
1642 * Create a new XMesaContext.
1643 * \param v  the XMesaVisual
1644 * \param share_list  another XMesaContext with which to share display
1645 *                    lists or NULL if no sharing is wanted.
1646 * \return an XMesaContext or NULL if error.
1647 */
1648XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
1649{
1650   static GLboolean firstTime = GL_TRUE;
1651   XMesaContext c;
1652   GLcontext *mesaCtx;
1653   struct dd_function_table functions;
1654   TNLcontext *tnl;
1655
1656   if (firstTime) {
1657      _glthread_INIT_MUTEX(_xmesa_lock);
1658      firstTime = GL_FALSE;
1659   }
1660
1661   /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
1662   c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
1663   if (!c)
1664      return NULL;
1665
1666   mesaCtx = &(c->mesa);
1667
1668   /* initialize with default driver functions, then plug in XMesa funcs */
1669   _mesa_init_driver_functions(&functions);
1670   xmesa_init_driver_functions(v, &functions);
1671   if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual,
1672                      share_list ? &(share_list->mesa) : (GLcontext *) NULL,
1673                      &functions, (void *) c)) {
1674      _mesa_free(c);
1675      return NULL;
1676   }
1677
1678   _mesa_enable_sw_extensions(mesaCtx);
1679   _mesa_enable_1_3_extensions(mesaCtx);
1680   _mesa_enable_1_4_extensions(mesaCtx);
1681   _mesa_enable_1_5_extensions(mesaCtx);
1682   _mesa_enable_2_0_extensions(mesaCtx);
1683#if ENABLE_EXT_texure_compression_s3tc
1684    if (c->Mesa_DXTn) {
1685       _mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc");
1686       _mesa_enable_extension(mesaCtx, "GL_S3_s3tc");
1687    }
1688    _mesa_enable_extension(mesaCtx, "GL_3DFX_texture_compression_FXT1");
1689#endif
1690#if ENABLE_EXT_timer_query
1691    _mesa_enable_extension(mesaCtx, "GL_EXT_timer_query");
1692#endif
1693
1694   /* finish up xmesa context initializations */
1695   c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
1696   c->xm_visual = v;
1697   c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
1698   c->display = v->display;
1699   c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
1700
1701   /* Initialize the software rasterizer and helper modules.
1702    */
1703   if (!_swrast_CreateContext( mesaCtx ) ||
1704       !_ac_CreateContext( mesaCtx ) ||
1705       !_tnl_CreateContext( mesaCtx ) ||
1706       !_swsetup_CreateContext( mesaCtx )) {
1707      _mesa_free_context_data(&c->mesa);
1708      _mesa_free(c);
1709      return NULL;
1710   }
1711
1712   /* tnl setup */
1713   tnl = TNL_CONTEXT(mesaCtx);
1714   tnl->Driver.RunPipeline = _tnl_run_pipeline;
1715   /* swrast setup */
1716   xmesa_register_swrast_functions( mesaCtx );
1717   _swsetup_Wakeup(mesaCtx);
1718
1719   return c;
1720}
1721
1722
1723
1724void XMesaDestroyContext( XMesaContext c )
1725{
1726   GLcontext *mesaCtx = &c->mesa;
1727#ifdef FX
1728   XMesaBuffer xmbuf = XMESA_BUFFER(mesaCtx->DrawBuffer);
1729
1730   if (xmbuf && xmbuf->FXctx)
1731      fxMesaDestroyContext(xmbuf->FXctx);
1732#endif
1733   _swsetup_DestroyContext( mesaCtx );
1734   _swrast_DestroyContext( mesaCtx );
1735   _tnl_DestroyContext( mesaCtx );
1736   _ac_DestroyContext( mesaCtx );
1737   _mesa_free_context_data( mesaCtx );
1738   _mesa_free( c );
1739}
1740
1741
1742
1743/*
1744 * XXX this isn't a public function!  It's a hack for the 3Dfx driver.
1745 * Create a new XMesaBuffer from an X window.
1746 * Input:  v - the XMesaVisual
1747 *         w - the window
1748 *         c - the context
1749 * Return:  new XMesaBuffer or NULL if error
1750 */
1751XMesaBuffer
1752XMesaCreateWindowBuffer2(XMesaVisual v, XMesaWindow w, XMesaContext c)
1753{
1754#ifndef XFree86Server
1755   XWindowAttributes attr;
1756#endif
1757#ifdef FX
1758   char *fxEnvVar;
1759#endif
1760   int client = 0;
1761   XMesaBuffer b;
1762   XMesaColormap cmap;
1763
1764   assert(v);
1765   (void) c;
1766
1767   /* Check that window depth matches visual depth */
1768#ifdef XFree86Server
1769   client = CLIENT_ID(((XMesaDrawable)w)->id);
1770
1771   if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
1772      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1773                    GET_VISUAL_DEPTH(v), ((XMesaDrawable) w)->depth);
1774      return NULL;
1775   }
1776#else
1777   XGetWindowAttributes( v->display, w, &attr );
1778
1779   if (GET_VISUAL_DEPTH(v) != attr.depth) {
1780      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1781                    GET_VISUAL_DEPTH(v), attr.depth);
1782      return NULL;
1783   }
1784#endif
1785
1786   /* Find colormap */
1787#ifdef XFree86Server
1788   cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1789#else
1790   if (attr.colormap) {
1791      cmap = attr.colormap;
1792   }
1793   else {
1794      _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
1795      /* this is weird, a window w/out a colormap!? */
1796      /* OK, let's just allocate a new one and hope for the best */
1797      cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1798   }
1799#endif
1800
1801   b = alloc_xmesa_buffer(v, WINDOW, cmap);
1802   if (!b) {
1803      return NULL;
1804   }
1805
1806   if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
1807                                      (XMesaDrawable)w, cmap )) {
1808      free_xmesa_buffer(client, b);
1809      return NULL;
1810   }
1811
1812#ifdef FX
1813   fxEnvVar = _mesa_getenv("MESA_GLX_FX");
1814   if (fxEnvVar) {
1815     if (fxEnvVar[0]!='d') {
1816       int attribs[100];
1817       int numAttribs = 0;
1818       int hw;
1819       if (v->mesa_visual.depthBits > 0) {
1820	 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
1821	 attribs[numAttribs++] = v->mesa_visual.depthBits;
1822       }
1823       if (v->mesa_visual.doubleBufferMode) {
1824	 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
1825       }
1826       if (v->mesa_visual.accumRedBits > 0) {
1827	 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
1828	 attribs[numAttribs++] = v->mesa_visual.accumRedBits;
1829       }
1830       if (v->mesa_visual.stencilBits > 0) {
1831         attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
1832         attribs[numAttribs++] = v->mesa_visual.stencilBits;
1833       }
1834       if (v->mesa_visual.alphaBits > 0) {
1835         attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
1836         attribs[numAttribs++] = v->mesa_visual.alphaBits;
1837       }
1838       if (1) {
1839         attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
1840         attribs[numAttribs++] = (int) &(c->mesa);
1841       }
1842       attribs[numAttribs++] = FXMESA_NONE;
1843
1844       /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
1845       hw = fxMesaSelectCurrentBoard(0);
1846
1847       /* if these fail, there's a new bug somewhere */
1848       ASSERT(b->mesa_buffer.Width > 0);
1849       ASSERT(b->mesa_buffer.Height > 0);
1850
1851       if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) {
1852         b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
1853                                            b->mesa_buffer.Height, attribs);
1854         if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) {
1855	   b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
1856	   if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) {
1857	     b->FXwindowHack = GL_TRUE;
1858	     FX_grSstControl(GR_CONTROL_DEACTIVATE);
1859	   }
1860           else {
1861	     b->FXwindowHack = GL_FALSE;
1862	   }
1863         }
1864       }
1865       else {
1866         if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1867	   b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
1868					  GR_REFRESH_75Hz, attribs);
1869         else
1870	   b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
1871                                              b->mesa_buffer.Height, attribs);
1872         b->FXisHackUsable = GL_FALSE;
1873         b->FXwindowHack = GL_FALSE;
1874       }
1875       /*
1876       fprintf(stderr,
1877               "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1878               hw, b->mesa_buffer.Width, b->mesa_buffer.Height,
1879	       b->FXisHackUsable, b->FXwindowHack);
1880       */
1881     }
1882   }
1883   else {
1884      _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n");
1885      _mesa_warning(NULL, "         you have not defined the MESA_GLX_FX env. var.\n");
1886      _mesa_warning(NULL, "         (check the README.3DFX file for more information).\n\n");
1887      _mesa_warning(NULL, "         you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1888   }
1889#endif
1890
1891   return b;
1892}
1893
1894
1895XMesaBuffer
1896XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
1897{
1898   return XMesaCreateWindowBuffer2( v, w, NULL );
1899}
1900
1901
1902/**
1903 * Create a new XMesaBuffer from an X pixmap.
1904 *
1905 * \param v    the XMesaVisual
1906 * \param p    the pixmap
1907 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1908 *             \c GLX_DIRECT_COLOR visual for the pixmap
1909 * \returns new XMesaBuffer or NULL if error
1910 */
1911XMesaBuffer
1912XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
1913{
1914   int client = 0;
1915   XMesaBuffer b;
1916
1917   assert(v);
1918
1919   b = alloc_xmesa_buffer(v, PIXMAP, cmap);
1920   if (!b) {
1921      return NULL;
1922   }
1923
1924#ifdef XFree86Server
1925   client = CLIENT_ID(((XMesaDrawable)p)->id);
1926#endif
1927
1928   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1929				     (XMesaDrawable)p, cmap)) {
1930      free_xmesa_buffer(client, b);
1931      return NULL;
1932   }
1933
1934   return b;
1935}
1936
1937
1938
1939XMesaBuffer
1940XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
1941                   unsigned int width, unsigned int height)
1942{
1943#ifdef XFree86Server
1944   return 0;
1945#else
1946   int client = 0;
1947   XMesaWindow root;
1948   XMesaDrawable drawable;  /* X Pixmap Drawable */
1949   XMesaBuffer b;
1950
1951   b = alloc_xmesa_buffer(v, PBUFFER, cmap);
1952   if (!b) {
1953      return NULL;
1954   }
1955
1956   /* allocate pixmap for front buffer */
1957   root = RootWindow( v->display, v->visinfo->screen );
1958   drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth );
1959
1960   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1961				     drawable, cmap)) {
1962      free_xmesa_buffer(client, b);
1963      return NULL;
1964   }
1965
1966   return b;
1967#endif
1968}
1969
1970
1971
1972/*
1973 * Deallocate an XMesaBuffer structure and all related info.
1974 */
1975void XMesaDestroyBuffer( XMesaBuffer b )
1976{
1977   int client = 0;
1978
1979#ifdef XFree86Server
1980   if (b->frontxrb->pixmap)
1981       client = CLIENT_ID(b->frontxrb->pixmap->id);
1982#endif
1983
1984   if (b->gc)  XMesaFreeGC( b->xm_visual->display, b->gc );
1985   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
1986   if (b->swapgc)  XMesaFreeGC( b->xm_visual->display, b->swapgc );
1987
1988   if (b->xm_visual->mesa_visual.doubleBufferMode)
1989   {
1990       if (b->backxrb->ximage) {
1991#if defined(USE_XSHM) && !defined(XFree86Server)
1992	   if (b->shm) {
1993	       XShmDetach( b->xm_visual->display, &b->shminfo );
1994	       XDestroyImage( b->backxrb->ximage );
1995	       shmdt( b->shminfo.shmaddr );
1996	   }
1997	   else
1998#endif
1999	       XMesaDestroyImage( b->backxrb->ximage );
2000       }
2001       if (b->backxrb->pixmap) {
2002	   XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap );
2003	   if (b->xm_visual->hpcr_clear_flag) {
2004	       XMesaFreePixmap( b->xm_visual->display,
2005				b->xm_visual->hpcr_clear_pixmap );
2006	       XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
2007	   }
2008       }
2009   }
2010   if (b->rowimage) {
2011      _mesa_free( b->rowimage->data );
2012      b->rowimage->data = NULL;
2013      XMesaDestroyImage( b->rowimage );
2014   }
2015
2016   free_xmesa_buffer(client, b);
2017}
2018
2019
2020
2021/*
2022 * Bind buffer b to context c and make c the current rendering context.
2023 */
2024GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
2025{
2026   return XMesaMakeCurrent2( c, b, b );
2027}
2028
2029
2030/*
2031 * Bind buffer b to context c and make c the current rendering context.
2032 */
2033GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
2034                             XMesaBuffer readBuffer )
2035{
2036   if (c) {
2037      if (!drawBuffer || !readBuffer)
2038         return GL_FALSE;  /* must specify buffers! */
2039
2040#ifdef FX
2041      if (drawBuffer->FXctx) {
2042         fxMesaMakeCurrent(drawBuffer->FXctx);
2043
2044         c->xm_buffer = drawBuffer;
2045
2046         return GL_TRUE;
2047      }
2048#endif
2049      if (&(c->mesa) == _mesa_get_current_context()
2050          && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
2051          && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
2052          && ((XMesaBuffer) c->mesa.DrawBuffer)->wasCurrent) {
2053         /* same context and buffer, do nothing */
2054         return GL_TRUE;
2055      }
2056
2057      c->xm_buffer = drawBuffer;
2058
2059      _mesa_make_current(&(c->mesa),
2060                         &drawBuffer->mesa_buffer,
2061                         &readBuffer->mesa_buffer);
2062
2063      if (c->xm_visual->mesa_visual.rgbMode) {
2064         /*
2065          * Must recompute and set these pixel values because colormap
2066          * can be different for different windows.
2067          */
2068         c->clearpixel = xmesa_color_to_pixel( &c->mesa,
2069                                               c->clearcolor[0],
2070                                               c->clearcolor[1],
2071                                               c->clearcolor[2],
2072                                               c->clearcolor[3],
2073                                               c->xm_visual->undithered_pf);
2074         XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
2075      }
2076
2077      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2078      drawBuffer->wasCurrent = GL_TRUE;
2079   }
2080   else {
2081      /* Detach */
2082      _mesa_make_current( NULL, NULL, NULL );
2083   }
2084   return GL_TRUE;
2085}
2086
2087
2088/*
2089 * Unbind the context c from its buffer.
2090 */
2091GLboolean XMesaUnbindContext( XMesaContext c )
2092{
2093   /* A no-op for XFree86 integration purposes */
2094   return GL_TRUE;
2095}
2096
2097
2098XMesaContext XMesaGetCurrentContext( void )
2099{
2100   GET_CURRENT_CONTEXT(ctx);
2101   if (ctx) {
2102      XMesaContext xmesa = XMESA_CONTEXT(ctx);
2103      return xmesa;
2104   }
2105   else {
2106      return 0;
2107   }
2108}
2109
2110
2111XMesaBuffer XMesaGetCurrentBuffer( void )
2112{
2113   GET_CURRENT_CONTEXT(ctx);
2114   if (ctx) {
2115      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2116      return xmbuf;
2117   }
2118   else {
2119      return 0;
2120   }
2121}
2122
2123
2124/* New in Mesa 3.1 */
2125XMesaBuffer XMesaGetCurrentReadBuffer( void )
2126{
2127   GET_CURRENT_CONTEXT(ctx);
2128   if (ctx) {
2129      return (XMesaBuffer) (ctx->ReadBuffer);
2130   }
2131   else {
2132      return 0;
2133   }
2134}
2135
2136
2137GLboolean XMesaForceCurrent(XMesaContext c)
2138{
2139   if (c) {
2140      if (&(c->mesa) != _mesa_get_current_context()) {
2141	 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
2142      }
2143   }
2144   else {
2145      _mesa_make_current(NULL, NULL, NULL);
2146   }
2147   return GL_TRUE;
2148}
2149
2150
2151GLboolean XMesaLoseCurrent(XMesaContext c)
2152{
2153   (void) c;
2154   _mesa_make_current(NULL, NULL, NULL);
2155   return GL_TRUE;
2156}
2157
2158
2159/*
2160 * Switch 3Dfx support hack between window and full-screen mode.
2161 */
2162GLboolean XMesaSetFXmode( GLint mode )
2163{
2164#ifdef FX
2165   const char *fx = _mesa_getenv("MESA_GLX_FX");
2166   if (fx && fx[0] != 'd') {
2167      GET_CURRENT_CONTEXT(ctx);
2168      GrHwConfiguration hw;
2169      if (!FX_grSstQueryHardware(&hw)) {
2170         /*fprintf(stderr, "!grSstQueryHardware\n");*/
2171         return GL_FALSE;
2172      }
2173      if (hw.num_sst < 1) {
2174         /*fprintf(stderr, "hw.num_sst < 1\n");*/
2175         return GL_FALSE;
2176      }
2177      if (ctx) {
2178         /* [dBorca] Hack alert:
2179	  * oh, this is sooo wrong: ctx above is
2180	  * really an fxMesaContext, not an XMesaContext
2181	  */
2182         XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
2183         if (mode == XMESA_FX_WINDOW) {
2184	    if (xmbuf->FXisHackUsable) {
2185	       FX_grSstControl(GR_CONTROL_DEACTIVATE);
2186	       xmbuf->FXwindowHack = GL_TRUE;
2187	       return GL_TRUE;
2188	    }
2189	 }
2190	 else if (mode == XMESA_FX_FULLSCREEN) {
2191	    FX_grSstControl(GR_CONTROL_ACTIVATE);
2192	    xmbuf->FXwindowHack = GL_FALSE;
2193	    return GL_TRUE;
2194	 }
2195	 else {
2196	    /* Error: Bad mode value */
2197	 }
2198      }
2199   }
2200   /*fprintf(stderr, "fallthrough\n");*/
2201#else
2202   (void) mode;
2203#endif
2204   return GL_FALSE;
2205}
2206
2207
2208
2209#ifdef FX
2210/*
2211 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2212 */
2213static void FXgetImage( XMesaBuffer b )
2214{
2215   GET_CURRENT_CONTEXT(ctx);
2216   static unsigned short pixbuf[MAX_WIDTH];
2217   GLuint x, y;
2218   int xpos, ypos;
2219   XMesaWindow root;
2220   unsigned int bw, depth, width, height;
2221   XMesaContext xmesa = XMESA_CONTEXT(ctx);
2222
2223#ifdef XFree86Server
2224   x = b->frontxrb->pixmap->x;
2225   y = b->frontxrb->pixmap->y;
2226   width = b->frontxrb->pixmap->width;
2227   height = b->frontxrb->pixmap->height;
2228   depth = b->frontxrb->pixmap->depth;
2229#else
2230   XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap,
2231                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2232#endif
2233   if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) {
2234      b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width);
2235      b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height);
2236      if (b->mesa_buffer.Width & 1)
2237         b->mesa_buffer.Width--;  /* prevent odd width */
2238      xmesa_alloc_back_buffer(b, b->mesa_buffer.Width, b->mesa_buffer.Height);
2239   }
2240
2241   /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
2242   /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
2243   if (b->xm_visual->undithered_pf==PF_5R6G5B) {
2244      /* Special case: 16bpp RGB */
2245      grLfbReadRegion( GR_BUFFER_FRONTBUFFER,       /* src buffer */
2246                       0, b->FXctx->height - b->mesa_buffer.Height,  /*pos*/
2247                       b->mesa_buffer.Width, b->mesa_buffer.Height,  /* size */
2248                       b->mesa_buffer.Width * sizeof(GLushort), /* stride */
2249                       b->backxrb->ximage->data);         /* dest buffer */
2250   }
2251   else if (b->xm_visual->dithered_pf==PF_Dither
2252	    && GET_VISUAL_DEPTH(b->xm_visual)==8) {
2253      /* Special case: 8bpp RGB */
2254      for (y=0;y<b->mesa_buffer.Height;y++) {
2255         GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data
2256                        + b->backxrb->ximage->bytes_per_line * y;
2257         XDITHER_SETUP(y);
2258
2259         /* read row from 3Dfx frame buffer */
2260         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2261                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2262                          b->mesa_buffer.Width, 1,
2263                          0,
2264                          pixbuf );
2265
2266         /* write to XImage back buffer */
2267         for (x=0;x<b->mesa_buffer.Width;x++) {
2268            GLubyte r = (pixbuf[x] & 0xf800) >> 8;
2269            GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
2270            GLubyte b = (pixbuf[x] & 0x001f) << 3;
2271            *ptr++ = XDITHER( x, r, g, b);
2272         }
2273      }
2274   }
2275   else {
2276      /* General case: slow! */
2277      for (y=0;y<b->mesa_buffer.Height;y++) {
2278         /* read row from 3Dfx frame buffer */
2279         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2280                          0, b->FXctx->height-(b->mesa_buffer.Height-y),
2281                          b->mesa_buffer.Width, 1,
2282                          0,
2283                          pixbuf );
2284
2285         /* write to XImage back buffer */
2286         for (x=0;x<b->mesa_buffer.Width;x++) {
2287            XMesaPutPixel(b->backxrb->ximage,x,y,
2288			  xmesa_color_to_pixel(ctx,
2289					       (pixbuf[x] & 0xf800) >> 8,
2290					       (pixbuf[x] & 0x07e0) >> 3,
2291					       (pixbuf[x] & 0x001f) << 3,
2292					       0xff,
2293                                               b->xm_visual->undithered_pf));
2294         }
2295      }
2296   }
2297   /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
2298}
2299#endif
2300
2301
2302/*
2303 * Copy the back buffer to the front buffer.  If there's no back buffer
2304 * this is a no-op.
2305 */
2306void XMesaSwapBuffers( XMesaBuffer b )
2307{
2308   GET_CURRENT_CONTEXT(ctx);
2309
2310   if (!b->backxrb) {
2311      /* single buffered */
2312      return;
2313   }
2314
2315   /* If we're swapping the buffer associated with the current context
2316    * we have to flush any pending rendering commands first.
2317    */
2318   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2319      _mesa_notifySwapBuffers(ctx);
2320
2321   if (b->db_mode) {
2322#ifdef FX
2323      if (b->FXctx) {
2324         fxMesaSwapBuffers();
2325
2326         if (b->FXwindowHack)
2327            FXgetImage(b);
2328         else
2329            return;
2330      }
2331#endif
2332     if (b->backxrb->ximage) {
2333	 /* Copy Ximage from host's memory to server's window */
2334#if defined(USE_XSHM) && !defined(XFree86Server)
2335	 if (b->shm) {
2336            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2337	    XShmPutImage( b->xm_visual->display, b->frontxrb->pixmap,
2338			  b->swapgc,
2339			  b->backxrb->ximage, 0, 0,
2340			  0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2341                          False );
2342            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2343	 }
2344	 else
2345#endif
2346         {
2347            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2348            XMesaPutImage( b->xm_visual->display, b->frontxrb->pixmap,
2349			   b->swapgc,
2350			   b->backxrb->ximage, 0, 0,
2351			   0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
2352            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2353         }
2354      }
2355      else {
2356	 /* Copy pixmap to window on server */
2357         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2358	 XMesaCopyArea( b->xm_visual->display,
2359			b->backxrb->pixmap,   /* source drawable */
2360			b->frontxrb->pixmap,  /* dest. drawable */
2361			b->swapgc,
2362			0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2363			0, 0                 /* dest region */
2364		      );
2365         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2366      }
2367   }
2368#if !defined(XFree86Server)
2369   XSync( b->xm_visual->display, False );
2370#endif
2371}
2372
2373
2374
2375/*
2376 * Copy sub-region of back buffer to front buffer
2377 */
2378void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2379{
2380   GET_CURRENT_CONTEXT(ctx);
2381
2382   /* If we're swapping the buffer associated with the current context
2383    * we have to flush any pending rendering commands first.
2384    */
2385   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2386      _mesa_notifySwapBuffers(ctx);
2387
2388   if (!b->backxrb) {
2389      /* single buffered */
2390      return;
2391   }
2392
2393   if (b->db_mode) {
2394      int yTop = b->mesa_buffer.Height - y - height;
2395#ifdef FX
2396      if (b->FXctx) {
2397         fxMesaSwapBuffers();
2398         if (b->FXwindowHack)
2399            FXgetImage(b);
2400         else
2401            return;
2402      }
2403#endif
2404      if (b->backxrb->ximage) {
2405         /* Copy Ximage from host's memory to server's window */
2406#if defined(USE_XSHM) && !defined(XFree86Server)
2407         if (b->shm) {
2408            /* XXX assuming width and height aren't too large! */
2409            XShmPutImage( b->xm_visual->display, b->frontxrb->pixmap,
2410                          b->swapgc,
2411                          b->backxrb->ximage, x, yTop,
2412                          x, yTop, width, height, False );
2413            /* wait for finished event??? */
2414         }
2415         else
2416#endif
2417         {
2418            /* XXX assuming width and height aren't too large! */
2419            XMesaPutImage( b->xm_visual->display, b->frontxrb->pixmap,
2420			   b->swapgc,
2421			   b->backxrb->ximage, x, yTop,
2422			   x, yTop, width, height );
2423         }
2424      }
2425      else {
2426         /* Copy pixmap to window on server */
2427         XMesaCopyArea( b->xm_visual->display,
2428			b->backxrb->pixmap,           /* source drawable */
2429			b->frontxrb->pixmap,          /* dest. drawable */
2430			b->swapgc,
2431			x, yTop, width, height,  /* source region */
2432			x, yTop                  /* dest region */
2433                      );
2434      }
2435   }
2436}
2437
2438
2439/*
2440 * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
2441 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2442 * back buffer directly.
2443 * Output:  pixmap - pointer to back buffer's Pixmap, or 0
2444 *          ximage - pointer to back buffer's XImage, or NULL
2445 * Return:  GL_TRUE = context is double buffered
2446 *          GL_FALSE = context is single buffered
2447 */
2448GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2449                              XMesaPixmap *pixmap,
2450                              XMesaImage **ximage )
2451{
2452   if (b->db_mode) {
2453      if (pixmap)
2454         *pixmap = b->backxrb->pixmap;
2455      if (ximage)
2456         *ximage = b->backxrb->ximage;
2457      return GL_TRUE;
2458   }
2459   else {
2460      *pixmap = 0;
2461      *ximage = NULL;
2462      return GL_FALSE;
2463   }
2464}
2465
2466
2467/*
2468 * Return the depth buffer associated with an XMesaBuffer.
2469 * Input:  b - the XMesa buffer handle
2470 * Output:  width, height - size of buffer in pixels
2471 *          bytesPerValue - bytes per depth value (2 or 4)
2472 *          buffer - pointer to depth buffer values
2473 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
2474 */
2475GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2476                               GLint *bytesPerValue, void **buffer )
2477{
2478   struct gl_renderbuffer *rb
2479      = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
2480   if (!rb || !rb->Data) {
2481      *width = 0;
2482      *height = 0;
2483      *bytesPerValue = 0;
2484      *buffer = 0;
2485      return GL_FALSE;
2486   }
2487   else {
2488      *width = b->mesa_buffer.Width;
2489      *height = b->mesa_buffer.Height;
2490      *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
2491         ? sizeof(GLushort) : sizeof(GLuint);
2492      *buffer = rb->Data;
2493      return GL_TRUE;
2494   }
2495}
2496
2497
2498void XMesaFlush( XMesaContext c )
2499{
2500   if (c && c->xm_visual) {
2501#ifdef XFree86Server
2502      /* NOT_NEEDED */
2503#else
2504      XSync( c->xm_visual->display, False );
2505#endif
2506   }
2507}
2508
2509
2510
2511const char *XMesaGetString( XMesaContext c, int name )
2512{
2513   (void) c;
2514   if (name==XMESA_VERSION) {
2515      return "5.0";
2516   }
2517   else if (name==XMESA_EXTENSIONS) {
2518      return "";
2519   }
2520   else {
2521      return NULL;
2522   }
2523}
2524
2525
2526
2527XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2528{
2529   XMesaBuffer b;
2530   for (b=XMesaBufferList; b; b=b->Next) {
2531      if (b->frontxrb->pixmap==d && b->display==dpy) {
2532         return b;
2533      }
2534   }
2535   return NULL;
2536}
2537
2538
2539
2540/*
2541 * Look for XMesaBuffers whose X window has been destroyed.
2542 * Deallocate any such XMesaBuffers.
2543 */
2544void XMesaGarbageCollect( void )
2545{
2546   XMesaBuffer b, next;
2547   for (b=XMesaBufferList; b; b=next) {
2548      next = b->Next;
2549      if (b->display && b->frontxrb->pixmap && b->type == WINDOW) {
2550#ifdef XFree86Server
2551	 /* NOT_NEEDED */
2552#else
2553         XSync(b->display, False);
2554         if (!window_exists( b->display, b->frontxrb->pixmap )) {
2555            /* found a dead window, free the ancillary info */
2556            XMesaDestroyBuffer( b );
2557         }
2558#endif
2559      }
2560   }
2561}
2562
2563
2564void XMesaReset( void )
2565{
2566    while (XMesaBufferList)
2567	XMesaDestroyBuffer(XMesaBufferList);
2568
2569    XMesaBufferList = NULL;
2570}
2571
2572
2573unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2574                                GLfloat red, GLfloat green,
2575                                GLfloat blue, GLfloat alpha )
2576{
2577   GLcontext *ctx = &xmesa->mesa;
2578   GLint r = (GLint) (red   * 255.0F);
2579   GLint g = (GLint) (green * 255.0F);
2580   GLint b = (GLint) (blue  * 255.0F);
2581   GLint a = (GLint) (alpha * 255.0F);
2582
2583   switch (xmesa->pixelformat) {
2584      case PF_Index:
2585         return 0;
2586      case PF_Truecolor:
2587         {
2588            unsigned long p;
2589            PACK_TRUECOLOR( p, r, g, b );
2590            return p;
2591         }
2592      case PF_8A8B8G8R:
2593         return PACK_8A8B8G8R( r, g, b, a );
2594      case PF_8A8R8G8B:
2595         return PACK_8A8R8G8B( r, g, b, a );
2596      case PF_8R8G8B:
2597         return PACK_8R8G8B( r, g, b );
2598      case PF_5R6G5B:
2599         return PACK_5R6G5B( r, g, b );
2600      case PF_Dither:
2601         {
2602            DITHER_SETUP;
2603            return DITHER( x, y, r, g, b );
2604         }
2605      case PF_1Bit:
2606         /* 382 = (3*255)/2 */
2607         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2608      case PF_HPCR:
2609         return DITHER_HPCR(x, y, r, g, b);
2610      case PF_Lookup:
2611         {
2612            LOOKUP_SETUP;
2613            return LOOKUP( r, g, b );
2614         }
2615      case PF_Grayscale:
2616         return GRAY_RGB( r, g, b );
2617      case PF_Dither_5R6G5B:
2618         /* fall through */
2619      case PF_Dither_True:
2620         {
2621            unsigned long p;
2622            PACK_TRUEDITHER(p, x, y, r, g, b);
2623            return p;
2624         }
2625      default:
2626         _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2627   }
2628   return 0;
2629}
2630
2631
2632/*
2633 * This is typically called when the window size changes and we need
2634 * to reallocate the buffer's back/depth/stencil/accum buffers.
2635 */
2636void XMesaResizeBuffers( XMesaBuffer b )
2637{
2638#ifdef XFree86Server
2639   GET_CURRENT_CONTEXT(ctx);
2640   xmesa_resize_buffers(ctx, &(b->mesa_buffer), 0, 0);
2641#else
2642   Window root;
2643   int xpos, ypos;
2644   unsigned int width, height, bw, depth;
2645   GET_CURRENT_CONTEXT(ctx);
2646   XGetGeometry( b->xm_visual->display, b->frontxrb->pixmap,
2647                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2648   xmesa_resize_buffers(ctx, &(b->mesa_buffer), width, height);
2649#endif
2650}
2651
2652