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