summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c
diff options
context:
space:
mode:
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.c312
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;
+}
+
+