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