/* * Mesa 3-D graphics library * Version: 6.5 * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "glxheader.h" #include "xmesaP.h" #ifdef FX #include "../glide/fxdrv.h" void FXcreateContext(XMesaVisual v, XMesaWindow w, XMesaContext c, XMesaBuffer b) { char *fxEnvVar = _mesa_getenv("MESA_GLX_FX"); if (fxEnvVar) { if (fxEnvVar[0]!='d') { int attribs[100]; int numAttribs = 0; int hw; if (v->mesa_visual.depthBits > 0) { attribs[numAttribs++] = FXMESA_DEPTH_SIZE; attribs[numAttribs++] = v->mesa_visual.depthBits; } if (v->mesa_visual.doubleBufferMode) { attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; } if (v->mesa_visual.accumRedBits > 0) { attribs[numAttribs++] = FXMESA_ACCUM_SIZE; attribs[numAttribs++] = v->mesa_visual.accumRedBits; } if (v->mesa_visual.stencilBits > 0) { attribs[numAttribs++] = FXMESA_STENCIL_SIZE; attribs[numAttribs++] = v->mesa_visual.stencilBits; } if (v->mesa_visual.alphaBits > 0) { attribs[numAttribs++] = FXMESA_ALPHA_SIZE; attribs[numAttribs++] = v->mesa_visual.alphaBits; } if (1) { attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; attribs[numAttribs++] = (int) &(c->mesa); } attribs[numAttribs++] = FXMESA_NONE; /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */ /* hw = fxMesaSelectCurrentBoard(0); */ hw = GR_SSTTYPE_Voodoo2; /* if these fail, there's a new bug somewhere */ ASSERT(b->mesa_buffer.Width > 0); ASSERT(b->mesa_buffer.Height > 0); if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) { b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width, b->mesa_buffer.Height, attribs); if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) { b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) { b->FXwindowHack = GL_TRUE; FX_grSstControl(GR_CONTROL_DEACTIVATE); } else { b->FXwindowHack = GL_FALSE; } } } else { if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, GR_REFRESH_75Hz, attribs); else b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width, b->mesa_buffer.Height, attribs); b->FXisHackUsable = GL_FALSE; b->FXwindowHack = GL_FALSE; } /* fprintf(stderr, "voodoo %d, wid %d height %d hack: usable %d active %d\n", hw, b->mesa_buffer.Width, b->mesa_buffer.Height, b->FXisHackUsable, b->FXwindowHack); */ } } else { _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n"); _mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n"); _mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n"); _mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); } } void FXdestroyContext( XMesaBuffer b ) { if (b && b->FXctx) fxMesaDestroyContext(b->FXctx); } GLboolean FXmakeCurrent( XMesaBuffer b ) { if (b->FXctx) { fxMesaMakeCurrent(b->FXctx); return GL_TRUE; } return GL_FALSE; } /* * Read image from VooDoo frame buffer into X/Mesa's back XImage. */ static void FXgetImage( XMesaBuffer b ) { GET_CURRENT_CONTEXT(ctx); static unsigned short pixbuf[MAX_WIDTH]; GLuint x, y; GLuint width, height; xmesa_get_window_size(b->display, b, &width, &height); x = y = 0; if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) { b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width); b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height); if (b->mesa_buffer.Width & 1) b->mesa_buffer.Width--; /* prevent odd width */ } /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */ /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */ if (b->xm_visual->undithered_pf==PF_5R6G5B) { /* Special case: 16bpp RGB */ grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ 0, b->FXctx->height - b->mesa_buffer.Height, /*pos*/ b->mesa_buffer.Width, b->mesa_buffer.Height, /* size */ b->mesa_buffer.Width * sizeof(GLushort), /* stride */ b->backxrb->ximage->data); /* dest buffer */ } else if (b->xm_visual->dithered_pf==PF_Dither && GET_VISUAL_DEPTH(b->xm_visual)==8) { /* Special case: 8bpp RGB */ for (y=0;ymesa_buffer.Height;y++) { GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data + b->backxrb->ximage->bytes_per_line * y; XDITHER_SETUP(y); /* read row from 3Dfx frame buffer */ grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 0, b->FXctx->height-(b->mesa_buffer.Height-y), b->mesa_buffer.Width, 1, 0, pixbuf ); /* write to XImage back buffer */ for (x=0;xmesa_buffer.Width;x++) { GLubyte r = (pixbuf[x] & 0xf800) >> 8; GLubyte g = (pixbuf[x] & 0x07e0) >> 3; GLubyte b = (pixbuf[x] & 0x001f) << 3; *ptr++ = XDITHER( x, r, g, b); } } } else { /* General case: slow! */ for (y=0;ymesa_buffer.Height;y++) { /* read row from 3Dfx frame buffer */ grLfbReadRegion( GR_BUFFER_FRONTBUFFER, 0, b->FXctx->height-(b->mesa_buffer.Height-y), b->mesa_buffer.Width, 1, 0, pixbuf ); /* write to XImage back buffer */ for (x=0;xmesa_buffer.Width;x++) { XMesaPutPixel(b->backxrb->ximage,x,y, xmesa_color_to_pixel(ctx, (pixbuf[x] & 0xf800) >> 8, (pixbuf[x] & 0x07e0) >> 3, (pixbuf[x] & 0x001f) << 3, 0xff, b->xm_visual->undithered_pf)); } } } /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */ } GLboolean FXswapBuffers( XMesaBuffer b ) { if (b->FXctx) { fxMesaSwapBuffers(); if (!b->FXwindowHack) return GL_TRUE; FXgetImage(b); } return GL_FALSE; } /* * Switch 3Dfx support hack between window and full-screen mode. */ GLboolean XMesaSetFXmode( GLint mode ) { const char *fx = _mesa_getenv("MESA_GLX_FX"); if (fx && fx[0] != 'd') { GET_CURRENT_CONTEXT(ctx); GrHwConfiguration hw; if (!FX_grSstQueryHardware(&hw)) { /*fprintf(stderr, "!grSstQueryHardware\n");*/ return GL_FALSE; } if (hw.num_sst < 1) { /*fprintf(stderr, "hw.num_sst < 1\n");*/ return GL_FALSE; } if (ctx) { /* [dBorca] Hack alert: * oh, this is sooo wrong: ctx above is * really an fxMesaContext, not an XMesaContext */ XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); if (mode == XMESA_FX_WINDOW) { if (xmbuf->FXisHackUsable) { FX_grSstControl(GR_CONTROL_DEACTIVATE); xmbuf->FXwindowHack = GL_TRUE; return GL_TRUE; } } else if (mode == XMESA_FX_FULLSCREEN) { FX_grSstControl(GR_CONTROL_ACTIVATE); xmbuf->FXwindowHack = GL_FALSE; return GL_TRUE; } else { /* Error: Bad mode value */ } } } /*fprintf(stderr, "fallthrough\n");*/ return GL_FALSE; } #endif