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