~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/extras/Mesa/src/X/xm_api.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

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