diff options
Diffstat (limited to 'src/mesa/drivers/dri/tdfx/server')
-rw-r--r-- | src/mesa/drivers/dri/tdfx/server/tdfx_dri.c | 525 |
1 files changed, 525 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/tdfx/server/tdfx_dri.c b/src/mesa/drivers/dri/tdfx/server/tdfx_dri.c new file mode 100644 index 0000000..e0f7609 --- /dev/null +++ b/src/mesa/drivers/dri/tdfx/server/tdfx_dri.c @@ -0,0 +1,525 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 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: + * Keith Whitwell + * Daniel Borca + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include "driver.h" +#include "drm.h" +#include "imports.h" + +#include "dri_util.h" + +#include "tdfx_context.h" +#include "tdfx_dri.h" +#include "xf86drm.h" + + +#define TILE_WIDTH 128 +#define TILE_HEIGHT 32 + +#define CMDFIFO_PAGES 64 + + +static int +calcBufferStride (int xres, int tiled, int cpp) +{ + int strideInTiles; + + if (tiled) { + /* Calculate tile width stuff */ + strideInTiles = (xres+TILE_WIDTH-1)/TILE_WIDTH; + + return strideInTiles*cpp*TILE_WIDTH; + } else { + return xres*cpp; + } +} /* calcBufferStride */ + + +static int +calcBufferHeightInTiles (int yres) +{ + int heightInTiles; /* Height of buffer in tiles */ + + /* Calculate tile height stuff */ + heightInTiles = yres >> 5; + + if (yres & (TILE_HEIGHT - 1)) + heightInTiles++; + + return heightInTiles; + +} /* calcBufferHeightInTiles */ + + +static int +calcBufferSize (int xres, int yres, int tiled, int cpp) +{ + int stride, height, bufSize; + + if (tiled) { + stride = calcBufferStride(xres, tiled, cpp); + height = TILE_HEIGHT * calcBufferHeightInTiles(yres); + } else { + stride = xres*cpp; + height = yres; + } + + bufSize = stride * height; + + return bufSize; +} /* calcBufferSize */ + + +static void allocateMemory (const DRIDriverContext *ctx, TDFXDRIPtr pTDFX) +{ + int memRemaining, fifoSize, screenSizeInTiles; + int fbSize; + char *str; + int pixmapCacheLinesMin; + int cursorOffset, cursorSize; + + pTDFX->stride = calcBufferStride(pTDFX->width, !0, pTDFX->cpp); + + /* enough to do DVD */ + pixmapCacheLinesMin = ((720*480*pTDFX->cpp) + + pTDFX->stride - 1)/pTDFX->stride; + + if (pTDFX->deviceID > PCI_CHIP_VOODOO3) { + if ((pixmapCacheLinesMin + pTDFX->height) > 4095) + pixmapCacheLinesMin = 4095 - pTDFX->height; + } else { + if ((pixmapCacheLinesMin + pTDFX->height) > 2047) + pixmapCacheLinesMin = 2047 - pTDFX->height; + } + + if (pTDFX->cpp!=3) { + screenSizeInTiles=calcBufferSize(pTDFX->width, pTDFX->height, + !0, pTDFX->cpp); + } + else { + /* cpp==3 needs to bump up to 4 */ + screenSizeInTiles=calcBufferSize(pTDFX->width, pTDFX->height, + !0, 4); + } + + /* + * Layout is: + * cursor, fifo, fb, tex, bb, db + */ + + fbSize = (pTDFX->height + pixmapCacheLinesMin) * pTDFX->stride; + + memRemaining=(pTDFX->mem - 1) &~ 0xFFF; + /* Note that a page is 4096 bytes, and a */ + /* tile is 32 x 128 = 4096 bytes. So, */ + /* page and tile boundaries are the same */ + /* Place the depth offset first, forcing */ + /* it to be on an *odd* page boundary. */ + pTDFX->depthOffset = (memRemaining - screenSizeInTiles) &~ 0xFFF; + if ((pTDFX->depthOffset & (0x1 << 12)) == 0) { + pTDFX->depthOffset -= (0x1 << 12); + } + /* Now, place the back buffer, forcing it */ + /* to be on an *even* page boundary. */ + pTDFX->backOffset = (pTDFX->depthOffset - screenSizeInTiles) &~ 0xFFF; + if (pTDFX->backOffset & (0x1 << 12)) { + pTDFX->backOffset -= (0x1 << 12); + } + /* Give the cmd fifo at least */ + /* CMDFIFO_PAGES pages, but no more than */ + /* 64. NOTE: Don't go higher than 64, as */ + /* there is suspect code in Glide3 ! */ + fifoSize = ((64 <= CMDFIFO_PAGES) ? 64 : CMDFIFO_PAGES) << 12; + + /* We give 4096 bytes to the cursor */ + cursorSize = 0/*4096*/; + cursorOffset = 0; + + pTDFX->fifoOffset = cursorOffset + cursorSize; + pTDFX->fifoSize = fifoSize; + /* Now, place the front buffer, forcing */ + /* it to be on a page boundary too, just */ + /* for giggles. */ + pTDFX->fbOffset = pTDFX->fifoOffset + pTDFX->fifoSize; + pTDFX->textureOffset = pTDFX->fbOffset + fbSize; + if (pTDFX->depthOffset <= pTDFX->textureOffset || + pTDFX->backOffset <= pTDFX->textureOffset) { + /* + * pTDFX->textureSize < 0 means that the DRI is disabled. pTDFX->backOffset + * is used to calculate the maximum amount of memory available for + * 2D offscreen use. With DRI disabled, set this to the top of memory. + */ + + pTDFX->textureSize = -1; + pTDFX->backOffset = pTDFX->mem; + pTDFX->depthOffset = -1; + fprintf(stderr, + "Not enough video memory available for textures and depth buffer\n" + "\tand/or back buffer. Disabling DRI. To use DRI try lower\n" + "\tresolution modes and/or a smaller virtual screen size\n"); + } else { + pTDFX->textureSize = pTDFX->backOffset - pTDFX->textureOffset; + } +} + + +static int createScreen (DRIDriverContext *ctx, TDFXDRIPtr pTDFX) +{ + int err; + + { + int width_bytes = (ctx->shared.virtualWidth * ctx->cpp); + int maxy = ctx->shared.fbSize / width_bytes; + + + if (maxy <= ctx->shared.virtualHeight * 3) { + fprintf(stderr, + "Static buffer allocation failed -- " + "need at least %d kB video memory (have %d kB)\n", + (ctx->shared.virtualWidth * ctx->shared.virtualHeight * + ctx->cpp * 3 + 1023) / 1024, + ctx->shared.fbSize / 1024); + return 0; + } + } + + ctx->shared.SAREASize = SAREA_MAX; + pTDFX->regsSize = ctx->MMIOSize; + + /* Note that drmOpen will try to load the kernel module, if needed. */ + ctx->drmFD = drmOpen("tdfx", NULL ); + if (ctx->drmFD < 0) { + fprintf(stderr, "[drm] drmOpen failed\n"); + return 0; + } + + if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { + fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", + ctx->drmFD, ctx->pciBusID, strerror(-err)); + return 0; + } + + if (drmAddMap( ctx->drmFD, + 0, + ctx->shared.SAREASize, + DRM_SHM, + DRM_CONTAINS_LOCK, + &ctx->shared.hSAREA) < 0) + { + fprintf(stderr, "[drm] drmAddMap failed\n"); + return 0; + } + fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", + ctx->shared.SAREASize, ctx->shared.hSAREA); + + if (drmMap( ctx->drmFD, + ctx->shared.hSAREA, + ctx->shared.SAREASize, + (drmAddressPtr)(&ctx->pSAREA)) < 0) + { + fprintf(stderr, "[drm] drmMap failed\n"); + return 0; + } + memset(ctx->pSAREA, 0, ctx->shared.SAREASize); + fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", + ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); + + /* Need to AddMap the framebuffer and mmio regions here: + */ + if (drmAddMap( ctx->drmFD, + (drmHandle)ctx->FBStart, + ctx->FBSize, + DRM_FRAME_BUFFER, +#ifndef _EMBEDDED + 0, +#else + DRM_READ_ONLY, +#endif + &ctx->shared.hFrameBuffer) < 0) + { + fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); + return 0; + } + + fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", + ctx->shared.hFrameBuffer); + + + if (drmAddMap(ctx->drmFD, + ctx->MMIOStart, + ctx->MMIOSize, + DRM_REGISTERS, + DRM_READ_ONLY, + &pTDFX->regs) < 0) { + fprintf(stderr, "[drm] drmAddMap mmio failed\n"); + return 0; + } + fprintf(stderr, + "[drm] register handle = 0x%08lx\n", pTDFX->regs); + + + /* Create a 'server' context so we can grab the lock for + * initialization ioctls. + */ + if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { + fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); + return 0; + } + + DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); + + /* Initialize the kernel data structures */ + + /* Initialize kernel gart memory manager */ + allocateMemory(ctx, pTDFX); + + /* Initialize the SAREA private data structure */ + + + /* Quick hack to clear the front & back buffers. Could also use + * the clear ioctl to do this, but would need to setup hw state + * first. + */ + + + /* This is the struct passed to tdfx_dri.so for its initialization */ + ctx->driverClientMsg = malloc(sizeof(TDFXDRIRec)); + ctx->driverClientMsgSize = sizeof(TDFXDRIRec); + memcpy(ctx->driverClientMsg, pTDFX, ctx->driverClientMsgSize); + pTDFX = (TDFXDRIPtr)ctx->driverClientMsg; + + /* Don't release the lock now - let the VT switch handler do it. */ + + return 1; +} + + +/** + * \brief Establish the set of modes available for the display. + * + * \param ctx display handle. + * \param numModes will receive the number of supported modes. + * \param modes will point to the list of supported modes. + * + * \return one on success, or zero on failure. + * + * Allocates a single visual and fills it with information according to the + * display bit depth. Supports only 16 and 32 bpp bit depths, aborting + * otherwise. + */ +const __GLcontextModes __glModes[] = { + + /* 32 bit, RGBA Depth=24 Stencil=8 */ + {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE, + .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_TRUE, + .redBits = 8, .greenBits = 8, .blueBits = 8, .alphaBits = 8, + .redMask = 0xff0000, .greenMask = 0xff00, .blueMask = 0xff, .alphaMask = 0xff000000, + .rgbBits = 32, .indexBits = 0, + .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0, + .depthBits = 24, .stencilBits = 8, + .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, }, + + /* 16 bit, RGB Depth=16 */ + {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE, + .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE, + .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0, + .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0, + .rgbBits = 16, .indexBits = 0, + .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0, + .depthBits = 16, .stencilBits = 0, + .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, }, +}; +static int tdfxInitContextModes( const DRIDriverContext *ctx, + int *numModes, const __GLcontextModes **modes) +{ + int n = sizeof(__glModes)/sizeof(__glModes[0]); + const __GLcontextModes *m = &__glModes[0]; + + if (ctx->chipset < PCI_CHIP_VOODOO4) { + n /= 2; + m += n; + } + + *numModes = n; + *modes = m; + + return 1; +} + + +/** + * \brief Validate the fbdev mode. + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Saves some registers and returns 1. + * + * \sa tdfxValidateMode(). + */ +static int tdfxValidateMode( const DRIDriverContext *ctx ) +{ + return 1; +} + + +/** + * \brief Examine mode returned by fbdev. + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Restores registers that fbdev has clobbered and returns 1. + * + * \sa tdfxValidateMode(). + */ +static int tdfxPostValidateMode( const DRIDriverContext *ctx ) +{ + return 1; +} + + +/** + * \brief Initialize the framebuffer device mode + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Before exiting clears the framebuffer memory accessing it directly. + */ +static int tdfxInitFBDev( DRIDriverContext *ctx ) +{ + TDFXDRIPtr pTDFX = calloc(1, sizeof(TDFXDRIRec)); + + { + int dummy = ctx->shared.virtualWidth; + + switch (ctx->bpp / 8) { + case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; + case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; + case 3: + case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; + } + + ctx->shared.virtualWidth = dummy; + } + + ctx->driverPrivate = (void *)pTDFX; + + pTDFX->deviceID = ctx->chipset; + pTDFX->width = ctx->shared.virtualWidth; + pTDFX->height = ctx->shared.virtualHeight; + pTDFX->cpp = ctx->cpp; + pTDFX->mem = ctx->FBSize; /* ->shared.fbSize? mem probe? */ + pTDFX->sarea_priv_offset = sizeof(drm_sarea_t); + + if (!createScreen(ctx, pTDFX)) + return 0; + + return 1; +} + + +/** + * \brief The screen is being closed, so clean up any state and free any + * resources used by the DRI. + * + * \param ctx display handle. + * + * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver + * private data. + */ +static void tdfxHaltFBDev( DRIDriverContext *ctx ) +{ + drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); + drmClose(ctx->drmFD); + + if (ctx->driverPrivate) { + free(ctx->driverPrivate); + ctx->driverPrivate = 0; + } +} + + +/** + * \brief Shutdown the drawing engine. + * + * \param ctx display handle + * + * Turns off the 3D engine & restores the graphics card + * to a state that fbdev understands. + */ +static int tdfxEngineShutdown( const DRIDriverContext *ctx ) +{ + fprintf(stderr, "%s: not implemented\n", __FUNCTION__); + return 1; +} + + +/** + * \brief Restore the drawing engine. + * + * \param ctx display handle + * + * Resets the graphics card and sets initial values for several registers of + * the card's drawing engine. + * + * Turns on 3dfx + */ +static int tdfxEngineRestore( const DRIDriverContext *ctx ) +{ + fprintf(stderr, "%s: not implemented\n", __FUNCTION__); + return 1; +} + + +/** + * \brief Exported driver interface for Mini GLX. + * + * \sa DRIDriverRec. + */ +struct DRIDriverRec __driDriver = { + tdfxInitContextModes, + tdfxValidateMode, + tdfxPostValidateMode, + tdfxInitFBDev, + tdfxHaltFBDev, + tdfxEngineShutdown, + tdfxEngineRestore, + 0 +}; |