xm_api.c revision 1832f1cc86758fdcbd122edd5bf9e7a29ccade20
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* $Id: xm_api.c,v 1.21 2001/04/27 21:18:25 brianp Exp $ */
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mesa 3-D graphics library
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version:  3.5
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the "Software"),
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to deal in the Software without restriction, including without limitation
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * and/or sell copies of the Software, and to permit persons to whom the
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Software is furnished to do so, subject to the following conditions:
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The above copyright notice and this permission notice shall be included
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in all copies or substantial portions of the Software.
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This file contains the implementations of all the XMesa* functions.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * NOTES:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The window coordinate system origin (0,0) is in the lower-left corner
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of the window.  X11's window coordinate origin is in the upper-left
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * corner of the window.  Therefore, most drawing functions in this
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * file have to flip Y coordinates.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in support for the MIT Shared Memory extension.  If enabled, when you
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use an Ximage for the back buffer in double buffered mode, the "swap"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * operation will be faster.  You must also link with -lXext.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Byte swapping:  If the Mesa host and the X display use a different
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * byte order then there's some trickiness to be aware of when using
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * XImages.  The byte ordering used for the XImage is that of the X
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * display, not the Mesa host.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The color-to-pixel encoding for True/DirectColor must be done
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * according to the display's visual red_mask, green_mask, and blue_mask.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * do byte swapping if needed.  If one wants to directly "poke" the pixel
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * into the XImage's buffer then the pixel must be byte swapped first.  In
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and use XPutPixel everywhere except in the implementation of
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * glClear(GL_COLOR_BUFFER_BIT).  We want this function to be fast so
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * instead of using XPutPixel we "poke" our values after byte-swapping
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the clear pixel value if needed.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __CYGWIN__
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef WIN32
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef __WIN32__
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "glxheader.h"
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GL/xmesa.h"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xmesaP.h"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "context.h"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "extensions.h"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "glthread.h"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "matrix.h"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "mem.h"
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "mmath.h"
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "mtypes.h"
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CONFIG_H
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "conf.h"
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "macros.h"
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "swrast/swrast.h"
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "swrast_setup/swrast_setup.h"
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "array_cache/acache.h"
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tnl/tnl.h"
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GLX_NONE_EXT
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GLX_NONE_EXT 0x8000
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Global X driver lock
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_glthread_Mutex _xmesa_lock;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Lookup tables for HPCR pixel format:
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static short hpcr_rgbTbl[3][256] = {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)},
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)},
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 40,  40,  41,  41,  42,  42,  43,  43,  44,  44,  45,  45,  46,  46,  47,  47,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48,  48,  49,  49,  50,  50,  51,  51,  52,  52,  53,  53,  54,  54,  55,  55,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 56,  56,  57,  57,  58,  58,  59,  59,  60,  60,  61,  61,  62,  62,  63,  63,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 64,  64,  65,  65,  66,  66,  67,  67,  68,  68,  69,  69,  70,  70,  71,  71,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72,  72,  73,  73,  74,  74,  75,  75,  76,  76,  77,  77,  78,  78,  79,  79,
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 80,  80,  81,  81,  82,  82,  83,  83,  84,  84,  85,  85,  86,  86,  87,  87,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**********************************************************************/
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*****                     X Utility Functions                    *****/
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**********************************************************************/
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * X/Mesa error reporting function:
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void error( const char *msg )
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (getenv("MESA_DEBUG"))
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf( stderr, "X/Mesa error: %s\n", msg );
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the host's byte order as LSBFirst or MSBFirst ala X.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef XFree86Server
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int host_byte_order( void )
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int i = 1;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   char *cptr = (char *) &i;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   return (*cptr==1) ? LSBFirst : MSBFirst;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Error handling.
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef XFree86Server
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int mesaXErrorFlag = 0;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event )
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   (void) dpy;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   (void) event;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   mesaXErrorFlag = 1;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return 0;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Check if the X Shared Memory extension is available.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return:  0 = not available
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *          1 = shared XImage support available
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *          2 = shared Pixmap support available also
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef XFree86Server
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int check_for_xshm( XMesaDisplay *display )
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef USE_XSHM
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int major, minor, ignore;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   Bool pixmaps;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return (pixmaps==True) ? 2 : 1;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return 0;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Can't compile XSHM support */
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return 0;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the width and height of the given drawable.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void get_drawable_size( XMesaDisplay *dpy, XMesaDrawable d,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               unsigned int *width, unsigned int *height)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XFree86Server
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void) dpy;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *width = d->width;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *height = d->height;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   Window root;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int x, y;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   unsigned int bw, depth;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   _glthread_LOCK_MUTEX(_xmesa_lock);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth );
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   _glthread_UNLOCK_MUTEX(_xmesa_lock);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Apply gamma correction to an intensity value in [0..max].  Return the
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new intensity value.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max )
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (gamma == 1.0) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return value;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double x = (double) value / (double) max;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return IROUND_POS((GLfloat) max * pow(x, 1.0F/gamma));
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Return the true number of bits per pixel for XImages.
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * For example, if we request a 24-bit deep visual we may actually need/get
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 32bpp XImages.  This function returns the appropriate bpp.
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Input:  dpy - the X display
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *         visinfo - desribes the visual to be used for XImages
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Return:  true number of bits per pixel for XImages
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GET_BITS_PER_PIXEL(xmv) bits_per_pixel(xmv)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef XFree86Server
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int bits_per_pixel( XMesaVisual xmv )
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   XMesaVisualInfo visinfo = xmv->visinfo;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   const int depth = visinfo->nplanes;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   int i;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   for (i = 0; i < screenInfo.numPixmapFormats; i++) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (screenInfo.formats[i].depth == depth)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         return screenInfo.formats[i].bitsPerPixel;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   return depth;  /* should never get here, but this should be safe */
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int bits_per_pixel( XMesaVisual xmv )
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   XMesaDisplay *dpy = xmv->display;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   XMesaVisualInfo visinfo = xmv->visinfo;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   XMesaImage *img;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   int bitsPerPixel;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   /* Create a temporary XImage */
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		       ZPixmap, 0,           /*format, offset*/
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		       (char*) MALLOC(8),    /*data*/
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		       1, 1,                 /*width, height*/
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		       32,                   /*bitmap_pad*/
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		       0                     /*bytes_per_line*/
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     );
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   assert(img);
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   /* grab the bits/pixel value */
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   bitsPerPixel = img->bits_per_pixel;
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   /* free the XImage */
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   FREE( img->data );
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   img->data = NULL;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   XMesaDestroyImage( img );
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   return bitsPerPixel;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Determine if a given X window ID is valid (window exists).
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Do this by calling XGetWindowAttributes() for the window and
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * checking if we catch an X error.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Input:  dpy - the display
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         win - the window to check for existance
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return:  GL_TRUE - window exists
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *          GL_FALSE - window doesn't exist
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef XFree86Server
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean WindowExistsFlag;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   (void) dpy;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (xerr->error_code == BadWindow) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WindowExistsFlag = GL_FALSE;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return 0;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean window_exists( XMesaDisplay *dpy, Window win )
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XWindowAttributes wa;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int (*old_handler)( XMesaDisplay*, XErrorEvent* );
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   WindowExistsFlag = GL_TRUE;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   old_handler = XSetErrorHandler(window_exists_err_handler);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XSetErrorHandler(old_handler);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return WindowExistsFlag;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**********************************************************************/
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*****                Linked list of XMesaBuffers                 *****/
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**********************************************************************/
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static XMesaBuffer XMesaBufferList = NULL;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Allocate a new XMesaBuffer, add to linked list */
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static XMesaBuffer alloc_xmesa_buffer(void)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (b) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->Next = XMesaBufferList;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XMesaBufferList = b;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return b;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find an XMesaBuffer by matching X display and colormap but NOT matching
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the notThis buffer.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     XMesaColormap cmap,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     XMesaBuffer notThis)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XMesaBuffer b;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (b=XMesaBufferList; b; b=b->Next) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (b->display==dpy && b->cmap==cmap && b!=notThis) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return b;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return NULL;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * entries.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void free_xmesa_buffer(int client, XMesaBuffer buffer)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XMesaBuffer prev = NULL, b;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   (void) client;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (b=XMesaBufferList; b; b=b->Next) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (b==buffer) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* unlink bufer from list */
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (prev)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prev->Next = buffer->Next;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            XMesaBufferList = buffer->Next;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Check to free X colors */
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (buffer->num_alloced>0) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* If no other buffer uses this X colormap then free the colors. */
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XFree86Server
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (void)FreeColors(buffer->cmap, client,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				buffer->num_alloced, buffer->alloced_colors,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				0);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               XFreeColors(buffer->display, buffer->cmap,
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           buffer->alloced_colors, buffer->num_alloced, 0);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         _mesa_free_framebuffer_data(&buffer->mesa_buffer);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         FREE(buffer);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* continue search */
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prev = b;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* buffer not found in XMesaBufferList */
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n");
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copy X color table stuff from one XMesaBuffer to another. */
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r));
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g));
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b));
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   dst->num_alloced = src->num_alloced;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   MEMCPY(dst->alloced_colors, src->alloced_colors,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sizeof(src->alloced_colors));
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/**********************************************************************/
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*****                   Misc Private Functions                   *****/
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**********************************************************************/
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return number of bits set in n.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int bitcount( unsigned long n )
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int bits;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (bits=0; n>0; n=n>>1) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (n&1) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         bits++;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   return bits;
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return:  GL_TRUE if success, GL_FALSE if error
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef XFree86Server
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean alloc_shm_back_buffer( XMesaBuffer b )
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef USE_XSHM
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /*
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * We have to do a _lot_ of error checking here to be sure we can
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * really use the XSHM extension.  It seems different servers trigger
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * errors at different points if the extension won't work.  Therefore
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * we have to be very careful...
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GC gc;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int (*old_handler)( XMesaDisplay *, XErrorEvent * );
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   b->backimage = XShmCreateImage( b->xm_visual->display,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   b->xm_visual->visinfo->visual,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   b->xm_visual->visinfo->depth,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   ZPixmap, NULL, &b->shminfo,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   b->width, b->height );
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (b->backimage == NULL) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error("alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->shm = 0;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_FALSE;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			     * b->backimage->height, IPC_CREAT|0777 );
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   if (b->shminfo.shmid < 0) {
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (getenv("MESA_DEBUG"))
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          perror("alloc_back_buffer");
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      XDestroyImage( b->backimage );
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      b->backimage = NULL;
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error("alloc_back_buffer: Shared memory error (shmget), disabling.");
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      b->shm = 0;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return GL_FALSE;
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   b->shminfo.shmaddr = b->backimage->data
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      = (char*)shmat( b->shminfo.shmid, 0, 0 );
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   if (b->shminfo.shmaddr == (char *) -1) {
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (getenv("MESA_DEBUG"))
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          perror("alloc_back_buffer");
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      XDestroyImage( b->backimage );
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      b->backimage = NULL;
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error("alloc_back_buffer: Shared memory error (shmat), disabling.");
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      b->shm = 0;
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return GL_FALSE;
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   b->shminfo.readOnly = False;
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   mesaXErrorFlag = 0;
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   old_handler = XSetErrorHandler( mesaHandleXError );
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   /* This may trigger the X protocol error we're ready to catch: */
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   XShmAttach( b->xm_visual->display, &b->shminfo );
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   XSync( b->xm_visual->display, False );
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   if (mesaXErrorFlag) {
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      /* we are on a remote display, this error is normal, don't print it */
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      XFlush( b->xm_visual->display );
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      mesaXErrorFlag = 0;
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      XDestroyImage( b->backimage );
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      shmdt( b->shminfo.shmaddr );
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      b->backimage = NULL;
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      b->shm = 0;
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (void) XSetErrorHandler( old_handler );
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return GL_FALSE;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Finally, try an XShmPutImage to be really sure the extension works */
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL );
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XShmPutImage( b->xm_visual->display, b->frontbuffer, gc,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False );
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XSync( b->xm_visual->display, False );
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XFreeGC( b->xm_visual->display, gc );
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   (void) XSetErrorHandler( old_handler );
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (mesaXErrorFlag) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XFlush( b->xm_visual->display );
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mesaXErrorFlag = 0;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XDestroyImage( b->backimage );
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shmdt( b->shminfo.shmaddr );
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shmctl( b->shminfo.shmid, IPC_RMID, 0 );
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->backimage = NULL;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->shm = 0;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_FALSE;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (b->backimage) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int height = b->backimage->height;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Needed by PIXELADDR1 macro */
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->ximage_width1 = b->backimage->bytes_per_line;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->ximage_origin1 = (GLubyte *) b->backimage->data
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        + b->ximage_width1 * (height-1);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Needed by PIXELADDR2 macro */
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->ximage_width2 = b->backimage->bytes_per_line / 2;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->ximage_origin2 = (GLushort *) b->backimage->data
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        + b->ximage_width2 * (height-1);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Needed by PIXELADDR3 macro */
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->ximage_width3 = b->backimage->bytes_per_line;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->ximage_origin3 = (GLubyte *) b->backimage->data
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        + b->ximage_width3 * (height-1);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Needed by PIXELADDR4 macro */
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->ximage_width4 = b->backimage->width;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->ximage_origin4 = (GLuint *) b->backimage->data
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        + b->ximage_width4 * (height-1);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GL_TRUE;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Can't compile XSHM support */
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GL_FALSE;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Setup an off-screen pixmap or Ximage to use as the back buffer.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Input:  b - the X/Mesa buffer
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void xmesa_alloc_back_buffer( XMesaBuffer b )
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (b->db_state==BACK_XIMAGE) {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Deallocate the old backimage, if any */
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (b->backimage) {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_XSHM) && !defined(XFree86Server)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 if (b->shm) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    XShmDetach( b->xm_visual->display, &b->shminfo );
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    XDestroyImage( b->backimage );
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    shmdt( b->shminfo.shmaddr );
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 }
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 else
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   XMesaDestroyImage( b->backimage );
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 b->backimage = NULL;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Allocate new back buffer */
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XFree86Server
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 /* Allocate a regular XImage for the back buffer. */
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 b->backimage = XMesaCreateImage(b->xm_visual->BitsPerPixel,
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 b->width, b->height, NULL);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (b->shm==0
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  || alloc_shm_back_buffer(b)==GL_FALSE
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  ) {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 /* Allocate a regular XImage for the back buffer. */
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 b->backimage = XCreateImage( b->xm_visual->display,
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      b->xm_visual->visinfo->visual,
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      GET_VISUAL_DEPTH(b->xm_visual),
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      ZPixmap, 0,   /* format, offset */
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      NULL, b->width, b->height,
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      8, 0 );  /* pad, bytes_per_line */
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 if (!b->backimage) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    error("alloc_back_buffer: XCreateImage failed.");
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 }
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         b->backimage->data = (char *) MALLOC( b->backimage->height
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             * b->backimage->bytes_per_line );
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (!b->backimage->data) {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            error("alloc_back_buffer: MALLOC failed.");
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            XMesaDestroyImage( b->backimage );
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            b->backimage = NULL;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->backpixmap = None;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else if (b->db_state==BACK_PIXMAP) {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XMesaPixmap old_pixmap = b->backpixmap;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Free the old back pixmap */
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (b->backpixmap) {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 XMesaFreePixmap( b->xm_visual->display, b->backpixmap );
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Allocate new back pixmap */
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->backpixmap = XMesaCreatePixmap( b->xm_visual->display, b->frontbuffer,
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 b->width, b->height,
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 GET_VISUAL_DEPTH(b->xm_visual) );
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b->backimage = NULL;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* update other references to backpixmap */
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (b->buffer==(XMesaDrawable)old_pixmap) {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 b->buffer = (XMesaDrawable)b->backpixmap;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A replacement for XAllocColor.  This function should never
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fail to allocate a color.  When XAllocColor fails, we return
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the nearest matching color.  If we have to allocate many colors
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this function isn't too efficient; the XQueryColors() could be
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * done just once.
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Written by Michael Pichler, Brian Paul, Mark Kilgard
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Input:  dpy - X display
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         cmap - X colormap
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         cmapSize - size of colormap
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In/Out: color - the XColor struct
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Output:  exact - 1=exact color match, 0=closest match
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *          alloced - 1=XAlloc worked, 0=XAlloc failed
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)noFaultXAllocColor( int client,
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    XMesaDisplay *dpy,
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    XMesaColormap cmap,
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int cmapSize,
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    XMesaColor *color,
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int *exact, int *alloced )
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XFree86Server
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   Pixel *ppixIn;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   xrgb *ctable;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* we'll try to cache ctable for better remote display performance */
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   static Display *prevDisplay = NULL;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   static XMesaColormap prevCmap = 0;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   static int prevCmapSize = 0;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   static XMesaColor *ctable = NULL;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   XMesaColor subColor;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int i, bestmatch;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   double mindist;       /* 3*2^16^2 exceeds long int precision. */
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   (void) client;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* First try just using XAllocColor. */
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XFree86Server
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (AllocColor(cmap,
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  &color->red, &color->green, &color->blue,
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  &color->pixel,
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  client) == Success) {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (XAllocColor(dpy, cmap, color)) {
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *exact = 1;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *alloced = 1;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Alloc failed, search for closest match */
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Retrieve color table entries. */
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* XXX alloca candidate. */
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XFree86Server
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel));
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb));
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < cmapSize; i++) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ppixIn[i] = i;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   QueryColors(cmap, cmapSize, ppixIn, ctable);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (prevDisplay != dpy || prevCmap != cmap
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || prevCmapSize != cmapSize || !ctable) {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* free previously cached color table */
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ctable)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         FREE(ctable);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Get the color table from X */
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor));
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(ctable);
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < cmapSize; i++) {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ctable[i].pixel = i;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XQueryColors(dpy, cmap, ctable, cmapSize);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prevDisplay = dpy;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prevCmap = cmap;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prevCmapSize = cmapSize;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Find best match. */
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   bestmatch = -1;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   mindist = 0.0;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < cmapSize; i++) {
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double dist = dr * dr + dg * dg + db * db;
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (bestmatch < 0 || dist < mindist) {
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         bestmatch = i;
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         mindist = dist;
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   /* Return result. */
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   subColor.red   = ctable[bestmatch].red;
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   subColor.green = ctable[bestmatch].green;
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   subColor.blue  = ctable[bestmatch].blue;
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   /* Try to allocate the closest match color.  This should only
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * fail if the cell is read/write.  Otherwise, we're incrementing
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * the cell's reference count.
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    */
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef XFree86Server
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   if (AllocColor(cmap,
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		  &subColor.red, &subColor.green, &subColor.blue,
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		  &subColor.pixel,
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		  client) == Success) {
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   if (XAllocColor(dpy, cmap, &subColor)) {
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *alloced = 1;
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   else {
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      /* do this to work around a problem reported by Frank Ortega */
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      subColor.pixel = (unsigned long) bestmatch;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      subColor.red   = ctable[bestmatch].red;
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      subColor.green = ctable[bestmatch].green;
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      subColor.blue  = ctable[bestmatch].blue;
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      subColor.flags = DoRed | DoGreen | DoBlue;
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *alloced = 0;
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef XFree86Server
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   FREE(ppixIn);
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   FREE(ctable);
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   /* don't free table, save it for next time */
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   *color = subColor;
803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   *exact = 0;
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/*
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Do setup for PF_GRAYSCALE pixel format.
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that buffer may be NULL.
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean setup_grayscale( int client, XMesaVisual v,
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  XMesaBuffer buffer, XMesaColormap cmap )
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_FALSE;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (buffer) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XMesaBuffer prevBuffer;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!cmap) {
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return GL_FALSE;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (prevBuffer &&
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (buffer->xm_visual->mesa_visual.rgbMode ==
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Copy colormap stuff from previous XMesaBuffer which uses same
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * X colormap.  Do this to avoid time spent in noFaultXAllocColor.
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         copy_colortable_info(buffer, prevBuffer);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Allocate 256 shades of gray */
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int gray;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         int colorsfailed = 0;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (gray=0;gray<256;gray++) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GLint r = gamma_adjust( v->RedGamma,   gray, 255 );
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GLint b = gamma_adjust( v->BlueGamma,  gray, 255 );
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int exact, alloced;
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            XMesaColor xcol;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xcol.red   = (r << 8) | r;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xcol.green = (g << 8) | g;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xcol.blue  = (b << 8) | b;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            noFaultXAllocColor( client, v->display,
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                cmap, GET_COLORMAP_SIZE(v),
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &xcol, &exact, &alloced );
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (!exact) {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               colorsfailed++;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (alloced) {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               assert(buffer->num_alloced<256);
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               buffer->num_alloced++;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /*OLD
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            assert(gray < 576);
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            buffer->color_table[gray*3+0] = xcol.pixel;
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            buffer->color_table[gray*3+1] = xcol.pixel;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer->color_table[gray*3+2] = xcol.pixel;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            assert(xcol.pixel < 65536);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            */
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer->color_table[gray] = xcol.pixel;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            assert(xcol.pixel < 65536);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer->pixel_to_r[xcol.pixel] = gray;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer->pixel_to_g[xcol.pixel] = gray;
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            buffer->pixel_to_b[xcol.pixel] = gray;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (colorsfailed && getenv("MESA_DEBUG")) {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fprintf( stderr,
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "Note: %d out of 256 needed colors do not match exactly.\n",
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  colorsfailed );
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   v->dithered_pf = PF_GRAYSCALE;
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   v->undithered_pf = PF_GRAYSCALE;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GL_TRUE;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Setup RGB rendering for a window with a PseudoColor, StaticColor,
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * or 8-bit TrueColor visual visual.  We try to allocate a palette of 225
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * color.  While this function was originally designed just for 8-bit
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Dithering code contributed by Bob Mercier.
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static GLboolean setup_dithered_color( int client, XMesaVisual v,
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       XMesaBuffer buffer, XMesaColormap cmap )
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_FALSE;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (buffer) {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XMesaBuffer prevBuffer;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!cmap) {
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return GL_FALSE;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (prevBuffer &&
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (buffer->xm_visual->mesa_visual.rgbMode ==
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* Copy colormap stuff from previous, matching XMesaBuffer.
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * Do this to avoid time spent in noFaultXAllocColor.
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         copy_colortable_info(buffer, prevBuffer);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
925         /* Allocate X colors and initialize color_table[], red_table[], etc */
926         int r, g, b, i;
927         int colorsfailed = 0;
928         for (r = 0; r < _R; r++) {
929            for (g = 0; g < _G; g++) {
930               for (b = 0; b < _B; b++) {
931                  XMesaColor xcol;
932                  int exact, alloced;
933                  xcol.red  =gamma_adjust(v->RedGamma,   r*65535/(_R-1),65535);
934                  xcol.green=gamma_adjust(v->GreenGamma, g*65535/(_G-1),65535);
935                  xcol.blue =gamma_adjust(v->BlueGamma,  b*65535/(_B-1),65535);
936                  noFaultXAllocColor( client, v->display,
937                                      cmap, GET_COLORMAP_SIZE(v),
938                                      &xcol, &exact, &alloced );
939                  if (!exact) {
940                     colorsfailed++;
941                  }
942                  if (alloced) {
943                     assert(buffer->num_alloced<256);
944                     buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
945                     buffer->num_alloced++;
946                  }
947                  i = _MIX( r, g, b );
948                  assert(i < 576);
949                  buffer->color_table[i] = xcol.pixel;
950                  assert(xcol.pixel < 65536);
951                  buffer->pixel_to_r[xcol.pixel] = r * 255 / (_R-1);
952                  buffer->pixel_to_g[xcol.pixel] = g * 255 / (_G-1);
953                  buffer->pixel_to_b[xcol.pixel] = b * 255 / (_B-1);
954               }
955            }
956         }
957
958         if (colorsfailed && getenv("MESA_DEBUG")) {
959            fprintf( stderr,
960                  "Note: %d out of %d needed colors do not match exactly.\n",
961                  colorsfailed, _R*_G*_B );
962         }
963      }
964   }
965
966   v->dithered_pf = PF_DITHER;
967   v->undithered_pf = PF_LOOKUP;
968   return GL_TRUE;
969}
970
971
972/*
973 * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
974 * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
975 * Special dithering tables have to be initialized.
976 */
977static void setup_8bit_hpcr( XMesaVisual v )
978{
979   /* HP Color Recovery contributed by:  Alex De Bruyn (ad@lms.be)
980    * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
981    * on the root window AND the colormap obtainable by XGetRGBColormaps
982    * for that atom must be set on the window.  (see also tkInitWindow)
983    * If that colormap is not set, the output will look stripy.
984    */
985
986   /* Setup color tables with gamma correction */
987   int i;
988   double g;
989
990   g = 1.0 / v->RedGamma;
991   for (i=0; i<256; i++) {
992      GLint red = IROUND_POS(255.0 * pow( hpcr_rgbTbl[0][i]/255.0, g ));
993      v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 );
994   }
995
996   g = 1.0 / v->GreenGamma;
997   for (i=0; i<256; i++) {
998      GLint green = IROUND_POS(255.0 * pow( hpcr_rgbTbl[1][i]/255.0, g ));
999      v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 );
1000   }
1001
1002   g = 1.0 / v->BlueGamma;
1003   for (i=0; i<256; i++) {
1004      GLint blue = IROUND_POS(255.0 * pow( hpcr_rgbTbl[2][i]/255.0, g ));
1005      v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 );
1006   }
1007   v->undithered_pf = PF_HPCR;  /* can't really disable dithering for now */
1008   v->dithered_pf = PF_HPCR;
1009
1010   /* which method should I use to clear */
1011   /* GL_FALSE: keep the ordinary method  */
1012   /* GL_TRUE : clear with dither pattern */
1013   v->hpcr_clear_flag = getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE;
1014
1015   if (v->hpcr_clear_flag) {
1016      v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display,
1017                                               DefaultRootWindow(v->display),
1018                                               16, 2, 8);
1019#ifndef XFree86Server
1020      v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap,
1021                                       0, 0, 16, 2, AllPlanes, ZPixmap);
1022#endif
1023   }
1024}
1025
1026
1027/*
1028 * Setup RGB rendering for a window with a True/DirectColor visual.
1029 */
1030static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer,
1031                             XMesaWindow window, XMesaColormap cmap )
1032{
1033   unsigned long rmask, gmask, bmask;
1034   (void) buffer;
1035   (void) window;
1036   (void) cmap;
1037
1038   /* Compute red multiplier (mask) and bit shift */
1039   v->rshift = 0;
1040   rmask = GET_REDMASK(v);
1041   while ((rmask & 1)==0) {
1042      v->rshift++;
1043      rmask = rmask >> 1;
1044   }
1045
1046   /* Compute green multiplier (mask) and bit shift */
1047   v->gshift = 0;
1048   gmask = GET_GREENMASK(v);
1049   while ((gmask & 1)==0) {
1050      v->gshift++;
1051      gmask = gmask >> 1;
1052   }
1053
1054   /* Compute blue multiplier (mask) and bit shift */
1055   v->bshift = 0;
1056   bmask = GET_BLUEMASK(v);
1057   while ((bmask & 1)==0) {
1058      v->bshift++;
1059      bmask = bmask >> 1;
1060   }
1061
1062   /*
1063    * Compute component-to-pixel lookup tables and dithering kernel
1064    */
1065   {
1066      static GLubyte kernel[16] = {
1067          0*16,  8*16,  2*16, 10*16,
1068         12*16,  4*16, 14*16,  6*16,
1069          3*16, 11*16,  1*16,  9*16,
1070         15*16,  7*16, 13*16,  5*16,
1071      };
1072      GLint rBits = bitcount(rmask);
1073      GLint gBits = bitcount(gmask);
1074      GLint bBits = bitcount(bmask);
1075      GLint maxBits;
1076      GLuint i;
1077
1078      /* convert pixel components in [0,_mask] to RGB values in [0,255] */
1079      for (i=0; i<=rmask; i++)
1080         v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
1081      for (i=0; i<=gmask; i++)
1082         v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
1083      for (i=0; i<=bmask; i++)
1084         v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
1085
1086      /* convert RGB values from [0,255] to pixel components */
1087
1088      for (i=0;i<256;i++) {
1089         GLint r = gamma_adjust(v->RedGamma,   i, 255);
1090         GLint g = gamma_adjust(v->GreenGamma, i, 255);
1091         GLint b = gamma_adjust(v->BlueGamma,  i, 255);
1092         v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
1093         v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
1094         v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
1095      }
1096      /* overflow protection */
1097      for (i=256;i<512;i++) {
1098         v->RtoPixel[i] = v->RtoPixel[255];
1099         v->GtoPixel[i] = v->GtoPixel[255];
1100         v->BtoPixel[i] = v->BtoPixel[255];
1101      }
1102
1103      /* setup dithering kernel */
1104      maxBits = rBits;
1105      if (gBits > maxBits)  maxBits = gBits;
1106      if (bBits > maxBits)  maxBits = bBits;
1107      for (i=0;i<16;i++) {
1108         v->Kernel[i] = kernel[i] >> maxBits;
1109      }
1110
1111      v->undithered_pf = PF_TRUECOLOR;
1112      v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_TRUEDITHER : PF_TRUECOLOR;
1113   }
1114
1115   /*
1116    * Now check for TrueColor visuals which we can optimize.
1117    */
1118   if (   GET_REDMASK(v)  ==0x0000ff
1119       && GET_GREENMASK(v)==0x00ff00
1120       && GET_BLUEMASK(v) ==0xff0000
1121       && CHECK_BYTE_ORDER(v)
1122       && v->BitsPerPixel==32
1123       && sizeof(GLuint)==4
1124       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1125      /* common 32 bpp config used on SGI, Sun */
1126      v->undithered_pf = v->dithered_pf = PF_8A8B8G8R;
1127   }
1128   else if (GET_REDMASK(v)  ==0xff0000
1129       &&   GET_GREENMASK(v)==0x00ff00
1130       &&   GET_BLUEMASK(v) ==0x0000ff
1131       && CHECK_BYTE_ORDER(v)
1132       && v->BitsPerPixel==32
1133       && sizeof(GLuint)==4
1134       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1135      /* common 32 bpp config used on Linux, HP, IBM */
1136      v->undithered_pf = v->dithered_pf = PF_8R8G8B;
1137   }
1138   else if (GET_REDMASK(v)  ==0xff0000
1139       &&   GET_GREENMASK(v)==0x00ff00
1140       &&   GET_BLUEMASK(v) ==0x0000ff
1141       && CHECK_BYTE_ORDER(v)
1142       && v->BitsPerPixel==24
1143       && sizeof(GLuint)==4
1144       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1145      /* common packed 24 bpp config used on Linux */
1146      v->undithered_pf = v->dithered_pf = PF_8R8G8B24;
1147   }
1148   else if (GET_REDMASK(v)  ==0xf800
1149       &&   GET_GREENMASK(v)==0x07e0
1150       &&   GET_BLUEMASK(v) ==0x001f
1151       && CHECK_BYTE_ORDER(v)
1152       && v->BitsPerPixel==16
1153       && sizeof(GLushort)==2
1154       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
1155      /* 5-6-5 color weight on common PC VGA boards */
1156      v->undithered_pf = PF_5R6G5B;
1157      v->dithered_pf = PF_DITHER_5R6G5B;
1158   }
1159   else if (GET_REDMASK(v)  ==0xe0
1160       &&   GET_GREENMASK(v)==0x1c
1161       &&   GET_BLUEMASK(v) ==0x03
1162       && CHECK_FOR_HPCR(v)) {
1163      setup_8bit_hpcr( v );
1164   }
1165}
1166
1167
1168
1169/*
1170 * Setup RGB rendering for a window with a monochrome visual.
1171 */
1172static void setup_monochrome( XMesaVisual v, XMesaBuffer b )
1173{
1174   (void) b;
1175   v->dithered_pf = v->undithered_pf = PF_1BIT;
1176   /* if black=1 then we must flip pixel values */
1177   v->bitFlip = (GET_BLACK_PIXEL(v) != 0);
1178}
1179
1180
1181
1182/*
1183 * When a context is "made current" for the first time, we can finally
1184 * finish initializing the context's visual and buffer information.
1185 * Input:  v - the XMesaVisual to initialize
1186 *         b - the XMesaBuffer to initialize (may be NULL)
1187 *         rgb_flag - TRUE = RGBA mode, FALSE = color index mode
1188 *         window - the window/pixmap we're rendering into
1189 *         cmap - the colormap associated with the window/pixmap
1190 * Return:  GL_TRUE=success, GL_FALSE=failure
1191 */
1192static GLboolean initialize_visual_and_buffer( int client,
1193                                               XMesaVisual v,
1194                                               XMesaBuffer b,
1195                                               GLboolean rgb_flag,
1196                                               XMesaDrawable window,
1197                                               XMesaColormap cmap
1198                                             )
1199{
1200#ifndef XFree86Server
1201   XGCValues gcvalues;
1202#endif
1203
1204   if (b) {
1205      assert(b->xm_visual == v);
1206   }
1207
1208   /* Save true bits/pixel */
1209   v->BitsPerPixel = GET_BITS_PER_PIXEL(v);
1210   assert(v->BitsPerPixel > 0);
1211
1212
1213   if (rgb_flag==GL_FALSE) {
1214      /* COLOR-INDEXED WINDOW:
1215       * Even if the visual is TrueColor or DirectColor we treat it as
1216       * being color indexed.  This is weird but might be useful to someone.
1217       */
1218      v->dithered_pf = v->undithered_pf = PF_INDEX;
1219      v->index_bits = GET_VISUAL_DEPTH(v);
1220   }
1221   else {
1222      /* RGB WINDOW:
1223       * We support RGB rendering into almost any kind of visual.
1224       */
1225      int xclass;
1226      xclass = GET_VISUAL_CLASS(v);
1227      if (xclass==TrueColor || xclass==DirectColor) {
1228	 setup_truecolor( v, b, (XMesaWindow)window, cmap );
1229      }
1230      else if (xclass==StaticGray && GET_VISUAL_DEPTH(v)==1) {
1231	 setup_monochrome( v, b );
1232      }
1233      else if (xclass==GrayScale || xclass==StaticGray) {
1234         if (!setup_grayscale( client, v, b, cmap )) {
1235            return GL_FALSE;
1236         }
1237      }
1238      else if ((xclass==PseudoColor || xclass==StaticColor)
1239               && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
1240	 if (!setup_dithered_color( client, v, b, cmap )) {
1241            return GL_FALSE;
1242         }
1243      }
1244      else {
1245	 error("XMesa: RGB mode rendering not supported in given visual.");
1246	 return GL_FALSE;
1247      }
1248      v->index_bits = 0;
1249
1250      if (getenv("MESA_NO_DITHER")) {
1251	 v->dithered_pf = v->undithered_pf;
1252      }
1253   }
1254
1255
1256   /*
1257    * If MESA_INFO env var is set print out some debugging info
1258    * which can help Brian figure out what's going on when a user
1259    * reports bugs.
1260    */
1261   if (getenv("MESA_INFO")) {
1262      fprintf(stderr, "X/Mesa visual = %p\n", v);
1263      fprintf(stderr, "X/Mesa dithered pf = %u\n", v->dithered_pf);
1264      fprintf(stderr, "X/Mesa undithered pf = %u\n", v->undithered_pf);
1265      fprintf(stderr, "X/Mesa level = %d\n", v->level);
1266      fprintf(stderr, "X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
1267      fprintf(stderr, "X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
1268   }
1269
1270   if (b && window) {
1271      /* Do window-specific initializations */
1272
1273      /* Window dimensions */
1274      unsigned int w, h;
1275      get_drawable_size( v->display, window, &w, &h );
1276      b->width = w;
1277      b->height = h;
1278
1279      b->frontbuffer = window;
1280
1281      /* Setup for single/double buffering */
1282      if (v->mesa_visual.doubleBufferMode) {
1283         /* Double buffered */
1284#ifndef XFree86Server
1285         b->shm = check_for_xshm( v->display );
1286#endif
1287         xmesa_alloc_back_buffer( b );
1288         if (b->db_state==BACK_PIXMAP) {
1289            b->buffer = (XMesaDrawable)b->backpixmap;
1290         }
1291         else {
1292            b->buffer = XIMAGE;
1293         }
1294      }
1295      else {
1296         /* Single Buffered */
1297         b->buffer = b->frontbuffer;
1298      }
1299
1300      /* X11 graphics contexts */
1301#ifdef XFree86Server
1302      b->gc = CreateScratchGC(v->display, window->depth);
1303#else
1304      b->gc = XCreateGC( v->display, window, 0, NULL );
1305#endif
1306      XMesaSetFunction( v->display, b->gc, GXcopy );
1307
1308      /*
1309       * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1310       * Patch contributed by Michael Pichler May 15, 1995.
1311       */
1312#ifdef XFree86Server
1313      b->cleargc = CreateScratchGC(v->display, window->depth);
1314      {
1315	  CARD32 v[1];
1316	  v[0] = FALSE;
1317	  dixChangeGC(NullClient, b->cleargc, GCGraphicsExposures, v, NULL);
1318      }
1319#else
1320      gcvalues.graphics_exposures = False;
1321      b->cleargc = XCreateGC( v->display, window,
1322                              GCGraphicsExposures, &gcvalues);
1323#endif
1324      XMesaSetFunction( v->display, b->cleargc, GXcopy );
1325      /*
1326       * Set fill style and tile pixmap once for all for HPCR stuff
1327       * (instead of doing it each time in clear_color_HPCR_pixmap())
1328       * Initialize whole stuff
1329       * Patch contributed by Jacques Leroy March 8, 1998.
1330       */
1331      if (v->hpcr_clear_flag && b->buffer!=XIMAGE) {
1332	int i;
1333	for (i=0; i<16; i++)
1334        {
1335	   XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0);
1336	   XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0);
1337        }
1338        XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap,
1339		      b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
1340	XMesaSetFillStyle( v->display, b->cleargc, FillTiled);
1341	XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap );
1342      }
1343
1344      /* Initialize the row buffer XImage for use in write_color_span() */
1345#ifdef XFree86Server
1346      b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1,
1347				     (char *)MALLOC(MAX_WIDTH*4));
1348#else
1349      b->rowimage = XCreateImage( v->display,
1350                                  v->visinfo->visual,
1351                                  v->visinfo->depth,
1352                                  ZPixmap, 0,           /*format, offset*/
1353                                  (char*) MALLOC(MAX_WIDTH*4),  /*data*/
1354                                  MAX_WIDTH, 1,         /*width, height*/
1355                                  32,                   /*bitmap_pad*/
1356                                  0                     /*bytes_per_line*/ );
1357#endif
1358   }
1359
1360   return GL_TRUE;
1361}
1362
1363
1364
1365/*
1366 * Convert an RGBA color to a pixel value.
1367 */
1368unsigned long
1369xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a,
1370                      GLuint pixelFormat)
1371{
1372   switch (pixelFormat) {
1373      case PF_INDEX:
1374         return 0;
1375      case PF_TRUECOLOR:
1376         {
1377            unsigned long p;
1378            PACK_TRUECOLOR( p, r, g, b );
1379            return p;
1380         }
1381      case PF_8A8B8G8R:
1382         return PACK_8A8B8G8R( r, g, b, a );
1383      case PF_8R8G8B:
1384         /* fall through */
1385      case PF_8R8G8B24:
1386         return PACK_8R8G8B( r, g, b );
1387      case PF_5R6G5B:
1388         return PACK_5R6G5B( r, g, b );
1389      case PF_DITHER:
1390         {
1391            DITHER_SETUP;
1392            return DITHER( 1, 0, r, g, b );
1393         }
1394      case PF_1BIT:
1395         /* 382 = (3*255)/2 */
1396         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
1397      case PF_HPCR:
1398         return DITHER_HPCR(1, 1, r, g, b);
1399      case PF_LOOKUP:
1400         {
1401            LOOKUP_SETUP;
1402            return LOOKUP( r, g, b );
1403         }
1404      case PF_GRAYSCALE:
1405         return GRAY_RGB( r, g, b );
1406      case PF_TRUEDITHER:
1407         /* fall through */
1408      case PF_DITHER_5R6G5B:
1409         {
1410            unsigned long p;
1411            PACK_TRUEDITHER(p, 1, 0, r, g, b);
1412            return p;
1413         }
1414      default:
1415         _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel");
1416   }
1417   return 0;
1418}
1419
1420
1421/**********************************************************************/
1422/*****                       Public Functions                     *****/
1423/**********************************************************************/
1424
1425
1426/*
1427 * Create a new X/Mesa visual.
1428 * Input:  display - X11 display
1429 *         visinfo - an XVisualInfo pointer
1430 *         rgb_flag - GL_TRUE = RGB mode,
1431 *                    GL_FALSE = color index mode
1432 *         alpha_flag - alpha buffer requested?
1433 *         db_flag - GL_TRUE = double-buffered,
1434 *                   GL_FALSE = single buffered
1435 *         stereo_flag - stereo visual?
1436 *         ximage_flag - GL_TRUE = use an XImage for back buffer,
1437 *                       GL_FALSE = use an off-screen pixmap for back buffer
1438 *         depth_size - requested bits/depth values, or zero
1439 *         stencil_size - requested bits/stencil values, or zero
1440 *         accum_red_size - requested bits/red accum values, or zero
1441 *         accum_green_size - requested bits/green accum values, or zero
1442 *         accum_blue_size - requested bits/blue accum values, or zero
1443 *         accum_alpha_size - requested bits/alpha accum values, or zero
1444 *         num_samples - number of samples/pixel if multisampling, or zero
1445 *         level - visual level, usually 0
1446 *         visualCaveat - ala the GLX extension, usually GLX_NONE_EXT
1447 * Return;  a new XMesaVisual or 0 if error.
1448 */
1449XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
1450                               XMesaVisualInfo visinfo,
1451                               GLboolean rgb_flag,
1452                               GLboolean alpha_flag,
1453                               GLboolean db_flag,
1454                               GLboolean stereo_flag,
1455                               GLboolean ximage_flag,
1456                               GLint depth_size,
1457                               GLint stencil_size,
1458                               GLint accum_red_size,
1459                               GLint accum_green_size,
1460                               GLint accum_blue_size,
1461                               GLint accum_alpha_size,
1462                               GLint num_samples,
1463                               GLint level,
1464                               GLint visualCaveat )
1465{
1466   char *gamma;
1467   XMesaVisual v;
1468   GLint red_bits, green_bits, blue_bits, alpha_bits;
1469
1470   /* For debugging only */
1471   if (getenv("MESA_XSYNC")) {
1472      /* This makes debugging X easier.
1473       * In your debugger, set a breakpoint on _XError to stop when an
1474       * X protocol error is generated.
1475       */
1476#ifdef XFree86Server
1477      /* NOT_NEEDED */
1478#else
1479      XSynchronize( display, 1 );
1480#endif
1481   }
1482
1483   v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
1484   if (!v) {
1485      return NULL;
1486   }
1487
1488   /*
1489    * In the X server, NULL is passed in for the display.  It will have
1490    * to be set before using this visual.  See XMesaSetVisualDisplay()
1491    * below.
1492    */
1493   v->display = display;
1494
1495   /* Save a copy of the XVisualInfo struct because the user may XFREE()
1496    * the struct but we may need some of the information contained in it
1497    * at a later time.
1498    */
1499#ifdef XFree86Server
1500   v->visinfo = visinfo;
1501#else
1502   v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
1503   if(!v->visinfo) {
1504      FREE(v);
1505      return NULL;
1506   }
1507   MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
1508
1509   /* Save a copy of the pointer now so we can find this visual again
1510    * if we need to search for it in find_glx_visual().
1511    */
1512   v->vishandle = visinfo;
1513#endif
1514
1515#ifdef XFree86Server
1516   /* Initialize the depth of the screen */
1517   {
1518       PixmapFormatRec *format;
1519
1520       for (format = screenInfo.formats;
1521	    format->depth != display->rootDepth;
1522	    format++)
1523	   ;
1524       v->screen_depth = format->bitsPerPixel;
1525   }
1526#endif
1527
1528   /* check for MESA_GAMMA environment variable */
1529   gamma = getenv("MESA_GAMMA");
1530   if (gamma) {
1531      v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
1532      sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
1533      if (v->RedGamma<=0.0)    v->RedGamma = 1.0;
1534      if (v->GreenGamma<=0.0)  v->GreenGamma = v->RedGamma;
1535      if (v->BlueGamma<=0.0)   v->BlueGamma = v->RedGamma;
1536   }
1537   else {
1538      v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
1539   }
1540
1541   v->ximage_flag = ximage_flag;
1542   v->level = level;
1543   v->VisualCaveat = visualCaveat;
1544
1545   (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 );
1546
1547   {
1548      int xclass;
1549      xclass = GET_VISUAL_CLASS(v);
1550      if (xclass==TrueColor || xclass==DirectColor) {
1551         red_bits   = bitcount(GET_REDMASK(v));
1552         green_bits = bitcount(GET_GREENMASK(v));
1553         blue_bits  = bitcount(GET_BLUEMASK(v));
1554         alpha_bits = 0;
1555      }
1556      else {
1557         /* this is an approximation */
1558         int depth;
1559         depth = GET_VISUAL_DEPTH(v);
1560         red_bits = depth / 3;
1561         depth -= red_bits;
1562         green_bits = depth / 2;
1563         depth -= green_bits;
1564         blue_bits = depth;
1565         alpha_bits = 0;
1566         assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
1567      }
1568   }
1569
1570   if (alpha_flag && alpha_bits == 0)
1571      alpha_bits = 8;
1572
1573   _mesa_initialize_visual( &v->mesa_visual,
1574                            rgb_flag, db_flag, stereo_flag,
1575                            red_bits, green_bits,
1576                            blue_bits, alpha_bits,
1577                            v->index_bits,
1578                            depth_size,
1579                            stencil_size,
1580                            accum_red_size, accum_green_size,
1581                            accum_blue_size, accum_alpha_size,
1582                            0 );
1583   return v;
1584}
1585
1586
1587void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v )
1588{
1589    v->display = dpy;
1590}
1591
1592
1593void XMesaDestroyVisual( XMesaVisual v )
1594{
1595#ifndef XFree86Server
1596   FREE(v->visinfo);
1597#endif
1598   FREE(v);
1599}
1600
1601
1602
1603/*
1604 * Create a new XMesaContext.
1605 * Input:  v - XMesaVisual
1606 *         share_list - another XMesaContext with which to share display
1607 *                      lists or NULL if no sharing is wanted.
1608 * Return:  an XMesaContext or NULL if error.
1609 */
1610XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
1611{
1612   XMesaContext c;
1613   GLcontext *ctx;
1614   GLboolean direct = GL_TRUE; /* XXXX */
1615   /* NOT_DONE: should this be GL_FALSE??? */
1616   static GLboolean firstTime = GL_TRUE;
1617
1618   if (firstTime) {
1619      _glthread_INIT_MUTEX(_xmesa_lock);
1620      firstTime = GL_FALSE;
1621   }
1622
1623   c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
1624   if (!c) {
1625      return NULL;
1626   }
1627
1628   ctx = c->gl_ctx = _mesa_create_context( &v->mesa_visual,
1629                      share_list ? share_list->gl_ctx : (GLcontext *) NULL,
1630                      (void *) c, direct );
1631   if (!c->gl_ctx) {
1632      FREE(c);
1633      return NULL;
1634   }
1635
1636   _mesa_enable_sw_extensions(ctx);
1637
1638   if (CHECK_BYTE_ORDER(v)) {
1639      c->swapbytes = GL_FALSE;
1640   }
1641   else {
1642      c->swapbytes = GL_TRUE;
1643   }
1644
1645   c->xm_visual = v;
1646   c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
1647   c->display = v->display;
1648   c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
1649
1650   ctx->Driver.UpdateState = xmesa_update_state;
1651
1652#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1653   c->driContextPriv = driContextPriv;
1654#endif
1655
1656   /* Initialize the software rasterizer and helper modules.
1657    */
1658   _swrast_CreateContext( ctx );
1659   _ac_CreateContext( ctx );
1660   _tnl_CreateContext( ctx );
1661   _swsetup_CreateContext( ctx );
1662
1663   xmesa_register_swrast_functions( ctx );
1664
1665   /* Set up some constant pointers:
1666    */
1667   xmesa_init_pointers( ctx );
1668
1669
1670   /* Run the config file
1671    */
1672   _mesa_context_initialize( ctx );
1673
1674
1675   return c;
1676}
1677
1678
1679
1680
1681void XMesaDestroyContext( XMesaContext c )
1682{
1683#ifdef FX
1684   if (c->xm_buffer && c->xm_buffer->FXctx)
1685      fxMesaDestroyContext(c->xm_buffer->FXctx);
1686#endif
1687   if (c->gl_ctx) {
1688      _swsetup_DestroyContext( c->gl_ctx );
1689      _swrast_DestroyContext( c->gl_ctx );
1690      _tnl_DestroyContext( c->gl_ctx );
1691      _ac_DestroyContext( c->gl_ctx );
1692      _mesa_destroy_context( c->gl_ctx );
1693   }
1694
1695   /* Disassociate old buffer with this context */
1696   if (c->xm_buffer)
1697       c->xm_buffer->xm_context = NULL;
1698
1699   /* Destroy any buffers which are using this context.  If we don't
1700    * we may have dangling references.  Hmm, maybe we should just
1701    * set the buffer's context pointer to NULL instead of deleting it?
1702    * Let's see if we get any bug reports...
1703    * This contributed by Doug Rabson <dfr@calcaphon.com>
1704    */
1705   {
1706      XMesaBuffer b, next;
1707      for (b = XMesaBufferList; b; b = next) {
1708         next = b->Next;
1709         if (!b->pixmap_flag) {
1710#ifndef XFree86Server
1711            XSync(b->display, False);
1712#endif
1713            if (b->xm_context == c) {
1714               /* found a context created for this context */
1715               XMesaDestroyBuffer( b );
1716            }
1717         }
1718      }
1719   }
1720
1721   FREE( c );
1722}
1723
1724
1725
1726/*
1727 * XXX this isn't a public function!  It's a hack for the 3Dfx driver.
1728 * Create a new XMesaBuffer from an X window.
1729 * Input:  v - the XMesaVisual
1730 *         w - the window
1731 *         c - the context
1732 * Return:  new XMesaBuffer or NULL if error
1733 */
1734XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w,
1735                                      XMesaContext c )
1736{
1737#ifndef XFree86Server
1738   XWindowAttributes attr;
1739#endif
1740#ifdef FX
1741   char *fxEnvVar;
1742#endif
1743   int client = 0;
1744
1745   XMesaBuffer b = alloc_xmesa_buffer();
1746   if (!b) {
1747      return NULL;
1748   }
1749
1750   (void) c;
1751
1752#ifdef XFree86Server
1753   client = CLIENT_ID(((XMesaDrawable)w)->id);
1754#endif
1755
1756   assert(v);
1757
1758#ifdef XFree86Server
1759   if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
1760#else
1761   XGetWindowAttributes( v->display, w, &attr );
1762
1763   if (GET_VISUAL_DEPTH(v) != attr.depth) {
1764#endif
1765      if (getenv("MESA_DEBUG")) {
1766         fprintf(stderr, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n");
1767      }
1768      return NULL;
1769   }
1770
1771   b->xm_context = NULL; /* Associate no context with this buffer */
1772
1773   b->xm_visual = v;
1774   b->pixmap_flag = GL_FALSE;
1775   b->display = v->display;
1776#ifdef XFree86Server
1777   b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1778#else
1779   if (attr.colormap) {
1780      b->cmap = attr.colormap;
1781   }
1782   else {
1783      if (getenv("MESA_DEBUG")) {
1784         fprintf(stderr, "Window %u has no colormap!\n", (unsigned int) w);
1785      }
1786      /* this is weird, a window w/out a colormap!? */
1787      /* OK, let's just allocate a new one and hope for the best */
1788      b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1789   }
1790#endif
1791
1792   /* determine back buffer implementation */
1793   if (v->mesa_visual.doubleBufferMode) {
1794      if (v->ximage_flag) {
1795	 b->db_state = BACK_XIMAGE;
1796      }
1797      else {
1798	 b->db_state = BACK_PIXMAP;
1799      }
1800   }
1801   else {
1802      b->db_state = 0;
1803   }
1804
1805   _mesa_initialize_framebuffer(&b->mesa_buffer,
1806                                &v->mesa_visual,
1807                                v->mesa_visual.depthBits > 0,
1808                                v->mesa_visual.stencilBits > 0,
1809                                v->mesa_visual.accumRedBits > 0,
1810                                v->mesa_visual.alphaBits > 0 );
1811
1812   if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
1813                                      (XMesaDrawable)w, b->cmap )) {
1814      free_xmesa_buffer(client, b);
1815      return NULL;
1816   }
1817
1818#ifdef FX
1819   fxEnvVar = getenv("MESA_GLX_FX");
1820   if (fxEnvVar) {
1821     if (fxEnvVar[0]!='d') {
1822       int attribs[100];
1823       int numAttribs = 0;
1824       int hw;
1825       if (v->mesa_visual.depthBits > 0) {
1826	 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
1827	 attribs[numAttribs++] = 1;
1828       }
1829       if (v->mesa_visual.doubleBufferMode) {
1830	 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
1831       }
1832       if (v->mesa_visual.accumRedBits > 0) {
1833	 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
1834	 attribs[numAttribs++] = v->mesa_visual.accumRedBits;
1835       }
1836       if (v->mesa_visual.stencilBits > 0) {
1837         attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
1838         attribs[numAttribs++] = v->mesa_visual.stencilBits;
1839       }
1840       if (v->mesa_visual.alphaBits > 0) {
1841         attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
1842         attribs[numAttribs++] = 1;
1843       }
1844       if (c->gl_ctx) {
1845#define FXMESA_SHARE_CONTEXT 990099  /* keep in sync with fxapi.c! */
1846         attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
1847         attribs[numAttribs++] = (int) c->gl_ctx;
1848       }
1849       attribs[numAttribs++] = FXMESA_NONE;
1850
1851       if ((hw = fxQueryHardware())==GR_SSTTYPE_VOODOO) {
1852         b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
1853         if ((v->undithered_pf!=PF_INDEX) && (b->backimage)) {
1854	   b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
1855	   if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1856	     b->FXwindowHack = b->FXctx ? GL_TRUE : GL_FALSE;
1857	   else
1858	     b->FXwindowHack = GL_FALSE;
1859         }
1860       }
1861       else {
1862         if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
1863	   b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
1864					  GR_REFRESH_75Hz, attribs);
1865         else
1866	   b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
1867         b->FXisHackUsable = GL_FALSE;
1868         b->FXwindowHack = GL_FALSE;
1869       }
1870       /*
1871       fprintf(stderr,
1872               "voodoo %d, wid %d height %d hack: usable %d active %d\n",
1873               hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
1874       */
1875     }
1876   }
1877   else {
1878      fprintf(stderr,"WARNING: This Mesa Library includes the Glide driver but\n");
1879      fprintf(stderr,"         you have not defined the MESA_GLX_FX env. var.\n");
1880      fprintf(stderr,"         (check the README.3DFX file for more information).\n\n");
1881      fprintf(stderr,"         you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
1882   }
1883#endif
1884
1885#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1886   b->driDrawPriv = driDrawPriv;
1887#endif
1888
1889   return b;
1890}
1891
1892
1893XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w )
1894{
1895   return XMesaCreateWindowBuffer2( v, w, NULL );
1896}
1897
1898
1899/*
1900 * Create a new XMesaBuffer from an X pixmap.
1901 * Input:  v - the XMesaVisual
1902 *         p - the pixmap
1903 *         cmap - the colormap, may be 0 if using a TrueColor or DirectColor
1904 *                visual for the pixmap
1905 * Return:  new XMesaBuffer or NULL if error
1906 */
1907XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v,
1908				     XMesaPixmap p, XMesaColormap cmap )
1909{
1910   int client = 0;
1911   XMesaBuffer b = alloc_xmesa_buffer();
1912   if (!b) {
1913      return NULL;
1914   }
1915
1916
1917#ifdef XFree86Server
1918   client = CLIENT_ID(((XMesaDrawable)p)->id);
1919#endif
1920
1921   assert(v);
1922
1923   b->xm_context = NULL; /* Associate no context with this buffer */
1924
1925   b->xm_visual = v;
1926   b->pixmap_flag = GL_TRUE;
1927   b->display = v->display;
1928   b->cmap = cmap;
1929
1930   /* determine back buffer implementation */
1931   if (v->mesa_visual.doubleBufferMode) {
1932      if (v->ximage_flag) {
1933	 b->db_state = BACK_XIMAGE;
1934      }
1935      else {
1936	 b->db_state = BACK_PIXMAP;
1937      }
1938   }
1939   else {
1940      b->db_state = 0;
1941   }
1942
1943   _mesa_initialize_framebuffer(&b->mesa_buffer,
1944                                &v->mesa_visual,
1945                                v->mesa_visual.depthBits > 0,
1946                                v->mesa_visual.stencilBits > 0,
1947                                v->mesa_visual.accumRedBits +
1948                                v->mesa_visual.accumGreenBits +
1949                                v->mesa_visual.accumBlueBits > 0,
1950                                v->mesa_visual.alphaBits > 0 );
1951
1952   if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
1953				     (XMesaDrawable)p, cmap)) {
1954      free_xmesa_buffer(client, b);
1955      return NULL;
1956   }
1957
1958#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
1959   b->driDrawPriv = driDrawPriv;
1960#endif
1961
1962   return b;
1963}
1964
1965
1966
1967/*
1968 * Deallocate an XMesaBuffer structure and all related info.
1969 */
1970void XMesaDestroyBuffer( XMesaBuffer b )
1971{
1972   int client = 0;
1973
1974#ifdef XFree86Server
1975   if (b->frontbuffer)
1976       client = CLIENT_ID(b->frontbuffer->id);
1977#endif
1978
1979   if (b->gc)  XMesaFreeGC( b->xm_visual->display, b->gc );
1980   if (b->cleargc)  XMesaFreeGC( b->xm_visual->display, b->cleargc );
1981
1982   if (b->backimage) {
1983#if defined(USE_XSHM) && !defined(XFree86Server)
1984       if (b->shm) {
1985	   XShmDetach( b->xm_visual->display, &b->shminfo );
1986	   XDestroyImage( b->backimage );
1987	   shmdt( b->shminfo.shmaddr );
1988       }
1989       else
1990#endif
1991	   XMesaDestroyImage( b->backimage );
1992   }
1993   if (b->backpixmap) {
1994      XMesaFreePixmap( b->xm_visual->display, b->backpixmap );
1995      if (b->xm_visual->hpcr_clear_flag) {
1996	XMesaFreePixmap( b->xm_visual->display,
1997			 b->xm_visual->hpcr_clear_pixmap );
1998	XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
1999      }
2000   }
2001   if (b->rowimage) {
2002      FREE( b->rowimage->data );
2003      b->rowimage->data = NULL;
2004      XMesaDestroyImage( b->rowimage );
2005   }
2006
2007   if (b->xm_context)
2008       b->xm_context->xm_buffer = NULL;
2009
2010   free_xmesa_buffer(client, b);
2011}
2012
2013
2014
2015/*
2016 * Bind buffer b to context c and make c the current rendering context.
2017 */
2018GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
2019{
2020   return XMesaMakeCurrent2( c, b, b );
2021}
2022
2023
2024/*
2025 * Bind buffer b to context c and make c the current rendering context.
2026 */
2027GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
2028                             XMesaBuffer readBuffer )
2029{
2030   if (c) {
2031      if (!drawBuffer || !readBuffer)
2032         return GL_FALSE;  /* must specify buffers! */
2033
2034#ifdef FX
2035      if (drawBuffer->FXctx) {
2036         fxMesaMakeCurrent(drawBuffer->FXctx);
2037
2038         /* Disassociate old buffer from this context */
2039         if (c->xm_buffer)
2040            c->xm_buffer->xm_context = NULL;
2041
2042         /* Associate the context with this buffer */
2043         drawBuffer->xm_context = c;
2044
2045         c->xm_buffer = drawBuffer;
2046         c->xm_read_buffer = readBuffer;
2047         c->use_read_buffer = (drawBuffer != readBuffer);
2048
2049         return GL_TRUE;
2050      }
2051#endif
2052      if (c->gl_ctx == _mesa_get_current_context()
2053          && c->xm_buffer == drawBuffer
2054          && c->xm_read_buffer == readBuffer
2055          && c->xm_buffer->wasCurrent) {
2056         /* same context and buffer, do nothing */
2057         return GL_TRUE;
2058      }
2059
2060      /* Disassociate old buffer with this context */
2061      if (c->xm_buffer)
2062	  c->xm_buffer->xm_context = NULL;
2063      drawBuffer->xm_context = c; /* Associate the context with this buffer */
2064
2065      c->xm_buffer = drawBuffer;
2066      c->xm_read_buffer = readBuffer;
2067      c->use_read_buffer = (drawBuffer != readBuffer);
2068
2069      _mesa_make_current2(c->gl_ctx,
2070                          &drawBuffer->mesa_buffer,
2071                          &readBuffer->mesa_buffer);
2072
2073      if (c->gl_ctx->Viewport.Width == 0) {
2074	 /* initialize viewport to window size */
2075	 _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height );
2076	 c->gl_ctx->Scissor.Width = drawBuffer->width;
2077	 c->gl_ctx->Scissor.Height = drawBuffer->height;
2078      }
2079
2080      if (c->xm_visual->mesa_visual.rgbMode) {
2081         /*
2082          * Must recompute and set these pixel values because colormap
2083          * can be different for different windows.
2084          */
2085         c->clearpixel = xmesa_color_to_pixel( c,
2086                                               c->clearcolor[0],
2087                                               c->clearcolor[1],
2088                                               c->clearcolor[2],
2089                                               c->clearcolor[3],
2090                                               c->xm_visual->undithered_pf);
2091         XMesaSetForeground(c->display, c->xm_buffer->cleargc, c->clearpixel);
2092      }
2093
2094      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
2095      c->xm_buffer->wasCurrent = GL_TRUE;
2096   }
2097   else {
2098      /* Detach */
2099      _mesa_make_current2( NULL, NULL, NULL );
2100   }
2101   return GL_TRUE;
2102}
2103
2104
2105/*
2106 * Unbind the context c from its buffer.
2107 */
2108GLboolean XMesaUnbindContext( XMesaContext c )
2109{
2110   /* A no-op for XFree86 integration purposes */
2111   return GL_TRUE;
2112}
2113
2114
2115XMesaContext XMesaGetCurrentContext( void )
2116{
2117   GET_CURRENT_CONTEXT(ctx);
2118   if (ctx) {
2119      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2120      return xmesa;
2121   }
2122   else {
2123      return 0;
2124   }
2125}
2126
2127
2128XMesaBuffer XMesaGetCurrentBuffer( void )
2129{
2130   GET_CURRENT_CONTEXT(ctx);
2131   if (ctx) {
2132      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2133      return xmesa->xm_buffer;
2134   }
2135   else {
2136      return 0;
2137   }
2138}
2139
2140
2141/* New in Mesa 3.1 */
2142XMesaBuffer XMesaGetCurrentReadBuffer( void )
2143{
2144   GET_CURRENT_CONTEXT(ctx);
2145   if (ctx) {
2146      XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2147      return xmesa->xm_buffer;
2148   }
2149   else {
2150      return 0;
2151   }
2152}
2153
2154
2155GLboolean XMesaForceCurrent(XMesaContext c)
2156{
2157   if (c) {
2158      if (c->gl_ctx != _mesa_get_current_context()) {
2159	 _mesa_make_current(c->gl_ctx, &c->xm_buffer->mesa_buffer);
2160      }
2161   }
2162   else {
2163      _mesa_make_current(NULL, NULL);
2164   }
2165   return GL_TRUE;
2166}
2167
2168
2169GLboolean XMesaLoseCurrent(XMesaContext c)
2170{
2171   (void) c;
2172   _mesa_make_current(NULL, NULL);
2173   return GL_TRUE;
2174}
2175
2176
2177/*
2178 * Switch 3Dfx support hack between window and full-screen mode.
2179 */
2180GLboolean XMesaSetFXmode( GLint mode )
2181{
2182#ifdef FX
2183   const char *fx = getenv("MESA_GLX_FX");
2184   if (fx && fx[0] != 'd') {
2185      GET_CURRENT_CONTEXT(ctx);
2186      GrHwConfiguration hw;
2187      if (!FX_grSstQueryHardware(&hw)) {
2188         /*fprintf(stderr, "!grSstQueryHardware\n");*/
2189         return GL_FALSE;
2190      }
2191      if (hw.num_sst < 1) {
2192         /*fprintf(stderr, "hw.num_sst < 1\n");*/
2193         return GL_FALSE;
2194      }
2195      if (ctx) {
2196         XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
2197         if (mode == XMESA_FX_WINDOW) {
2198	    if (xmesa->xm_buffer->FXisHackUsable) {
2199	       FX_grSstControl(GR_CONTROL_DEACTIVATE);
2200	       xmesa->xm_buffer->FXwindowHack = GL_TRUE;
2201	       return GL_TRUE;
2202	    }
2203	 }
2204	 else if (mode == XMESA_FX_FULLSCREEN) {
2205	    FX_grSstControl(GR_CONTROL_ACTIVATE);
2206	    xmesa->xm_buffer->FXwindowHack = GL_FALSE;
2207	    return GL_TRUE;
2208	 }
2209	 else {
2210	    /* Error: Bad mode value */
2211	 }
2212      }
2213   }
2214   /*fprintf(stderr, "fallthrough\n");*/
2215#else
2216   (void) mode;
2217#endif
2218   return GL_FALSE;
2219}
2220
2221
2222
2223#ifdef FX
2224/*
2225 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
2226 */
2227static void FXgetImage( XMesaBuffer b )
2228{
2229   static unsigned short pixbuf[MAX_WIDTH];
2230   GLuint x, y;
2231   int xpos, ypos;
2232   XMesaWindow root;
2233   unsigned int bw, depth, width, height;
2234   XMesaContext xmesa = (XMesaContext) b->xm_context->gl_ctx->DriverCtx;
2235
2236   assert(xmesa->xm_buffer->FXctx);
2237
2238#ifdef XFree86Server
2239   x = b->frontbuffer->x;
2240   y = b->frontbuffer->y;
2241   width = b->frontbuffer->width;
2242   height = b->frontbuffer->height;
2243   depth = b->frontbuffer->depth;
2244#else
2245   XGetGeometry( xmesa->xm_visual->display, b->frontbuffer,
2246                 &root, &xpos, &ypos, &width, &height, &bw, &depth);
2247#endif
2248   if (b->width != width || b->height != height) {
2249      b->width = MIN2((int)width, xmesa->xm_buffer->FXctx->width);
2250      b->height = MIN2((int)height, xmesa->xm_buffer->FXctx->height);
2251      if (b->width & 1)
2252         b->width--;  /* prevent odd width */
2253      xmesa_alloc_back_buffer( b );
2254   }
2255
2256   grLfbWriteColorFormat(GR_COLORFORMAT_ARGB);
2257   if (xmesa->xm_visual->undithered_pf==PF_5R6G5B) {
2258      /* Special case: 16bpp RGB */
2259      grLfbReadRegion( GR_BUFFER_FRONTBUFFER,       /* src buffer */
2260                       0, xmesa->xm_buffer->FXctx->height - b->height,  /*pos*/
2261                       b->width, b->height,         /* size */
2262                       b->width * sizeof(GLushort), /* stride */
2263                       b->backimage->data);         /* dest buffer */
2264   }
2265   else if (xmesa->xm_visual->dithered_pf==PF_DITHER
2266	    && GET_VISUAL_DEPTH(xmesa->xm_visual)==8) {
2267      /* Special case: 8bpp RGB */
2268      for (y=0;y<b->height;y++) {
2269         GLubyte *ptr = (GLubyte*) xmesa->xm_buffer->backimage->data
2270                        + xmesa->xm_buffer->backimage->bytes_per_line * y;
2271         XDITHER_SETUP(y);
2272
2273         /* read row from 3Dfx frame buffer */
2274         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2275                          0, xmesa->xm_buffer->FXctx->height-(b->height-y),
2276                          b->width, 1,
2277                          0,
2278                          pixbuf );
2279
2280         /* write to XImage back buffer */
2281         for (x=0;x<b->width;x++) {
2282            GLubyte r = (pixbuf[x] & 0xf800) >> 8;
2283            GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
2284            GLubyte b = (pixbuf[x] & 0x001f) << 3;
2285            *ptr++ = XDITHER( x, r, g, b);
2286         }
2287      }
2288   }
2289   else {
2290      /* General case: slow! */
2291      for (y=0;y<b->height;y++) {
2292         /* read row from 3Dfx frame buffer */
2293         grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
2294                          0, xmesa->xm_buffer->FXctx->height-(b->height-y),
2295                          b->width, 1,
2296                          0,
2297                          pixbuf );
2298
2299         /* write to XImage back buffer */
2300         for (x=0;x<b->width;x++) {
2301            XMesaPutPixel(b->backimage,x,y,
2302			  xmesa_color_to_pixel(xmesa,
2303					       (pixbuf[x] & 0xf800) >> 8,
2304					       (pixbuf[x] & 0x07e0) >> 3,
2305					       (pixbuf[x] & 0x001f) << 3,
2306					       0xff, xmesa->pixelformat));
2307         }
2308      }
2309   }
2310   grLfbWriteColorFormat(GR_COLORFORMAT_ABGR);
2311}
2312#endif
2313
2314
2315/*
2316 * Copy the back buffer to the front buffer.  If there's no back buffer
2317 * this is a no-op.
2318 */
2319void XMesaSwapBuffers( XMesaBuffer b )
2320{
2321   GET_CURRENT_CONTEXT(ctx);
2322
2323   /* If we're swapping the buffer associated with the current context
2324    * we have to flush any pending rendering commands first.
2325    */
2326   if (b->xm_context && b->xm_context->gl_ctx == ctx)
2327      _mesa_swapbuffers(ctx);
2328
2329   if (b->db_state) {
2330#ifdef FX
2331      if (b->FXctx) {
2332         fxMesaSwapBuffers();
2333
2334         if (b->FXwindowHack)
2335            FXgetImage(b);
2336         else
2337            return;
2338      }
2339#endif
2340     if (b->backimage) {
2341	 /* Copy Ximage from host's memory to server's window */
2342#if defined(USE_XSHM) && !defined(XFree86Server)
2343	 if (b->shm) {
2344            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2345	    XShmPutImage( b->xm_visual->display, b->frontbuffer,
2346			  b->cleargc,
2347			  b->backimage, 0, 0,
2348			  0, 0, b->width, b->height, False );
2349            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2350	 }
2351	 else
2352#endif
2353         {
2354#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server)
2355	    XMesaDriSwapBuffers( b );
2356#else
2357            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2358            XMesaPutImage( b->xm_visual->display, b->frontbuffer,
2359			   b->cleargc,
2360			   b->backimage, 0, 0,
2361			   0, 0, b->width, b->height );
2362            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2363#endif
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->cleargc,
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(GLX_DIRECT_RENDERING) && !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 */
2389void 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 (b->xm_context->gl_ctx == ctx)
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->cleargc,
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->cleargc,
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->cleargc,
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 */
2454GLboolean 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 */
2479GLboolean 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
2499void 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
2512const char *XMesaGetString( XMesaContext c, int name )
2513{
2514   (void) c;
2515   if (name==XMESA_VERSION) {
2516      return "3.1";
2517   }
2518   else if (name==XMESA_EXTENSIONS) {
2519      return "";
2520   }
2521   else {
2522      return NULL;
2523   }
2524}
2525
2526
2527
2528XMesaBuffer 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 */
2545void XMesaGarbageCollect( void )
2546{
2547   XMesaBuffer b, next;
2548   for (b=XMesaBufferList; b; b=next) {
2549      next = b->Next;
2550      if (!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
2565void XMesaReset( void )
2566{
2567    while (XMesaBufferList)
2568	XMesaDestroyBuffer(XMesaBufferList);
2569
2570    XMesaBufferList = NULL;
2571}
2572
2573
2574unsigned 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