diff options
Diffstat (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/glide/fxapi.c')
-rw-r--r-- | nx-X11/extras/Mesa/src/mesa/drivers/glide/fxapi.c | 951 |
1 files changed, 951 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/glide/fxapi.c b/nx-X11/extras/Mesa/src/mesa/drivers/glide/fxapi.c new file mode 100644 index 000000000..e535e739b --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/glide/fxapi.c @@ -0,0 +1,951 @@ +/* + * Mesa 3-D graphics library + * Version: 4.0 + * + * Copyright (C) 1999-2001 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. + */ + +/* Authors: + * David Bucciarelli + * Brian Paul + * Daryll Strauss + * Keith Whitwell + * Daniel Borca + * Hiroshi Morii + */ + + +/* fxapi.c - public interface to FX/Mesa functions (fxmesa.h) */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) +#include "fxdrv.h" + +#include "drivers/common/driverfuncs.h" +#include "framebuffer.h" + +#ifndef TDFX_DEBUG +int TDFX_DEBUG = (0 +/* | VERBOSE_VARRAY */ +/* | VERBOSE_TEXTURE */ +/* | VERBOSE_IMMEDIATE */ +/* | VERBOSE_PIPELINE */ +/* | VERBOSE_DRIVER */ +/* | VERBOSE_STATE */ +/* | VERBOSE_API */ +/* | VERBOSE_DISPLAY_LIST */ +/* | VERBOSE_LIGHTING */ +/* | VERBOSE_PRIMS */ +/* | VERBOSE_VERTS */ + ); +#endif + +static fxMesaContext fxMesaCurrentCtx = NULL; + +/* + * Status of 3Dfx hardware initialization + */ + +static int glbGlideInitialized = 0; +static int glb3DfxPresent = 0; +static int glbTotNumCtx = 0; + +static GrHwConfiguration glbHWConfig; +static int glbCurrentBoard = 0; + + +#if defined(__WIN32__) +static int +cleangraphics(void) +{ + glbTotNumCtx = 1; + fxMesaDestroyContext(fxMesaCurrentCtx); + + return 0; +} +#elif defined(__linux__) +static void +cleangraphics(void) +{ + glbTotNumCtx = 1; + fxMesaDestroyContext(fxMesaCurrentCtx); +} + +static void +cleangraphics_handler(int s) +{ + fprintf(stderr, "fxmesa: ERROR: received a not handled signal %d\n", s); + + cleangraphics(); +/* abort(); */ + exit(1); +} +#endif + + +/* + * Query 3Dfx hardware presence/kind + */ +static GLboolean GLAPIENTRY fxQueryHardware (void) +{ + if (TDFX_DEBUG & VERBOSE_DRIVER) { + fprintf(stderr, "fxQueryHardware()\n"); + } + + if (!glbGlideInitialized) { + grGlideInit(); + glb3DfxPresent = FX_grSstQueryHardware(&glbHWConfig); + + glbGlideInitialized = 1; + +#if defined(__WIN32__) + _onexit((_onexit_t) cleangraphics); +#elif defined(__linux__) + /* Only register handler if environment variable is not defined. */ + if (!getenv("MESA_FX_NO_SIGNALS")) { + atexit(cleangraphics); + } +#endif + } + + return glb3DfxPresent; +} + + +/* + * Select the Voodoo board to use when creating + * a new context. + */ +GLint GLAPIENTRY fxMesaSelectCurrentBoard (int n) +{ + fxQueryHardware(); + + if ((n < 0) || (n >= glbHWConfig.num_sst)) + return -1; + + return glbHWConfig.SSTs[glbCurrentBoard = n].type; +} + + +fxMesaContext GLAPIENTRY fxMesaGetCurrentContext (void) +{ + return fxMesaCurrentCtx; +} + + +void GLAPIENTRY fxGetScreenGeometry (GLint *w, GLint *h) +{ + GLint width = 0; + GLint height = 0; + + if (fxMesaCurrentCtx != NULL) { + width = fxMesaCurrentCtx->screen_width; + height = fxMesaCurrentCtx->screen_height; + } + + if (w != NULL) { + *w = width; + } + if (h != NULL) { + *h = height; + } +} + + +/* + * The 3Dfx Global Palette extension for GLQuake. + * More a trick than a real extesion, use the shared global + * palette extension. + */ +extern void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint * pal); /* silence warning */ +void GLAPIENTRY +gl3DfxSetPaletteEXT(GLuint * pal) +{ + fxMesaContext fxMesa = fxMesaCurrentCtx; + + if (TDFX_DEBUG & VERBOSE_DRIVER) { + int i; + + fprintf(stderr, "gl3DfxSetPaletteEXT(...)\n"); + + for (i = 0; i < 256; i++) { + fprintf(stderr, "\t%x\n", pal[i]); + } + } + + if (fxMesa) { + fxMesa->haveGlobalPaletteTexture = 1; + + grTexDownloadTable(GR_TEXTABLE_PALETTE, (GuTexPalette *) pal); + } +} + + +static GrScreenResolution_t fxBestResolution (int width, int height) +{ + static int resolutions[][3] = { + { GR_RESOLUTION_320x200, 320, 200 }, + { GR_RESOLUTION_320x240, 320, 240 }, + { GR_RESOLUTION_400x256, 400, 256 }, + { GR_RESOLUTION_512x384, 512, 384 }, + { GR_RESOLUTION_640x200, 640, 200 }, + { GR_RESOLUTION_640x350, 640, 350 }, + { GR_RESOLUTION_640x400, 640, 400 }, + { GR_RESOLUTION_640x480, 640, 480 }, + { GR_RESOLUTION_800x600, 800, 600 }, + { GR_RESOLUTION_960x720, 960, 720 }, + { GR_RESOLUTION_856x480, 856, 480 }, + { GR_RESOLUTION_512x256, 512, 256 }, + { GR_RESOLUTION_1024x768, 1024, 768 }, + { GR_RESOLUTION_1280x1024, 1280, 1024 }, + { GR_RESOLUTION_1600x1200, 1600, 1200 }, + { GR_RESOLUTION_400x300, 400, 300 }, + { GR_RESOLUTION_1152x864, 1152, 864 }, + { GR_RESOLUTION_1280x960, 1280, 960 }, + { GR_RESOLUTION_1600x1024, 1600, 1024 }, + { GR_RESOLUTION_1792x1344, 1792, 1344 }, + { GR_RESOLUTION_1856x1392, 1856, 1392 }, + { GR_RESOLUTION_1920x1440, 1920, 1440 }, + { GR_RESOLUTION_2048x1536, 2048, 1536 }, + { GR_RESOLUTION_2048x2048, 2048, 2048 } + }; + + int i, size; + int lastvalidres = GR_RESOLUTION_640x480; + int min = 2048 * 2048; /* max is GR_RESOLUTION_2048x2048 */ + GrResolution resTemplate = { + GR_QUERY_ANY, + GR_QUERY_ANY, + 2 /*GR_QUERY_ANY */, + GR_QUERY_ANY + }; + GrResolution *presSupported; + + fxQueryHardware(); + + size = grQueryResolutions(&resTemplate, NULL); + presSupported = malloc(size); + + size /= sizeof(GrResolution); + grQueryResolutions(&resTemplate, presSupported); + + for (i = 0; i < size; i++) { + int r = presSupported[i].resolution; + if ((width <= resolutions[r][1]) && (height <= resolutions[r][2])) { + if (min > (resolutions[r][1] * resolutions[r][2])) { + min = resolutions[r][1] * resolutions[r][2]; + lastvalidres = r; + } + } + } + + free(presSupported); + + return resolutions[lastvalidres][0]; +} + + +fxMesaContext GLAPIENTRY +fxMesaCreateBestContext(GLuint win, GLint width, GLint height, + const GLint attribList[]) +{ + int res = fxBestResolution(width, height); + + if (res == -1) { + return NULL; + } + + return fxMesaCreateContext(win, res, GR_REFRESH_60Hz, attribList); +} + + +/* + * Create a new FX/Mesa context and return a handle to it. + */ +fxMesaContext GLAPIENTRY +fxMesaCreateContext(GLuint win, + GrScreenResolution_t res, + GrScreenRefresh_t ref, const GLint attribList[]) +{ + fxMesaContext fxMesa = NULL; + GLcontext *ctx = NULL, *shareCtx = NULL; + struct dd_function_table functions; + + int i; + const char *str; + int sliaa, numSLI, samplesPerChip; + struct SstCard_St *voodoo; + struct tdfx_glide *Glide; + + GLboolean aux; + GLboolean doubleBuffer; + GLuint colDepth; + GLuint depthSize, alphaSize, stencilSize, accumSize; + GLuint redBits, greenBits, blueBits, alphaBits; + GrPixelFormat_t pixFmt; + + if (TDFX_DEBUG & VERBOSE_DRIVER) { + fprintf(stderr, "fxMesaCreateContext(...)\n"); + } + + /* Okay, first process the user flags */ + aux = GL_FALSE; + doubleBuffer = GL_FALSE; + colDepth = 16; + depthSize = alphaSize = stencilSize = accumSize = 0; + + i = 0; + while (attribList[i] != FXMESA_NONE) { + switch (attribList[i]) { + case FXMESA_COLORDEPTH: + colDepth = attribList[++i]; + break; + case FXMESA_DOUBLEBUFFER: + doubleBuffer = GL_TRUE; + break; + case FXMESA_ALPHA_SIZE: + if ((alphaSize = attribList[++i])) { + aux = GL_TRUE; + } + break; + case FXMESA_DEPTH_SIZE: + if ((depthSize = attribList[++i])) { + aux = GL_TRUE; + } + break; + case FXMESA_STENCIL_SIZE: + stencilSize = attribList[++i]; + break; + case FXMESA_ACCUM_SIZE: + accumSize = attribList[++i]; + break; + /* XXX ugly hack here for sharing display lists */ + case FXMESA_SHARE_CONTEXT: + shareCtx = (GLcontext *)attribList[++i]; + break; + default: + fprintf(stderr, "fxMesaCreateContext: ERROR: wrong parameter (%d) passed\n", attribList[i]); + return NULL; + } + i++; + } + + if (!fxQueryHardware()) { + str = "no Voodoo hardware!"; + goto errorhandler; + } + + grSstSelect(glbCurrentBoard); + /*grEnable(GR_OPENGL_MODE_EXT);*/ /* [koolsmoky] */ + voodoo = &glbHWConfig.SSTs[glbCurrentBoard]; + + fxMesa = (fxMesaContext)CALLOC_STRUCT(tfxMesaContext); + if (!fxMesa) { + str = "private context"; + goto errorhandler; + } + + if (getenv("MESA_FX_INFO")) { + fxMesa->verbose = GL_TRUE; + } + + fxMesa->type = voodoo->type; + fxMesa->HavePalExt = voodoo->HavePalExt && !getenv("MESA_FX_IGNORE_PALEXT"); + fxMesa->HavePixExt = voodoo->HavePixExt && !getenv("MESA_FX_IGNORE_PIXEXT"); + fxMesa->HaveTexFmt = voodoo->HaveTexFmt && !getenv("MESA_FX_IGNORE_TEXFMT"); + fxMesa->HaveCmbExt = voodoo->HaveCmbExt && !getenv("MESA_FX_IGNORE_CMBEXT"); + fxMesa->HaveMirExt = voodoo->HaveMirExt && !getenv("MESA_FX_IGNORE_MIREXT"); + fxMesa->HaveTexUma = voodoo->HaveTexUma && !getenv("MESA_FX_IGNORE_TEXUMA"); + fxMesa->Glide = glbHWConfig.Glide; + Glide = &fxMesa->Glide; + fxMesa->HaveTexus2 = Glide->txImgQuantize && + Glide->txMipQuantize && + Glide->txPalToNcc && !getenv("MESA_FX_IGNORE_TEXUS2"); + + /* Determine if we need vertex swapping, RGB order and SLI/AA */ + sliaa = 0; + switch (fxMesa->type) { + case GR_SSTTYPE_VOODOO: + case GR_SSTTYPE_SST96: + case GR_SSTTYPE_Banshee: + fxMesa->bgrOrder = GL_TRUE; + fxMesa->snapVertices = (getenv("MESA_FX_NOSNAP") == NULL); + break; + case GR_SSTTYPE_Voodoo2: + fxMesa->bgrOrder = GL_TRUE; + fxMesa->snapVertices = GL_FALSE; + break; + case GR_SSTTYPE_Voodoo4: + case GR_SSTTYPE_Voodoo5: + /* number of SLI units and AA Samples per chip */ + if ((str = Glide->grGetRegistryOrEnvironmentStringExt("SSTH3_SLI_AA_CONFIGURATION")) != NULL) { + sliaa = atoi(str); + } + case GR_SSTTYPE_Voodoo3: + default: + fxMesa->bgrOrder = GL_FALSE; + fxMesa->snapVertices = GL_FALSE; + break; + } + /* XXX todo - Add the old SLI/AA settings for Napalm. */ + switch(voodoo->numChips) { + case 4: /* 4 chips */ + switch(sliaa) { + case 8: /* 8 Sample AA */ + numSLI = 1; + samplesPerChip = 2; + break; + case 7: /* 4 Sample AA */ + numSLI = 1; + samplesPerChip = 1; + break; + case 6: /* 2 Sample AA */ + numSLI = 2; + samplesPerChip = 1; + break; + default: + numSLI = 4; + samplesPerChip = 1; + } + break; + case 2: /* 2 chips */ + switch(sliaa) { + case 4: /* 4 Sample AA */ + numSLI = 1; + samplesPerChip = 2; + break; + case 3: /* 2 Sample AA */ + numSLI = 1; + samplesPerChip = 1; + break; + default: + numSLI = 2; + samplesPerChip = 1; + } + break; + default: /* 1 chip */ + switch(sliaa) { + case 1: /* 2 Sample AA */ + numSLI = 1; + samplesPerChip = 2; + break; + default: + numSLI = 1; + samplesPerChip = 1; + } + } + + fxMesa->fsaa = samplesPerChip * voodoo->numChips / numSLI; /* 1:noFSAA, 2:2xFSAA, 4:4xFSAA, 8:8xFSAA */ + + switch (fxMesa->colDepth = colDepth) { + case 15: + redBits = 5; + greenBits = 5; + blueBits = 5; + alphaBits = depthSize ? 1 : 8; + switch(fxMesa->fsaa) { + case 8: + pixFmt = GR_PIXFMT_AA_8_ARGB_1555; + break; + case 4: + pixFmt = GR_PIXFMT_AA_4_ARGB_1555; + break; + case 2: + pixFmt = GR_PIXFMT_AA_2_ARGB_1555; + break; + default: + pixFmt = GR_PIXFMT_ARGB_1555; + } + break; + case 16: + redBits = 5; + greenBits = 6; + blueBits = 5; + alphaBits = depthSize ? 0 : 8; + switch(fxMesa->fsaa) { + case 8: + pixFmt = GR_PIXFMT_AA_8_RGB_565; + break; + case 4: + pixFmt = GR_PIXFMT_AA_4_RGB_565; + break; + case 2: + pixFmt = GR_PIXFMT_AA_2_RGB_565; + break; + default: + pixFmt = GR_PIXFMT_RGB_565; + } + break; + case 24: + fxMesa->colDepth = 32; + case 32: + redBits = 8; + greenBits = 8; + blueBits = 8; + alphaBits = 8; + switch(fxMesa->fsaa) { + case 8: + pixFmt = GR_PIXFMT_AA_8_ARGB_8888; + break; + case 4: + pixFmt = GR_PIXFMT_AA_4_ARGB_8888; + break; + case 2: + pixFmt = GR_PIXFMT_AA_2_ARGB_8888; + break; + default: + pixFmt = GR_PIXFMT_ARGB_8888; + } + break; + default: + str = "pixelFormat"; + goto errorhandler; + } + + /* Tips: + * 1. we don't bother setting/checking AUX for stencil, because we'll decide + * later whether we have HW stencil, based on depth buffer (thus AUX is + * properly set) + * 2. when both DEPTH and ALPHA are enabled, depth should win. However, it is + * not clear whether 15bpp and 32bpp require AUX alpha buffer. Furthermore, + * alpha buffering is required only if destination alpha is used in alpha + * blending; alpha blending modes that do not use destination alpha can be + * used w/o alpha buffer. + * 3. `alphaBits' is what we can provide + * `alphaSize' is what app requests + * if we cannot provide enough bits for alpha buffer, we should fallback to + * SW alpha. However, setting `alphaBits' to `alphaSize' might confuse some + * of the span functions... + */ + + fxMesa->haveHwAlpha = GL_FALSE; + if (alphaSize && (alphaSize <= alphaBits)) { + alphaSize = alphaBits; + fxMesa->haveHwAlpha = GL_TRUE; + } + + fxMesa->haveHwStencil = (fxMesa->HavePixExt && stencilSize && depthSize == 24); + + fxMesa->haveZBuffer = depthSize > 0; + fxMesa->haveDoubleBuffer = doubleBuffer; + fxMesa->haveGlobalPaletteTexture = GL_FALSE; + fxMesa->board = glbCurrentBoard; + + fxMesa->haveTwoTMUs = (voodoo->nTexelfx > 1); + + if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_NUM_TMU"))) { + if (atoi(str) <= 1) { + fxMesa->haveTwoTMUs = GL_FALSE; + } + } + + if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPPENDINGCOUNT"))) { + fxMesa->maxPendingSwapBuffers = atoi(str); + if (fxMesa->maxPendingSwapBuffers > 6) { + fxMesa->maxPendingSwapBuffers = 6; + } else if (fxMesa->maxPendingSwapBuffers < 0) { + fxMesa->maxPendingSwapBuffers = 0; + } + } else { + fxMesa->maxPendingSwapBuffers = 2; + } + + if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPINTERVAL"))) { + fxMesa->swapInterval = atoi(str); + } else { + fxMesa->swapInterval = 0; + } + + BEGIN_BOARD_LOCK(); + if (fxMesa->HavePixExt) { + fxMesa->glideContext = Glide->grSstWinOpenExt((FxU32)win, res, ref, + GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT, + pixFmt, + 2, aux); + } else if (pixFmt == GR_PIXFMT_RGB_565) { + fxMesa->glideContext = grSstWinOpen((FxU32)win, res, ref, + GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT, + 2, aux); + } else { + fxMesa->glideContext = 0; + } + END_BOARD_LOCK(); + if (!fxMesa->glideContext) { + str = "grSstWinOpen"; + goto errorhandler; + } + + /* screen */ + fxMesa->screen_width = FX_grSstScreenWidth(); + fxMesa->screen_height = FX_grSstScreenHeight(); + + /* window inside screen */ + fxMesa->width = fxMesa->screen_width; + fxMesa->height = fxMesa->screen_height; + + /* scissor inside window */ + fxMesa->clipMinX = 0; + fxMesa->clipMaxX = fxMesa->width; + fxMesa->clipMinY = 0; + fxMesa->clipMaxY = fxMesa->height; + + if (fxMesa->verbose) { + FxI32 tmuRam, fbRam; + + /* Not that it matters, but tmuRam and fbRam change after grSstWinOpen. */ + tmuRam = voodoo->tmuConfig[GR_TMU0].tmuRam; + fbRam = voodoo->fbRam; + BEGIN_BOARD_LOCK(); + grGet(GR_MEMORY_TMU, 4, &tmuRam); + grGet(GR_MEMORY_FB, 4, &fbRam); + END_BOARD_LOCK(); + + fprintf(stderr, "Voodoo Using Glide %s\n", grGetString(GR_VERSION)); + fprintf(stderr, "Voodoo Board: %d/%d, %s, %d GPU\n", + fxMesa->board + 1, + glbHWConfig.num_sst, + grGetString(GR_HARDWARE), + voodoo->numChips); + fprintf(stderr, "Voodoo Memory: FB = %ld, TM = %d x %ld\n", + fbRam, + voodoo->nTexelfx, + tmuRam); + fprintf(stderr, "Voodoo Screen: %dx%d:%d %s, %svertex snapping\n", + fxMesa->screen_width, + fxMesa->screen_height, + colDepth, + fxMesa->bgrOrder ? "BGR" : "RGB", + fxMesa->snapVertices ? "" : "no "); + } + + sprintf(fxMesa->rendererString, "Mesa %s v0.63 %s%s", + grGetString(GR_RENDERER), + grGetString(GR_HARDWARE), + ((fxMesa->type < GR_SSTTYPE_Voodoo4) && (voodoo->numChips > 1)) ? " SLI" : ""); + + fxMesa->glVis = _mesa_create_visual(GL_TRUE, /* RGB mode */ + doubleBuffer, + GL_FALSE, /* stereo */ + redBits, /* RGBA.R bits */ + greenBits, /* RGBA.G bits */ + blueBits, /* RGBA.B bits */ + alphaSize, /* RGBA.A bits */ + 0, /* index bits */ + depthSize, /* depth_size */ + stencilSize, /* stencil_size */ + accumSize, + accumSize, + accumSize, + alphaSize ? accumSize : 0, + 1); + if (!fxMesa->glVis) { + str = "_mesa_create_visual"; + goto errorhandler; + } + + _mesa_init_driver_functions(&functions); + ctx = fxMesa->glCtx = _mesa_create_context(fxMesa->glVis, shareCtx, + &functions, (void *) fxMesa); + if (!ctx) { + str = "_mesa_create_context"; + goto errorhandler; + } + + + if (!fxDDInitFxMesaContext(fxMesa)) { + str = "fxDDInitFxMesaContext"; + goto errorhandler; + } + + + fxMesa->glBuffer = _mesa_create_framebuffer(fxMesa->glVis); +#if 0 +/* XXX this is a complete mess :( + * _mesa_add_soft_renderbuffers + * driNewRenderbuffer + */ + GL_FALSE, /* no software depth */ + stencilSize && !fxMesa->haveHwStencil, + fxMesa->glVis->accumRedBits > 0, + alphaSize && !fxMesa->haveHwAlpha); +#endif + if (!fxMesa->glBuffer) { + str = "_mesa_create_framebuffer"; + goto errorhandler; + } + + glbTotNumCtx++; + + /* install signal handlers */ +#if defined(__linux__) + /* Only install if environment var. is not set. */ + if (!getenv("MESA_FX_NO_SIGNALS")) { + signal(SIGINT, cleangraphics_handler); + signal(SIGHUP, cleangraphics_handler); + signal(SIGPIPE, cleangraphics_handler); + signal(SIGFPE, cleangraphics_handler); + signal(SIGBUS, cleangraphics_handler); + signal(SIGILL, cleangraphics_handler); + signal(SIGSEGV, cleangraphics_handler); + signal(SIGTERM, cleangraphics_handler); + } +#endif + + return fxMesa; + +errorhandler: + if (fxMesa) { + if (fxMesa->glideContext) { + grSstWinClose(fxMesa->glideContext); + fxMesa->glideContext = 0; + } + + if (fxMesa->state) { + FREE(fxMesa->state); + } + if (fxMesa->fogTable) { + FREE(fxMesa->fogTable); + } + if (fxMesa->glBuffer) { + _mesa_destroy_framebuffer(fxMesa->glBuffer); + } + if (fxMesa->glVis) { + _mesa_destroy_visual(fxMesa->glVis); + } + if (fxMesa->glCtx) { + _mesa_destroy_context(fxMesa->glCtx); + } + FREE(fxMesa); + } + + fprintf(stderr, "fxMesaCreateContext: ERROR: %s\n", str); + return NULL; +} + + +/* + * Function to set the new window size in the context (mainly for the Voodoo Rush) + */ +void GLAPIENTRY +fxMesaUpdateScreenSize(fxMesaContext fxMesa) +{ + fxMesa->width = FX_grSstScreenWidth(); + fxMesa->height = FX_grSstScreenHeight(); +} + + +/* + * Destroy the given FX/Mesa context. + */ +void GLAPIENTRY +fxMesaDestroyContext(fxMesaContext fxMesa) +{ + if (TDFX_DEBUG & VERBOSE_DRIVER) { + fprintf(stderr, "fxMesaDestroyContext(...)\n"); + } + + if (!fxMesa) + return; + + if (fxMesa->verbose) { + fprintf(stderr, "Misc Stats:\n"); + fprintf(stderr, " # swap buffer: %u\n", fxMesa->stats.swapBuffer); + + if (!fxMesa->stats.swapBuffer) + fxMesa->stats.swapBuffer = 1; + + fprintf(stderr, "Textures Stats:\n"); + fprintf(stderr, " Free texture memory on TMU0: %d\n", + fxMesa->freeTexMem[FX_TMU0]); + if (fxMesa->haveTwoTMUs) + fprintf(stderr, " Free texture memory on TMU1: %d\n", + fxMesa->freeTexMem[FX_TMU1]); + fprintf(stderr, " # request to TMM to upload a texture objects: %u\n", + fxMesa->stats.reqTexUpload); + fprintf(stderr, + " # request to TMM to upload a texture objects per swapbuffer: %.2f\n", + fxMesa->stats.reqTexUpload / (float) fxMesa->stats.swapBuffer); + fprintf(stderr, " # texture objects uploaded: %u\n", + fxMesa->stats.texUpload); + fprintf(stderr, " # texture objects uploaded per swapbuffer: %.2f\n", + fxMesa->stats.texUpload / (float) fxMesa->stats.swapBuffer); + fprintf(stderr, " # MBs uploaded to texture memory: %.2f\n", + fxMesa->stats.memTexUpload / (float) (1 << 20)); + fprintf(stderr, + " # MBs uploaded to texture memory per swapbuffer: %.2f\n", + (fxMesa->stats.memTexUpload / + (float) fxMesa->stats.swapBuffer) / (float) (1 << 20)); + } + + glbTotNumCtx--; + + if (!glbTotNumCtx && getenv("MESA_FX_INFO")) { + GrSstPerfStats_t st; + + FX_grSstPerfStats(&st); + + fprintf(stderr, "Pixels Stats:\n"); + fprintf(stderr, " # pixels processed (minus buffer clears): %u\n", + (unsigned) st.pixelsIn); + fprintf(stderr, " # pixels not drawn due to chroma key test failure: %u\n", + (unsigned) st.chromaFail); + fprintf(stderr, " # pixels not drawn due to depth test failure: %u\n", + (unsigned) st.zFuncFail); + fprintf(stderr, + " # pixels not drawn due to alpha test failure: %u\n", + (unsigned) st.aFuncFail); + fprintf(stderr, " # pixels drawn (including buffer clears and LFB writes): %u\n", + (unsigned) st.pixelsOut); + } + + /* close the hardware first, + * so we can debug atexit problems (memory leaks, etc). + */ + grSstWinClose(fxMesa->glideContext); + fxCloseHardware(); + + fxDDDestroyFxMesaContext(fxMesa); /* must be before _mesa_destroy_context */ + _mesa_destroy_visual(fxMesa->glVis); + _mesa_destroy_context(fxMesa->glCtx); + _mesa_destroy_framebuffer(fxMesa->glBuffer); + fxTMClose(fxMesa); /* must be after _mesa_destroy_context */ + + FREE(fxMesa); + + if (fxMesa == fxMesaCurrentCtx) + fxMesaCurrentCtx = NULL; +} + + +/* + * Make the specified FX/Mesa context the current one. + */ +void GLAPIENTRY +fxMesaMakeCurrent(fxMesaContext fxMesa) +{ + if (!fxMesa) { + _mesa_make_current(NULL, NULL, NULL); + fxMesaCurrentCtx = NULL; + + if (TDFX_DEBUG & VERBOSE_DRIVER) { + fprintf(stderr, "fxMesaMakeCurrent(NULL)\n"); + } + + return; + } + + /* if this context is already the current one, we can return early */ + if (fxMesaCurrentCtx == fxMesa + && fxMesaCurrentCtx->glCtx == _mesa_get_current_context()) { + if (TDFX_DEBUG & VERBOSE_DRIVER) { + fprintf(stderr, "fxMesaMakeCurrent(NOP)\n"); + } + + return; + } + + if (TDFX_DEBUG & VERBOSE_DRIVER) { + fprintf(stderr, "fxMesaMakeCurrent(...)\n"); + } + + if (fxMesaCurrentCtx) + grGlideGetState((GrState *) fxMesaCurrentCtx->state); + + fxMesaCurrentCtx = fxMesa; + + grSstSelect(fxMesa->board); + grGlideSetState((GrState *) fxMesa->state); + + _mesa_make_current(fxMesa->glCtx, fxMesa->glBuffer, fxMesa->glBuffer); + + fxSetupDDPointers(fxMesa->glCtx); +} + + +/* + * Swap front/back buffers for current context if double buffered. + */ +void GLAPIENTRY +fxMesaSwapBuffers(void) +{ + if (TDFX_DEBUG & VERBOSE_DRIVER) { + fprintf(stderr, "fxMesaSwapBuffers()\n"); + } + + if (fxMesaCurrentCtx) { + _mesa_notifySwapBuffers(fxMesaCurrentCtx->glCtx); + + if (fxMesaCurrentCtx->haveDoubleBuffer) { + + grBufferSwap(fxMesaCurrentCtx->swapInterval); + +#if 0 + /* + * Don't allow swap buffer commands to build up! + */ + while (FX_grGetInteger(GR_PENDING_BUFFERSWAPS) > + fxMesaCurrentCtx->maxPendingSwapBuffers) + /* The driver is able to sleep when waiting for the completation + of multiple swapbuffer operations instead of wasting + CPU time (NOTE: you must uncomment the following line in the + in order to enable this option) */ + /* usleep(10000); */ + ; +#endif + + fxMesaCurrentCtx->stats.swapBuffer++; + } + } +} + + +/* + * Shutdown Glide library + */ +void GLAPIENTRY +fxCloseHardware(void) +{ + if (glbGlideInitialized) { + if (glbTotNumCtx == 0) { + grGlideShutdown(); + glbGlideInitialized = 0; + } + } +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ +extern int gl_fx_dummy_function_api(void); +int +gl_fx_dummy_function_api(void) +{ + return 0; +} + +#endif /* FX */ |