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