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