Home | History | Annotate | Line # | Download | only in src
      1 
      2 #ifdef HAVE_CONFIG_H
      3 #include "config.h"
      4 #endif
      5 
      6 #include "xf86.h"
      7 #include "xf86_OSproc.h"
      8 #include "xf86Pci.h"
      9 #include "fb.h"
     10 #include "miline.h"
     11 #include "tdfx.h"
     12 #include "tdfx_dri.h"
     13 #include "tdfx_dripriv.h"
     14 
     15 static char TDFXKernelDriverName[] = "tdfx";
     16 static char TDFXClientDriverName[] = "tdfx";
     17 
     18 static Bool TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual,
     19 			      drm_context_t hwContext, void *pVisualConfigPriv,
     20 			      DRIContextType contextStore);
     21 static void TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
     22 			       DRIContextType contextStore);
     23 static void TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
     24 			       DRIContextType readContextType,
     25 			       void *readContextStore,
     26 			       DRIContextType writeContextType,
     27 			       void *writeContextStore);
     28 static Bool TDFXDRIOpenFullScreen(ScreenPtr pScreen);
     29 static Bool TDFXDRICloseFullScreen(ScreenPtr pScreen);
     30 static void TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
     31 static void TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
     32 			       RegionPtr prgnSrc, CARD32 index);
     33 static void TDFXDRITransitionTo2d(ScreenPtr pScreen);
     34 static void TDFXDRITransitionTo3d(ScreenPtr pScreen);
     35 
     36 static void
     37 TDFXDoWakeupHandler(WAKEUPHANDLER_ARGS_DECL)
     38 {
     39   SCREEN_PTR(arg);
     40   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     41   TDFXPtr pTDFX = TDFXPTR(pScrn);
     42 
     43   pTDFX->pDRIInfo->wrap.WakeupHandler = pTDFX->coreWakeupHandler;
     44   (*pTDFX->pDRIInfo->wrap.WakeupHandler) (WAKEUPHANDLER_ARGS);
     45   pTDFX->pDRIInfo->wrap.WakeupHandler = TDFXDoWakeupHandler;
     46 
     47 
     48   TDFXNeedSync(pScrn);
     49 }
     50 
     51 static void
     52 TDFXDoBlockHandler(BLOCKHANDLER_ARGS_DECL)
     53 {
     54   SCREEN_PTR(arg);
     55   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     56   TDFXPtr pTDFX = TDFXPTR(pScrn);
     57 
     58   TDFXCheckSync(pScrn);
     59 
     60   pTDFX->pDRIInfo->wrap.BlockHandler = pTDFX->coreBlockHandler;
     61   (*pTDFX->pDRIInfo->wrap.BlockHandler) (BLOCKHANDLER_ARGS);
     62   pTDFX->pDRIInfo->wrap.BlockHandler = TDFXDoBlockHandler;
     63 
     64 }
     65 
     66 Bool TDFXDRIScreenInit(ScreenPtr pScreen)
     67 {
     68   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     69   TDFXPtr pTDFX = TDFXPTR(pScrn);
     70   DRIInfoPtr pDRIInfo;
     71   TDFXDRIPtr pTDFXDRI;
     72   Bool bppOk = FALSE;
     73 
     74   switch (pScrn->bitsPerPixel) {
     75   case 16:
     76     bppOk = TRUE;
     77     break;
     78   case 32:
     79     if (pTDFX->ChipType > PCI_CHIP_VOODOO3) {
     80       bppOk = TRUE;
     81     }
     82     break;
     83   }
     84   if (!bppOk) {
     85     xf86DrvMsg(pScreen->myNum, X_ERROR,
     86             "[dri] tdfx DRI not supported in %d bpp mode, disabling DRI.\n",
     87             (pScrn->bitsPerPixel));
     88     if (pTDFX->ChipType <= PCI_CHIP_VOODOO3) {
     89       xf86DrvMsg(pScreen->myNum, X_INFO,
     90               "[dri] To use DRI, invoke the server using 16 bpp\n"
     91 	      "\t(-depth 15 or -depth 16).\n");
     92     } else {
     93       xf86DrvMsg(pScreen->myNum, X_INFO,
     94               "[dri] To use DRI, invoke the server using 16 bpp\n"
     95 	      "\t(-depth 15 or -depth 16) or 32 bpp (-depth 24 -fbbpp 32).\n");
     96     }
     97     return FALSE;
     98   }
     99 
    100     /* Check that the DRI, and DRM modules have been loaded by testing
    101        for canonical symbols in each module. */
    102     if (!xf86LoaderCheckSymbol("drmAvailable"))        return FALSE;
    103     if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
    104       xf86DrvMsg(pScreen->myNum, X_ERROR,
    105                  "TDFXDRIScreenInit failed (libdri.a too old)\n");
    106       return FALSE;
    107     }
    108 
    109   /* Check the DRI version */
    110   {
    111     int major, minor, patch;
    112     DRIQueryVersion(&major, &minor, &patch);
    113     if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
    114       xf86DrvMsg(pScreen->myNum, X_ERROR,
    115                  "[dri] TDFXDRIScreenInit failed because of a version mismatch.\n"
    116                  "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n"
    117                  "[dri] Disabling the DRI.\n",
    118                  major, minor, patch,
    119                  DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
    120       return FALSE;
    121     }
    122   }
    123 
    124   pDRIInfo = DRICreateInfoRec();
    125   if (!pDRIInfo) {
    126     xf86DrvMsg(pScreen->myNum, X_ERROR,
    127                "[dri] DRICreateInfoRect() failed, disabling DRI.\n");
    128     return FALSE;
    129   }
    130 
    131   pTDFX->pDRIInfo = pDRIInfo;
    132 
    133   pDRIInfo->drmDriverName = TDFXKernelDriverName;
    134   pDRIInfo->clientDriverName = TDFXClientDriverName;
    135 #ifdef XSERVER_LIBPCIACCESS
    136     pDRIInfo->busIdString = DRICreatePCIBusID(pTDFX->PciInfo[0]);
    137 #else
    138   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
    139     pDRIInfo->busIdString = DRICreatePCIBusID(pTDFX->PciInfo);
    140   } else {
    141     pDRIInfo->busIdString = malloc(64);
    142     sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
    143 	    ((pciConfigPtr)pTDFX->PciInfo->thisCard)->busnum,
    144 	    ((pciConfigPtr)pTDFX->PciInfo->thisCard)->devnum,
    145 	    ((pciConfigPtr)pTDFX->PciInfo->thisCard)->funcnum);
    146   }
    147 #endif
    148   pDRIInfo->ddxDriverMajorVersion = TDFX_MAJOR_VERSION;
    149   pDRIInfo->ddxDriverMinorVersion = TDFX_MINOR_VERSION;
    150   pDRIInfo->ddxDriverPatchVersion = TDFX_PATCHLEVEL;
    151   pDRIInfo->frameBufferPhysicalAddress = (pointer) pTDFX->LinearAddr[0];
    152   pDRIInfo->frameBufferSize = pTDFX->FbMapSize;
    153   pDRIInfo->frameBufferStride = pTDFX->stride;
    154   pDRIInfo->ddxDrawableTableEntry = TDFX_MAX_DRAWABLES;
    155 
    156   pTDFX->coreBlockHandler = pDRIInfo->wrap.BlockHandler;
    157   pDRIInfo->wrap.BlockHandler = TDFXDoBlockHandler;
    158   pTDFX->coreWakeupHandler = pDRIInfo->wrap.WakeupHandler;
    159   pDRIInfo->wrap.WakeupHandler = TDFXDoWakeupHandler;
    160 
    161   if (SAREA_MAX_DRAWABLES < TDFX_MAX_DRAWABLES)
    162     pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
    163   else
    164     pDRIInfo->maxDrawableTableEntry = TDFX_MAX_DRAWABLES;
    165 
    166 #ifdef NOT_DONE
    167   /* FIXME need to extend DRI protocol to pass this size back to client
    168    * for SAREA mapping that includes a device private record
    169    */
    170   pDRIInfo->SAREASize =
    171     ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
    172   /* + shared memory device private rec */
    173 #else
    174   /* For now the mapping works by using a fixed size defined
    175    * in the SAREA header
    176    */
    177   if (sizeof(XF86DRISAREARec)+sizeof(TDFXSAREAPriv)>SAREA_MAX) {
    178     xf86DrvMsg(pScreen->myNum, X_ERROR, "Data does not fit in SAREA\n");
    179     return FALSE;
    180   }
    181   pDRIInfo->SAREASize = SAREA_MAX;
    182 #endif
    183 
    184   if (!(pTDFXDRI = (TDFXDRIPtr)calloc(sizeof(TDFXDRIRec),1))) {
    185     xf86DrvMsg(pScreen->myNum, X_ERROR,
    186                "[dri] DRI memory allocation failed, disabling DRI.\n");
    187     DRIDestroyInfoRec(pTDFX->pDRIInfo);
    188     pTDFX->pDRIInfo=0;
    189     return FALSE;
    190   }
    191   pDRIInfo->devPrivate = pTDFXDRI;
    192   pDRIInfo->devPrivateSize = sizeof(TDFXDRIRec);
    193   pDRIInfo->contextSize = sizeof(TDFXDRIContextRec);
    194 
    195   pDRIInfo->CreateContext = TDFXCreateContext;
    196   pDRIInfo->DestroyContext = TDFXDestroyContext;
    197   pDRIInfo->SwapContext = TDFXDRISwapContext;
    198   pDRIInfo->InitBuffers = TDFXDRIInitBuffers;
    199   pDRIInfo->MoveBuffers = TDFXDRIMoveBuffers;
    200   pDRIInfo->OpenFullScreen = TDFXDRIOpenFullScreen;
    201   pDRIInfo->CloseFullScreen = TDFXDRICloseFullScreen;
    202   pDRIInfo->TransitionTo2d = TDFXDRITransitionTo2d;
    203   pDRIInfo->TransitionTo3d = TDFXDRITransitionTo3d;
    204   pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
    205 
    206   pDRIInfo->createDummyCtx = FALSE;
    207   pDRIInfo->createDummyCtxPriv = FALSE;
    208 
    209   if (!DRIScreenInit(pScreen, pDRIInfo, &pTDFX->drmSubFD)) {
    210     free(pDRIInfo->devPrivate);
    211     pDRIInfo->devPrivate=0;
    212     DRIDestroyInfoRec(pTDFX->pDRIInfo);
    213     pTDFX->pDRIInfo=0;
    214     xf86DrvMsg(pScreen->myNum, X_ERROR,
    215                "[dri] DRIScreenInit failed, disabling DRI.\n");
    216 
    217     return FALSE;
    218   }
    219 
    220   /* Check the TDFX DRM version */
    221   {
    222      drmVersionPtr version = drmGetVersion(pTDFX->drmSubFD);
    223      if (version) {
    224         if (version->version_major != 1 ||
    225             version->version_minor < 0) {
    226            /* incompatible drm version */
    227            xf86DrvMsg(pScreen->myNum, X_ERROR,
    228                       "[dri] TDFXDRIScreenInit failed because of a version mismatch.\n"
    229                       "[dri] tdfx.o kernel module version is %d.%d.%d but version 1.0.x is needed.\n"
    230                       "[dri] Disabling the DRI.\n",
    231                       version->version_major,
    232                       version->version_minor,
    233                       version->version_patchlevel);
    234            TDFXDRICloseScreen(pScreen);
    235            drmFreeVersion(version);
    236            return FALSE;
    237         }
    238         drmFreeVersion(version);
    239      }
    240   }
    241 
    242   pTDFXDRI->regsSize=TDFXIOMAPSIZE;
    243   if (drmAddMap(pTDFX->drmSubFD, (drm_handle_t)pTDFX->MMIOAddr[0],
    244 		pTDFXDRI->regsSize, DRM_REGISTERS, 0, &pTDFXDRI->regs)<0) {
    245     TDFXDRICloseScreen(pScreen);
    246     xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap failed, disabling DRI.\n");
    247     return FALSE;
    248   }
    249   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
    250 	       pTDFXDRI->regs);
    251 
    252   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "visual configs initialized\n" );
    253 
    254   return TRUE;
    255 }
    256 
    257 void
    258 TDFXDRICloseScreen(ScreenPtr pScreen)
    259 {
    260   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    261   TDFXPtr pTDFX = TDFXPTR(pScrn);
    262 
    263   DRICloseScreen(pScreen);
    264 
    265   if (pTDFX->pDRIInfo) {
    266     if (pTDFX->pDRIInfo->devPrivate) {
    267       free(pTDFX->pDRIInfo->devPrivate);
    268       pTDFX->pDRIInfo->devPrivate=0;
    269     }
    270     DRIDestroyInfoRec(pTDFX->pDRIInfo);
    271     pTDFX->pDRIInfo=0;
    272   }
    273 }
    274 
    275 static Bool
    276 TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual,
    277 		  drm_context_t hwContext, void *pVisualConfigPriv,
    278 		  DRIContextType contextStore)
    279 {
    280   return TRUE;
    281 }
    282 
    283 static void
    284 TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
    285 		   DRIContextType contextStore)
    286 {
    287 }
    288 
    289 Bool
    290 TDFXDRIFinishScreenInit(ScreenPtr pScreen)
    291 {
    292   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    293   TDFXPtr pTDFX = TDFXPTR(pScrn);
    294   TDFXDRIPtr pTDFXDRI;
    295 
    296   pTDFX->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
    297 
    298   pTDFXDRI=(TDFXDRIPtr)pTDFX->pDRIInfo->devPrivate;
    299 #ifdef XSERVER_LIBPCIACCESS
    300   pTDFXDRI->deviceID = DEVICE_ID(pTDFX->PciInfo[0]);
    301 #else
    302   pTDFXDRI->deviceID = DEVICE_ID(pTDFX->PciInfo);
    303 #endif
    304   pTDFXDRI->width=pScrn->virtualX;
    305   pTDFXDRI->height=pScrn->virtualY;
    306   pTDFXDRI->mem=pScrn->videoRam*1024;
    307   pTDFXDRI->cpp=pTDFX->cpp;
    308   pTDFXDRI->stride=pTDFX->stride;
    309   pTDFXDRI->fifoOffset=pTDFX->fifoOffset;
    310   pTDFXDRI->fifoSize=pTDFX->fifoSize;
    311   pTDFXDRI->textureOffset=pTDFX->texOffset;
    312   pTDFXDRI->textureSize=pTDFX->texSize;
    313   pTDFXDRI->fbOffset=pTDFX->fbOffset;
    314   pTDFXDRI->backOffset=pTDFX->backOffset;
    315   pTDFXDRI->depthOffset=pTDFX->depthOffset;
    316   pTDFXDRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
    317   return DRIFinishScreenInit(pScreen);
    318 }
    319 
    320 static void
    321 TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
    322 		   DRIContextType oldContextType, void *oldContext,
    323 		   DRIContextType newContextType, void *newContext)
    324 {
    325 }
    326 
    327 static void
    328 TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
    329 {
    330 #ifdef HAVE_XAA_H
    331   ScreenPtr pScreen = pWin->drawable.pScreen;
    332   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    333   TDFXPtr pTDFX = TDFXPTR(pScrn);
    334   BoxPtr pbox;
    335   int nbox;
    336 
    337   /* It looks nicer if these start out black */
    338   pbox = REGION_RECTS(prgn);
    339   nbox = REGION_NUM_RECTS(prgn);
    340 
    341   TDFXSetupForSolidFill(pScrn, 0, GXcopy, -1);
    342   while (nbox--) {
    343     TDFXSelectBuffer(pTDFX, TDFX_BACK);
    344     TDFXSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
    345 				pbox->x2-pbox->x1, pbox->y2-pbox->y1);
    346     TDFXSelectBuffer(pTDFX, TDFX_DEPTH);
    347     TDFXSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
    348 				pbox->x2-pbox->x1, pbox->y2-pbox->y1);
    349     pbox++;
    350   }
    351   TDFXSelectBuffer(pTDFX, TDFX_FRONT);
    352 
    353 
    354   pTDFX->AccelInfoRec->NeedToSync = TRUE;
    355 #endif
    356 }
    357 
    358 static void
    359 TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
    360 		   RegionPtr prgnSrc, CARD32 index)
    361 {
    362 #ifdef HAVE_XAA_H
    363   ScreenPtr pScreen = pParent->drawable.pScreen;
    364   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    365   TDFXPtr pTDFX = TDFXPTR(pScrn);
    366   int dx, dy, xdir, ydir, i, x, y, nbox;
    367   BoxPtr pbox;
    368 
    369   dx = pParent->drawable.x - ptOldOrg.x;
    370   dy = pParent->drawable.y - ptOldOrg.y;
    371 
    372   DRIMoveBuffersHelper(pScreen, dx, dy, &xdir, &ydir, prgnSrc);
    373 
    374   pbox = REGION_RECTS(prgnSrc);
    375   nbox = REGION_NUM_RECTS(prgnSrc);
    376 
    377   TDFXSetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, ~0, -1);
    378 
    379   TDFXSelectBuffer(pTDFX, TDFX_BACK);
    380   for(i = 0; i < nbox; i++) {
    381      x = pbox[i].x1;
    382      y = pbox[i].y1;
    383      TDFXSubsequentScreenToScreenCopy(pScrn, x, y, x+dx, y+dy,
    384                                       pbox[i].x2 - x, pbox[i].y2 - y);
    385   }
    386 
    387   TDFXSelectBuffer(pTDFX, TDFX_DEPTH);
    388   for(i = 0; i < nbox; i++) {
    389      x = pbox[i].x1;
    390      y = pbox[i].y1;
    391      TDFXSubsequentScreenToScreenCopy(pScrn, x, y, x+dx, y+dy,
    392                                       pbox[i].x2 - x, pbox[i].y2 - y);
    393   }
    394 
    395   TDFXSelectBuffer(pTDFX, TDFX_FRONT);
    396 
    397   pTDFX->AccelInfoRec->NeedToSync = TRUE;
    398 #endif
    399 
    400 }
    401 
    402 /*
    403  * the FullScreen DRI code is dead; this is just left in place to show how
    404  * to set up SLI mode.
    405  */
    406 static Bool
    407 TDFXDRIOpenFullScreen(ScreenPtr pScreen)
    408 {
    409 #if 0
    410   ScrnInfoPtr pScrn;
    411   TDFXPtr pTDFX;
    412 
    413   xf86DrvMsg(pScreen->myNum, X_INFO, "OpenFullScreen\n");
    414   pScrn = xf86ScreenToScrn(pScreen);
    415   pTDFX=TDFXPTR(pScrn);
    416   if (pTDFX->numChips>1) {
    417     TDFXSetupSLI(pScrn);
    418   }
    419 #endif
    420   return TRUE;
    421 }
    422 
    423 static Bool
    424 TDFXDRICloseFullScreen(ScreenPtr pScreen)
    425 {
    426 #if 0
    427   ScrnInfoPtr pScrn;
    428 
    429   xf86DrvMsg(pScreen->myNum, X_INFO, "CloseFullScreen\n");
    430   pScrn = xf86ScreenToScrn(pScreen);
    431   TDFXDisableSLI(pScrn);
    432 #endif
    433   return TRUE;
    434 }
    435 
    436 static void
    437 TDFXDRITransitionTo2d(ScreenPtr pScreen)
    438 {
    439   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    440   TDFXPtr pTDFX = TDFXPTR(pScrn);
    441 
    442   xf86FreeOffscreenArea(pTDFX->reservedArea);
    443 }
    444 
    445 static void
    446 TDFXDRITransitionTo3d(ScreenPtr pScreen)
    447 {
    448   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    449   TDFXPtr pTDFX = TDFXPTR(pScrn);
    450   FBAreaPtr pArea;
    451 
    452   if(pTDFX->overlayBuffer) {
    453 	xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
    454 	pTDFX->overlayBuffer = NULL;
    455   }
    456 
    457   if(pTDFX->overlayBuffer2) {
    458 	xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
    459 	pTDFX->overlayBuffer2 = NULL;
    460   }
    461 
    462   if(pTDFX->textureBuffer) {
    463 	xf86FreeOffscreenArea(pTDFX->textureBuffer);
    464 	pTDFX->textureBuffer = NULL;
    465   }
    466 
    467   xf86PurgeUnlockedOffscreenAreas(pScreen);
    468 
    469   pArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
    470 				    pTDFX->pixmapCacheLinesMin,
    471 				    pScrn->displayWidth, NULL, NULL, NULL);
    472   pTDFX->reservedArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
    473 			pTDFX->pixmapCacheLinesMax - pTDFX->pixmapCacheLinesMin,
    474 			pScrn->displayWidth, NULL, NULL, NULL);
    475   xf86FreeOffscreenArea(pArea);
    476 }
    477