diff options
-rw-r--r-- | src/mesa/drivers/x11/fakeglx.c | 13 | ||||
-rw-r--r-- | src/mesa/drivers/x11/xm_api.c | 258 | ||||
-rw-r--r-- | src/mesa/drivers/x11/xmesaP.h | 19 |
3 files changed, 284 insertions, 6 deletions
diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c index b6569b1938f..eecd52aa32b 100644 --- a/src/mesa/drivers/x11/fakeglx.c +++ b/src/mesa/drivers/x11/fakeglx.c @@ -1440,7 +1440,7 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, } if (!drawBuffer) { /* drawable must be a new window! */ - drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); + drawBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, draw, xmctx); if (!drawBuffer) { /* Out of memory, or context/drawable depth mismatch */ return False; @@ -1457,7 +1457,8 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, } if (!readBuffer) { /* drawable must be a new window! */ - readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); + readBuffer = XMesaCreateWindowBuffer2(glxCtx->xmesaContext->xm_visual, + read, xmctx); if (!readBuffer) { /* Out of memory, or context/drawable depth mismatch */ return False; @@ -1929,6 +1930,12 @@ Fake_glXWaitX( void ) static const char * get_extensions( void ) { +#ifdef FX + const char *fx = _mesa_getenv("MESA_GLX_FX"); + if (fx && fx[0] != 'd') { + return EXTENSIONS; + } +#endif return EXTENSIONS + 23; /* skip "GLX_MESA_set_3dfx_mode" */ } @@ -2100,7 +2107,7 @@ Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, if (!xmvis) return 0; - xmbuf = XMesaCreateWindowBuffer(xmvis, win); + xmbuf = XMesaCreateWindowBuffer2(xmvis, win, NULL); if (!xmbuf) return 0; diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c index 6f671969fec..6439d13fa5f 100644 --- a/src/mesa/drivers/x11/xm_api.c +++ b/src/mesa/drivers/x11/xm_api.c @@ -1557,6 +1557,12 @@ PUBLIC void XMesaDestroyContext( XMesaContext c ) { GLcontext *mesaCtx = &c->mesa; +#ifdef FX + XMesaBuffer xmbuf = XMESA_BUFFER(mesaCtx->DrawBuffer); + + if (xmbuf && xmbuf->FXctx) + fxMesaDestroyContext(xmbuf->FXctx); +#endif _swsetup_DestroyContext( mesaCtx ); _swrast_DestroyContext( mesaCtx ); _tnl_DestroyContext( mesaCtx ); @@ -1572,20 +1578,25 @@ void XMesaDestroyContext( XMesaContext c ) * X window or pixmap. * \param v the window's XMesaVisual * \param w the window we're wrapping + * \param c context used to initialize the buffer if 3Dfx mode in use. * \return new XMesaBuffer or NULL if error */ -PUBLIC XMesaBuffer -XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) +XMesaBuffer +XMesaCreateWindowBuffer2(XMesaVisual v, XMesaWindow w, XMesaContext c) { #ifndef XFree86Server XWindowAttributes attr; #endif +#ifdef FX + char *fxEnvVar; +#endif int client = 0; XMesaBuffer b; XMesaColormap cmap; assert(v); assert(w); + (void) c; /* Check that window depth matches visual depth */ #ifdef XFree86Server @@ -1631,10 +1642,96 @@ XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) return NULL; } +#ifdef FX + 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); + + /* 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"); + } +#endif + return b; } +PUBLIC XMesaBuffer +XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) +{ + return XMesaCreateWindowBuffer2( v, w, NULL ); +} + + /** * Create a new XMesaBuffer from an X pixmap. * @@ -1760,6 +1857,15 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, if (!drawBuffer || !readBuffer) return GL_FALSE; /* must specify buffers! */ +#ifdef FX + if (drawBuffer->FXctx) { + fxMesaMakeCurrent(drawBuffer->FXctx); + + c->xm_buffer = drawBuffer; + + return GL_TRUE; + } +#endif if (&(c->mesa) == _mesa_get_current_context() && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer && c->mesa.ReadBuffer == &readBuffer->mesa_buffer @@ -1900,12 +2006,141 @@ GLboolean XMesaCopyContext( XMesaContext xm_src, XMesaContext xm_dst, GLuint mas */ GLboolean XMesaSetFXmode( GLint mode ) { +#ifdef FX + 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");*/ +#else (void) mode; +#endif return GL_FALSE; } +#ifdef FX +/* + * 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; + XMesaContext xmesa = XMESA_CONTEXT(ctx); + +#ifdef XFree86Server + x = b->frontxrb->pixmap->x; + y = b->frontxrb->pixmap->y; + width = b->frontxrb->pixmap->width; + height = b->frontxrb->pixmap->height; + depth = b->frontxrb->pixmap->depth; +#else + xmesa_get_window_size(b->display, b, &width, &height); + x = y = 0; +#endif + 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;y<b->mesa_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;x<b->mesa_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;y<b->mesa_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;x<b->mesa_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); */ +} +#endif + + /* * Copy the back buffer to the front buffer. If there's no back buffer * this is a no-op. @@ -1927,6 +2162,16 @@ void XMesaSwapBuffers( XMesaBuffer b ) _mesa_notifySwapBuffers(ctx); if (b->db_mode) { +#ifdef FX + if (b->FXctx) { + fxMesaSwapBuffers(); + + if (b->FXwindowHack) + FXgetImage(b); + else + return; + } +#endif if (b->backxrb->ximage) { /* Copy Ximage (back buf) from client memory to server window */ #if defined(USE_XSHM) && !defined(XFree86Server) @@ -1993,6 +2238,15 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) if (b->db_mode) { int yTop = b->mesa_buffer.Height - y - height; +#ifdef FX + if (b->FXctx) { + fxMesaSwapBuffers(); + if (b->FXwindowHack) + FXgetImage(b); + else + return; + } +#endif if (b->backxrb->ximage) { /* Copy Ximage from host's memory to server's window */ #if defined(USE_XSHM) && !defined(XFree86Server) diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h index 7b72e6b2f98..98d03ccf62f 100644 --- a/src/mesa/drivers/x11/xmesaP.h +++ b/src/mesa/drivers/x11/xmesaP.h @@ -29,7 +29,10 @@ #include "GL/xmesa.h" #include "mtypes.h" - +#if defined(FX) +#include "GL/fxmesa.h" +#include "../glide/fxdrv.h" +#endif #ifdef XFree86Server #include "xm_image.h" #endif @@ -257,6 +260,13 @@ struct xmesa_buffer { unsigned long alloced_colors[256]; #endif +#if defined( FX ) + /* For 3Dfx Glide only */ + GLboolean FXisHackUsable; /* Can we render into window? */ + GLboolean FXwindowHack; /* Are we rendering into a window? */ + fxMesaContext FXctx; +#endif + struct xmesa_buffer *Next; /* Linked list pointer: */ }; @@ -557,6 +567,13 @@ extern void xmesa_choose_triangle( GLcontext *ctx ); extern void xmesa_register_swrast_functions( GLcontext *ctx ); + +/* XXX this is a hack to implement shared display lists with 3Dfx */ +extern XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, + XMesaWindow w, + XMesaContext c ); + + #define ENABLE_EXT_texure_compression_s3tc 0 /* SW texture compression */ #ifdef XFree86Server |