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
15static char TDFXKernelDriverName[] = "tdfx";
16static char TDFXClientDriverName[] = "tdfx";
17
18static Bool TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual,
19			      drm_context_t hwContext, void *pVisualConfigPriv,
20			      DRIContextType contextStore);
21static void TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
22			       DRIContextType contextStore);
23static void TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
24			       DRIContextType readContextType,
25			       void *readContextStore,
26			       DRIContextType writeContextType,
27			       void *writeContextStore);
28static Bool TDFXDRIOpenFullScreen(ScreenPtr pScreen);
29static Bool TDFXDRICloseFullScreen(ScreenPtr pScreen);
30static void TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
31static void TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
32			       RegionPtr prgnSrc, CARD32 index);
33static void TDFXDRITransitionTo2d(ScreenPtr pScreen);
34static void TDFXDRITransitionTo3d(ScreenPtr pScreen);
35
36static void
37TDFXDoWakeupHandler(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
51static void
52TDFXDoBlockHandler(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
66Bool 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
257void
258TDFXDRICloseScreen(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
275static Bool
276TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual,
277		  drm_context_t hwContext, void *pVisualConfigPriv,
278		  DRIContextType contextStore)
279{
280  return TRUE;
281}
282
283static void
284TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
285		   DRIContextType contextStore)
286{
287}
288
289Bool
290TDFXDRIFinishScreenInit(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
320static void
321TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
322		   DRIContextType oldContextType, void *oldContext,
323		   DRIContextType newContextType, void *newContext)
324{
325}
326
327static void
328TDFXDRIInitBuffers(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
358static void
359TDFXDRIMoveBuffers(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 */
406static Bool
407TDFXDRIOpenFullScreen(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
423static Bool
424TDFXDRICloseFullScreen(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
436static void
437TDFXDRITransitionTo2d(ScreenPtr pScreen)
438{
439  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
440  TDFXPtr pTDFX = TDFXPTR(pScrn);
441
442  xf86FreeOffscreenArea(pTDFX->reservedArea);
443}
444
445static void
446TDFXDRITransitionTo3d(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