#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86Priv.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#define PSZ 8
#include "cfb.h"
#undef PSZ
#include "cfb16.h"
#include "cfb32.h"
#include "miline.h"
#include "GL/glxtokens.h"
#include "xf86drm.h"
#include "sarea.h"
#define _XF86DRI_SERVER_
#include "xf86dri.h"
#include "dri.h"
#include "dristruct.h"
#include "GL/glxint.h"
#include "ffb.h"
#include "ffb_regs.h"
#include "ffb_fifo.h"
#include "ffb_rcache.h"
static char FFBKernelDriverName[] = "ffb";
static char FFBClientDriverName[] = "ffb";
static Bool FFBDRICreateContext(ScreenPtr, VisualPtr, drmContext,
void *, DRIContextType);
static void FFBDRIDestroyContext(ScreenPtr, drmContext, DRIContextType);
static void FFBDRIInitBuffers(WindowPtr, RegionPtr, CARD32);
static void FFBDRIMoveBuffers(WindowPtr, DDXPointRec, RegionPtr, CARD32);
static void FFBDRISetDrawableIndex(WindowPtr, CARD32);
extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
void **configprivs);
static Bool
FFBDRIInitVisualConfigs(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
__GLXvisualConfig *pConfigs;
FFBConfigPrivPtr pFfbConfigs;
FFBConfigPrivPtr *pFfbConfigPtrs;
pConfigs = (__GLXvisualConfig *)
xcalloc(sizeof(__GLXvisualConfig), 1);
if (!pConfigs)
return FALSE;
pFfbConfigs = (FFBConfigPrivPtr)
xcalloc(sizeof(FFBConfigPrivRec), 1);
if (!pFfbConfigs) {
xfree(pConfigs);
return FALSE;
}
pFfbConfigPtrs = (FFBConfigPrivPtr *)
xcalloc(sizeof(FFBConfigPrivPtr), 1);
if (!pFfbConfigPtrs) {
xfree(pConfigs);
xfree(pFfbConfigs);
return FALSE;
}
pFfbConfigPtrs[0] = &pFfbConfigs[0];
pConfigs->vid = -1;
pConfigs->class = -1;
pConfigs->rgba = TRUE;
pConfigs->redSize = 8;
pConfigs->greenSize = 8;
pConfigs->blueSize = 8;
pConfigs->alphaSize = 0;
pConfigs->redMask = 0x000000ff;
pConfigs->greenMask = 0x0000ff00;
pConfigs->blueMask = 0x00ff0000;
pConfigs->alphaMask = 0;
pConfigs->accumRedSize = 0;
pConfigs->accumGreenSize = 0;
pConfigs->accumBlueSize = 0;
pConfigs->accumAlphaSize = 0;
pConfigs->doubleBuffer = TRUE;
pConfigs->stereo = FALSE;
pConfigs->bufferSize = 32;
pConfigs->depthSize = 16;
pConfigs->stencilSize = 0;
pConfigs->auxBuffers = 0;
pConfigs->level = 0;
pConfigs->visualRating = 0;
pConfigs->transparentPixel = 0;
pConfigs->transparentRed = 0;
pConfigs->transparentGreen = 0;
pConfigs->transparentBlue = 0;
pConfigs->transparentAlpha = 0;
pConfigs->transparentIndex = 0;
pFfb->numVisualConfigs = 1;
pFfb->pVisualConfigs = pConfigs;
pFfb->pVisualConfigsPriv = pFfbConfigs;
GlxSetVisualConfigs(1, pConfigs, (void **)pFfbConfigPtrs);
return TRUE;
}
static void
init_ffb_sarea(FFBPtr pFfb, ffb_dri_state_t *pFfbSarea)
{
int i;
pFfbSarea->flags = 0;
switch (pFfb->ffb_type) {
case ffb2_prototype:
case ffb2_vertical:
case ffb2_vertical_plus:
case ffb2_horizontal:
case ffb2_horizontal_plus:
pFfbSarea->flags |= FFB_DRI_FFB2;
break;
default:
break;
};
if (pFfb->ffb_type == ffb2_vertical_plus ||
pFfb->ffb_type == ffb2_horizontal_plus)
pFfbSarea->flags |= FFB_DRI_FFB2PLUS;
if (pFfb->dac_info.flags & FFB_DAC_PAC1)
pFfbSarea->flags |= FFB_DRI_PAC1;
if (pFfb->dac_info.flags & FFB_DAC_PAC2)
pFfbSarea->flags |= FFB_DRI_PAC2;
for (i = 0; i < FFB_DRI_NWIDS; i++)
pFfbSarea->wid_table[i] = 0;
}
#define FFB_DFB24_POFF 0x02000000UL
#define FFB_DFB24_SIZE 0x01000000UL
#define FFB_FBC_REGS_POFF 0x00600000UL
#define FFB_FBC_REGS_SIZE 0x00002000UL
#define FFB_DAC_POFF 0x00400000UL
#define FFB_DAC_SIZE 0x00002000UL
#define FFB_SFB8R_POFF 0x04000000UL
#define FFB_SFB8R_SIZE 0x00400000UL
#define FFB_SFB32_POFF 0x05000000UL
#define FFB_SFB32_SIZE 0x01000000UL
#define FFB_SFB64_POFF 0x06000000UL
#define FFB_SFB64_SIZE 0x02000000UL
Bool
FFBDRIScreenInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
DRIInfoPtr pDRIInfo;
FFBDRIPtr pFfbDRI;
if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs"))
return FALSE;
if (!xf86LoaderCheckSymbol("DRIScreenInit"))
return FALSE;
if (!xf86LoaderCheckSymbol("drmAvailable"))
return FALSE;
if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"FFBDRIScreenInit failed (libdri.a too old)\n");
return FALSE;
}
{
int major, minor, patch;
DRIQueryVersion(&major, &minor, &patch);
if (major != 4 || minor < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] FFBDRIScreenInit failed because of a version mismatch.\n"
"[dri] libDRI version is %d.%d.%d but version, 4.0.x is needed.\n"
"[dri] Disabling DRI.\n",
major, minor, patch);
return FALSE;
}
}
pDRIInfo = DRICreateInfoRec();
if (pDRIInfo == NULL)
return FALSE;
pFfb->pDRIInfo = pDRIInfo;
pDRIInfo->drmDriverName = FFBKernelDriverName;
pDRIInfo->clientDriverName = FFBClientDriverName;
pDRIInfo->ddxDriverMajorVersion = 0;
pDRIInfo->ddxDriverMinorVersion = 0;
pDRIInfo->ddxDriverPatchVersion = 1;
pDRIInfo->busIdString = xalloc(64);
sprintf(pDRIInfo->busIdString, "SBUS:%s", pFfb->psdp->device);
pDRIInfo->frameBufferPhysicalAddress = FFB_DFB24_POFF;
pDRIInfo->frameBufferSize = FFB_DFB24_SIZE;
pDRIInfo->frameBufferStride = (2048 * 4);
pDRIInfo->ddxDrawableTableEntry = 15;
pDRIInfo->maxDrawableTableEntry = 15;
pDRIInfo->SAREASize = (SAREA_MAX + (0x2000 - 1)) & ~(0x2000 - 1);
pFfbDRI = (FFBDRIPtr) xcalloc(sizeof(FFBDRIRec), 1);
if (pFfbDRI == NULL) {
DRIDestroyInfoRec(pFfb->pDRIInfo);
return FALSE;
}
pDRIInfo->devPrivate = pFfbDRI;
pDRIInfo->devPrivateSize = sizeof(*pFfbDRI);
pDRIInfo->contextSize = 0;
pDRIInfo->CreateContext = FFBDRICreateContext;
pDRIInfo->DestroyContext = FFBDRIDestroyContext;
pDRIInfo->InitBuffers = FFBDRIInitBuffers;
pDRIInfo->MoveBuffers = FFBDRIMoveBuffers;
pDRIInfo->SetDrawableIndex = FFBDRISetDrawableIndex;
pDRIInfo->bufferRequests = DRI_3D_WINDOWS_ONLY;
pDRIInfo->createDummyCtx = TRUE;
pDRIInfo->createDummyCtxPriv = FALSE;
if (!DRIScreenInit(pScreen, pDRIInfo, &(pFfb->drmSubFD))) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] DRIScreenInit failed. Disabling DRI.\n");
DRIDestroyInfoRec(pFfb->pDRIInfo);
xfree(pFfbDRI);
return FALSE;
}
#if 000
version = drmGetVersion(info->drmFD);
if (version) {
if (version->version_major != 1 ||
version->version_minor < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] FFBDRIScreenInit failed because of a version mismatch.\n"
"[dri] ffb.o kernel module version is %d.%d.%d but version 1.0.x is needed.\n"
"[dri] Disabling the DRI.\n",
version->version_major,
version->version_minor,
version->version_patchlevel);
drmFreeVersion(version);
R128DRICloseScreen(pScreen);
return FALSE;
}
drmFreeVersion(version);
}
#endif
pFfb->pFfbSarea = DRIGetSAREAPrivate(pScreen);
init_ffb_sarea(pFfb, pFfb->pFfbSarea);
if (drmAddMap(pFfb->drmSubFD,
FFB_FBC_REGS_POFF, FFB_FBC_REGS_SIZE,
DRM_REGISTERS, 0, &pFfbDRI->hFbcRegs) < 0) {
DRICloseScreen(pScreen);
return FALSE;
}
pFfbDRI->sFbcRegs = FFB_FBC_REGS_SIZE;
pFfbDRI->mFbcRegs = 0;
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] FBC Register handle = 0x%08x\n",
pFfbDRI->hFbcRegs);
if (drmAddMap(pFfb->drmSubFD,
FFB_DAC_POFF, FFB_DAC_SIZE,
DRM_REGISTERS, 0, &pFfbDRI->hDacRegs) < 0) {
DRICloseScreen(pScreen);
return FALSE;
}
pFfbDRI->sDacRegs = FFB_DAC_SIZE;
pFfbDRI->mDacRegs = 0;
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] DAC Register handle = 0x%08x\n",
pFfbDRI->hDacRegs);
if (drmAddMap(pFfb->drmSubFD,
FFB_SFB8R_POFF, FFB_SFB8R_SIZE,
DRM_REGISTERS, 0, &pFfbDRI->hSfb8r) < 0) {
DRICloseScreen(pScreen);
return FALSE;
}
pFfbDRI->sSfb8r = FFB_SFB8R_SIZE;
pFfbDRI->mSfb8r = 0;
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] SFB8R handle = 0x%08x\n",
pFfbDRI->hSfb8r);
if (drmAddMap(pFfb->drmSubFD,
FFB_SFB32_POFF, FFB_SFB32_SIZE,
DRM_REGISTERS, 0, &pFfbDRI->hSfb32) < 0) {
DRICloseScreen(pScreen);
return FALSE;
}
pFfbDRI->sSfb32 = FFB_SFB32_SIZE;
pFfbDRI->mSfb32 = 0;
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] SFB32 handle = 0x%08x\n",
pFfbDRI->hSfb32);
if (drmAddMap(pFfb->drmSubFD,
FFB_SFB64_POFF, FFB_SFB64_SIZE,
DRM_REGISTERS, 0, &pFfbDRI->hSfb64) < 0) {
DRICloseScreen(pScreen);
return FALSE;
}
pFfbDRI->sSfb64 = FFB_SFB64_SIZE;
pFfbDRI->mSfb64 = 0;
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] SFB64 handle = 0x%08x\n",
pFfbDRI->hSfb64);
if (!FFBDRIInitVisualConfigs(pScreen)) {
DRICloseScreen(pScreen);
return FALSE;
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[drm] Visual configs initialized\n");
return TRUE;
}
void
FFBDRICloseScreen(ScreenPtr pScreen)
{
FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
DRICloseScreen(pScreen);
if (pFfb->pDRIInfo) {
DRIInfoPtr pDRIInfo = pFfb->pDRIInfo;
if (pDRIInfo->devPrivate)
xfree(pDRIInfo->devPrivate);
DRIDestroyInfoRec(pDRIInfo);
pFfb->pDRIInfo = NULL;
}
if (pFfb->pVisualConfigs) {
xfree(pFfb->pVisualConfigs);
pFfb->pVisualConfigs = NULL;
}
if (pFfb->pVisualConfigsPriv) {
xfree(pFfb->pVisualConfigsPriv);
pFfb->pVisualConfigsPriv = NULL;
}
}
static Bool
FFBDRICreateContext(ScreenPtr pScreen, VisualPtr visual, drmContext hwContext,
void *pVisualConfigPriv, DRIContextType context)
{
return TRUE;
}
static void
FFBDRIDestroyContext(ScreenPtr pScreen, drmContext hwContext, DRIContextType context)
{
}
Bool
FFBDRIFinishScreenInit(ScreenPtr pScreen)
{
FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
DRIInfoPtr pDRIInfo = pFfb->pDRIInfo;
FFBDRIPtr pFfbDRI = (FFBDRIPtr) pDRIInfo->devPrivate;
int i;
pDRIInfo->driverSwapMethod = DRI_KERNEL_SWAP;
pFfbDRI->disable_pagefill = pFfb->disable_pagefill;
pFfbDRI->fastfill_small_area = FFB_FFPARMS(pFfb).fastfill_small_area;
pFfbDRI->pagefill_small_area = FFB_FFPARMS(pFfb).pagefill_small_area;
pFfbDRI->fastfill_height = FFB_FFPARMS(pFfb).fastfill_height;
pFfbDRI->fastfill_width = FFB_FFPARMS(pFfb).fastfill_width;
pFfbDRI->pagefill_height = FFB_FFPARMS(pFfb).pagefill_height;
pFfbDRI->pagefill_width = FFB_FFPARMS(pFfb).pagefill_width;
for (i = 0; i < 0x800; i++)
pFfbDRI->Pf_AlignTab[i] = pFfb->Pf_AlignTab[i];
return DRIFinishScreenInit(pScreen);
}
static void
FFBDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
ffb_fbcPtr ffb = pFfb->regs;
unsigned int fbc;
BoxPtr pBox;
int nBox;
fbc = pFfbPrivWin->fbc_base;
fbc = (fbc & ~FFB_FBC_WB_MASK) | FFB_FBC_WB_AB;
fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_ON;
fbc = (fbc & ~FFB_FBC_RGBE_MASK) | FFB_FBC_RGBE_OFF;
pBox = REGION_RECTS(prgn);
nBox = (int) REGION_NUM_RECTS(prgn);
FFB_WRITE_ROP(pFfb, ffb, (FFB_ROP_NEW | (FFB_ROP_NEW << 8)));
FFB_WRITE_PPC(pFfb, ffb,
(FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID),
(FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK));
FFB_WRITE_PMASK(pFfb, ffb, ~0);
FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
FFB_WRITE_FBC(pFfb, ffb, fbc);
FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
while(nBox--) {
register int x, y, w, h;
x = pBox->x1;
y = pBox->y1;
w = (pBox->x2 - x);
h = (pBox->y2 - y);
FFBFifo(pFfb, 4);
FFB_WRITE64(&ffb->by, y, x);
FFB_WRITE64_2(&ffb->bh, h, w);
pBox++;
}
pFfb->rp_active = 1;
FFBSync(pFfb, ffb);
}
static void
FFBDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
RegionPtr prgnSrc, CARD32 index)
{
}
static void
FFBDRISetDrawableIndex(WindowPtr pWin, CARD32 index)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
unsigned int wid;
if (FFBWidIsShared(pFfb, pFfbPrivWin->wid)) {
wid = FFBWidUnshare(pFfb, pFfbPrivWin->wid);
if (wid == (unsigned int) -1)
return;
ErrorF("FFB: Allocated WID %x for DRI window.\n", wid);
pFfbPrivWin->wid = wid;
pFfb->pFfbSarea->wid_table[index] = wid;
}
}