diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c')
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c | 312 |
1 files changed, 250 insertions, 62 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c index ae4fc5133..b6655c943 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c,v 1.6 2002/10/08 22:14:08 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c,v 1.12 2003/02/08 21:26:57 dawes Exp $ */ /************************************************************************** Copyright 2001 VA Linux Systems Inc., Fremont, California. @@ -41,8 +41,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* - * Authors: Jeff Hartmann <jhartmann@valinux.com> + * Authors: Jeff Hartmann <jhartmann@valinux.com> * David Dawes <dawes@tungstengraphics.com> + * Keith Whitwell <keith@tungstengraphics.com> */ /* @@ -66,6 +67,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86Pci.h" #include "windowstr.h" +#include "shadow.h" #include "GL/glxtokens.h" @@ -91,16 +93,20 @@ static void I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); static void I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 index); +static Bool I830DRICloseFullScreen(ScreenPtr pScreen); +static Bool I830DRIOpenFullScreen(ScreenPtr pScreen); +static void I830DRITransitionTo2d(ScreenPtr pScreen); +static void I830DRITransitionTo3d(ScreenPtr pScreen); +static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen); +static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen); + +static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf); + extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig * configs, void **configprivs); -#ifndef HAVE_DRM_COMMAND -extern drmVersionPtr drmGetLibVersion(int fd); -#endif - -#ifdef HAVE_DRM_COMMAND -Bool +static Bool I830CleanupDma(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); @@ -117,22 +123,8 @@ I830CleanupDma(ScrnInfoPtr pScrn) return TRUE; } -#else -Bool -I830CleanupDma(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - if (!drmI830CleanupDma(pI830->drmSubFD)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Cleanup Failed\n"); - return FALSE; - } - return TRUE; -} -#endif - -#ifdef HAVE_DRM_COMMAND -Bool +static Bool I830InitDma(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); @@ -172,41 +164,25 @@ I830InitDma(ScrnInfoPtr pScrn) return TRUE; } -#else -Bool -I830InitDma(ScrnInfoPtr pScrn) + +static Bool +I830SetParam(ScrnInfoPtr pScrn, int param, int value) { I830Ptr pI830 = I830PTR(pScrn); - I830RingBuffer *ring = &(pI830->LpRing); - I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; - drmI830Init info; - - info.start = ring->mem.Start + pI830->LinearAddr; - info.end = ring->mem.End + pI830->LinearAddr; - info.size = ring->mem.Size; - - info.mmio_offset = (unsigned int)pI830DRI->regs; - info.buffers_offset = (unsigned int)pI830->buffer_map; + drmI830SetParam sp; - info.sarea_off = sizeof(XF86DRISAREARec); + memset(&sp, 0, sizeof(sp)); + sp.param = param; + sp.value = value; - info.front_offset = pI830->FrontBuffer.Start; - info.back_offset = pI830->BackBuffer.Start; - info.depth_offset = pI830->DepthBuffer.Start; - info.w = pScrn->virtualX; - info.h = pScrn->virtualY; - info.pitch = pI830->auxPitch; - info.pitch_bits = pI830->auxPitchBits; - info.cpp = pI830->cpp; - - if (!drmI830InitDma(pI830->drmSubFD, &info)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "I830 Dma Initialization Failed\n"); + if (drmCommandWrite(pI830->drmSubFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 SetParam Failed\n"); return FALSE; } + return TRUE; } -#endif + static Bool I830InitVisualConfigs(ScreenPtr pScreen) @@ -348,11 +324,11 @@ I830InitVisualConfigs(ScreenPtr pScreen) pConfigs[i].redSize = 8; pConfigs[i].greenSize = 8; pConfigs[i].blueSize = 8; - pConfigs[i].alphaSize = 0; + pConfigs[i].alphaSize = 8; pConfigs[i].redMask = 0x00FF0000; pConfigs[i].greenMask = 0x0000FF00; pConfigs[i].blueMask = 0x000000FF; - pConfigs[i].alphaMask = 0xff000000;; + pConfigs[i].alphaMask = 0xFF000000;; if (accum) { pConfigs[i].accumRedSize = 16; pConfigs[i].accumGreenSize = 16; @@ -516,6 +492,12 @@ I830DRIScreenInit(ScreenPtr pScreen) pDRIInfo->InitBuffers = I830DRIInitBuffers; pDRIInfo->MoveBuffers = I830DRIMoveBuffers; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; + pDRIInfo->OpenFullScreen = I830DRIOpenFullScreen; + pDRIInfo->CloseFullScreen = I830DRICloseFullScreen; + pDRIInfo->TransitionTo2d = I830DRITransitionTo2d; + pDRIInfo->TransitionTo3d = I830DRITransitionTo3d; + pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d; + pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d; if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) { xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -531,7 +513,6 @@ I830DRIScreenInit(ScreenPtr pScreen) { drmVersionPtr version; -#if defined(XFree86LOADER) || defined(HAVE_DRM_COMMAND) /* Check the DRM lib version. * drmGetLibVersion was not supported in version 1.0, so check for * symbol first to avoid possible crash or hang. @@ -539,7 +520,6 @@ I830DRIScreenInit(ScreenPtr pScreen) if (xf86LoaderCheckSymbol("drmGetLibVersion")) { version = drmGetLibVersion(pI830->drmSubFD); } else -#endif { /* drmlib version 1.0.0 didn't have the drmGetLibVersion * entry point. Fake it by allocating a version record @@ -552,11 +532,7 @@ I830DRIScreenInit(ScreenPtr pScreen) } #define REQ_MAJ 1 -#ifdef HAVE_DRM_COMMAND #define REQ_MIN 1 -#else -#define REQ_MIN 0 -#endif if (version) { if (version->version_major != REQ_MAJ || version->version_minor < REQ_MIN) { @@ -578,11 +554,11 @@ I830DRIScreenInit(ScreenPtr pScreen) /* Check the i830 DRM version */ version = drmGetVersion(pI830->drmSubFD); if (version) { - if (version->version_major != 1 || version->version_minor < 2) { + if (version->version_major != 1 || version->version_minor < 3) { /* incompatible drm version */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] %s failed because of a version mismatch.\n" - "[dri] i830.o kernel module version is %d.%d.%d but version 1.2 or greater is needed.\n" + "[dri] i830.o kernel module version is %d.%d.%d but version 1.3 or greater is needed.\n" "[dri] Disabling DRI.\n", "I830DRIScreenInit", version->version_major, @@ -591,6 +567,7 @@ I830DRIScreenInit(ScreenPtr pScreen) drmFreeVersion(version); return FALSE; } + pI830->drmMinor = version->version_minor; drmFreeVersion(version); } } @@ -709,6 +686,11 @@ I830DRIDoMappings(ScreenPtr pScreen) I830InitDma(pScrn); + if (pI830->PciInfo->chipType != PCI_CHIP_845_G && + pI830->PciInfo->chipType != PCI_CHIP_I830_M) { + I830SetParam(pScrn, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 ); + } + /* Okay now initialize the dma engine */ if (!pI830DRI->irq) { pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD, @@ -729,6 +711,7 @@ I830DRIDoMappings(ScreenPtr pScreen) #endif } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] dma control initialized, using IRQ %d\n", pI830DRI->irq); @@ -774,9 +757,15 @@ I830DRICloseScreen(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); + I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; DPRINTF(PFX, "I830DRICloseScreen\n"); + if (pI830DRI->irq) { + drmCtlUninstHandler(pI830->drmSubFD); + pI830DRI->irq = 0; + } + I830CleanupDma(pScrn); DRICloseScreen(pScreen); @@ -813,10 +802,22 @@ Bool I830DRIFinishScreenInit(ScreenPtr pScreen) { I830SAREARec *sPriv = (I830SAREARec *) DRIGetSAREAPrivate(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); DPRINTF(PFX, "I830DRIFinishScreenInit\n"); memset(sPriv, 0, sizeof(sPriv)); + + /* Have shadow run only while there is 3d active. + */ + if (pI830->allowPageFlip && pI830->drmMinor >= 3) { + shadowSetup(pScreen); + shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0); + } + else + pI830->allowPageFlip = 0; + return DRIFinishScreenInit(pScreen); } @@ -896,7 +897,7 @@ I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) /* This routine is a modified form of XAADoBitBlt with the calls to * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source * instead of destination. My origin is upside down so the ydir cases - * are reversed. + * are reversed. */ static void I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, @@ -1058,7 +1059,7 @@ I830EmitInvarientState(ScrnInfoPtr pScrn) I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; CARD32 ctx_addr, temp; - BEGIN_LP_RING(128-4); + BEGIN_LP_RING(128-2); ctx_addr = pI830->ContextMem.Start; /* Align to a 2k boundry */ @@ -1274,6 +1275,7 @@ I830EmitInvarientState(ScrnInfoPtr pScrn) TEX_STREAM_COORD_SET(3) | ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3)); +#if 0 OUT_RING(STATE3D_MAP_FILTER_CMD | MAP_UNIT(0) | ENABLE_CHROMA_KEY_PARAMS | @@ -1380,6 +1382,7 @@ I830EmitInvarientState(ScrnInfoPtr pScrn) MAP_UNIT(3) | ENABLE_MAX_MIP_LVL | ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0)); +#endif OUT_RING(STATE3D_MAP_COORD_TRANSFORM); OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0)); @@ -1477,6 +1480,191 @@ I830EmitInvarientState(ScrnInfoPtr pScrn) OUT_RING(MAGIC_W_STATE_DWORD1); OUT_RING(0x3f800000 /* 1.0 in IEEE float */ ); +#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) + + OUT_RING(GFX_OP_STIPPLE); + OUT_RING(0); + ADVANCE_LP_RING(); } +/* Fullscreen hooks. The DRI fullscreen mode can probably be removed + * as it adds little or nothing above the mechanism below. (and isn't + * widely used) + */ +static Bool +I830DRIOpenFullScreen(ScreenPtr pScreen) +{ + return TRUE; +} + +static Bool +I830DRICloseFullScreen(ScreenPtr pScreen) +{ + return TRUE; +} + + + +/* Use callbacks from dri.c to support pageflipping mode for a single + * 3d context without need for any specific full-screen extension. + * + * Also see tdfx driver for example of using these callbacks to + * allocate and free 3d-specific memory on demand. + */ + + + + + +/* Use the miext/shadow module to maintain a list of dirty rectangles. + * These are blitted to the back buffer to keep both buffers clean + * during page-flipping when the 3d application isn't fullscreen. + * + * Unlike most use of the shadow code, both buffers are in video + * memory. + * + * An alternative to this would be to organize for all on-screen + * drawing operations to be duplicated for the two buffers. That + * might be faster, but seems like a lot more work... + */ + + +/* This should be done *before* XAA syncs, + * Otherwise will have to sync again??? + */ +static void +I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + RegionPtr damage = &pBuf->damage; + int i, num = REGION_NUM_RECTS(damage); + BoxPtr pbox = REGION_RECTS(damage); + I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen); + int cmd, br13; + + /* Don't want to do this when no 3d is active and pages are + * right-way-round : + */ + if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0) + return; + + br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); + + if (pScrn->bitsPerPixel == 32) { + cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + br13 |= 3 << 24; + } else { + cmd = (XY_SRC_COPY_BLT_CMD); + br13 |= 1 << 24; + } + + for (i = 0 ; i < num ; i++, pbox++) { + BEGIN_LP_RING(8); + OUT_RING(cmd); + OUT_RING(br13); + OUT_RING((pbox->y1 << 16) | pbox->x1); + OUT_RING((pbox->y2 << 16) | pbox->x2); + OUT_RING(pI830->BackBuffer.Start); + OUT_RING((pbox->y1 << 16) | pbox->x1); + OUT_RING(br13 & 0xffff); + OUT_RING(pI830->FrontBuffer.Start); + ADVANCE_LP_RING(); + } +} + + +static void +I830EnablePageFlip(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + pSAREAPriv->pf_enabled = pI830->allowPageFlip; + pSAREAPriv->pf_active = 0; + + if (pI830->allowPageFlip) { + int br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); + + BEGIN_LP_RING(8); + if (pScrn->bitsPerPixel == 32) { + OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + br13 |= 3 << 24; + } else { + OUT_RING(XY_SRC_COPY_BLT_CMD); + br13 |= 1 << 24; + } + + OUT_RING(br13); + OUT_RING(0); + OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX); + OUT_RING(pI830->BackBuffer.Start); + OUT_RING(0); + OUT_RING(br13 & 0xffff); + OUT_RING(pI830->FrontBuffer.Start); + ADVANCE_LP_RING(); + + pSAREAPriv->pf_active = 1; + } +} + +static void +I830DisablePageFlip(ScreenPtr pScreen) +{ + I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + pSAREAPriv->pf_active = 0; +} + + +static void +I830DRITransitionSingleToMulti3d(ScreenPtr pScreen) +{ + /* Tell the clients not to pageflip. How? + * -- Field in sarea, plus bumping the window counters. + * -- DRM needs to cope with Front-to-Back swapbuffers. + */ + I830DisablePageFlip(pScreen); +} + +static void +I830DRITransitionMultiToSingle3d(ScreenPtr pScreen) +{ + /* Let the remaining 3d app start page flipping again. + */ + I830EnablePageFlip(pScreen); +} + + +static void +I830DRITransitionTo3d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + + I830EnablePageFlip(pScreen); + pI830->have3DWindows = 1; +} + + +static void +I830DRITransitionTo2d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + I830SAREARec *sPriv = (I830SAREARec *) DRIGetSAREAPrivate(pScreen); + + /* Shut down shadowing if we've made it back to the front page: + */ + if (sPriv->pf_current_page == 0) { + I830DisablePageFlip(pScreen); + } + + pI830->have3DWindows = 0; +} + + |