⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdfx_dri.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
字号:
/* * 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 64static intcalcBufferStride (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 intcalcBufferHeightInTiles (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 intcalcBufferSize (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,		  (drm_handle_t)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 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 = {   tdfxValidateMode,   tdfxPostValidateMode,   tdfxInitFBDev,   tdfxHaltFBDev,   tdfxEngineShutdown,   tdfxEngineRestore,   0};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -