diff --git a/src/i830.h b/src/i830.h index ee0f03a..33ac2ef 100644 --- a/src/i830.h +++ b/src/i830.h @@ -412,6 +412,7 @@ typedef struct _I830Rec { CreateScreenResourcesProcPtr CreateScreenResources; i830_memory *logical_context; + i830_memory *other_context; #ifdef XF86DRI i830_memory *back_buffer; diff --git a/src/i830_accel.c b/src/i830_accel.c index 953a73b..e868c37 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -90,6 +90,21 @@ intel_get_pixmap_pitch(PixmapPtr pPix) #endif } +#include + +static __inline__ void intel_backtrace(void) +{ + void *array[32]; /* deeper nesting than this means something's wrong */ + size_t size, i; + char **strings; + ErrorF("\nBacktrace:\n"); + size = backtrace(array, 32); + strings = backtrace_symbols(array, size); + for (i = 0; i < size; i++) + ErrorF("%d: %s\n", i, strings[i]); + free(strings); +} + int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) { @@ -130,6 +145,7 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) } else if (now - start > timeout_millis) { ErrorF("Error in I830WaitLpRing(), timeout for %d seconds\n", timeout_millis/1000); + intel_backtrace(); if (IS_I965G(pI830)) i965_dump_error_state(pScrn); else diff --git a/src/i830_driver.c b/src/i830_driver.c index e1ab536..3d0b4ff 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -970,6 +970,8 @@ PreInitCleanup(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + RestoreHWState(pScrn); + if (I830IsPrimary(pScrn)) { if (pI830->entityPrivate) pI830->entityPrivate->pScrn_1 = NULL; @@ -1547,7 +1549,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (!xf86InitialConfiguration (pScrn, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); - RestoreHWState(pScrn); PreInitCleanup(pScrn); return FALSE; } @@ -2029,6 +2030,40 @@ SaveHWState(ScrnInfoPtr pScrn) return TRUE; } +static void +i830_restore_other_context(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (pI830->noAccel || pI830->preinit) + return; + + /* Switch back to "other" context */ + { + BEGIN_BATCH(2); + OUT_BATCH(MI_SET_CONTEXT); + OUT_BATCH(pI830->other_context->offset); + ADVANCE_BATCH(); + } +} + +static void +i830_restore_logical_context(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (pI830->noAccel) + return; + + /* Switch back to our context */ + { + BEGIN_BATCH(2); + OUT_BATCH(MI_SET_CONTEXT); + OUT_BATCH(pI830->logical_context->offset); + ADVANCE_BATCH(); + } +} + /* Wait for the PLL to settle down after programming */ static void i830_dpll_settle(void) @@ -2047,6 +2082,8 @@ RestoreHWState(ScrnInfoPtr pScrn) DPRINTF(PFX, "RestoreHWState\n"); + i830_restore_other_context(pScrn); + #ifdef XF86DRI I830DRISetVBlankInterrupt (pScrn, FALSE); #endif @@ -2344,8 +2381,7 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn) BEGIN_BATCH(2); OUT_BATCH(MI_SET_CONTEXT); OUT_BATCH(pI830->logical_context->offset | - CTXT_NO_RESTORE | - CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE); + CTXT_NO_RESTORE | CTXT_PALETTE_RESTORE_DISABLE); ADVANCE_BATCH(); } @@ -3007,9 +3043,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) I830InitVideo(pScreen); #endif - /* Setup 3D engine, needed for rotation too */ - IntelEmitInvarientState(pScrn); - #ifdef XF86DRI if (pI830->directRenderingEnabled) { pI830->directRenderingOpen = TRUE; @@ -3283,7 +3316,21 @@ I830EnterVT(int scrnIndex, int flags) /* Mark 3D state as being clobbered and setup the basics */ *pI830->last_3d = LAST_3D_OTHER; - IntelEmitInvarientState(pScrn); + if (pI830->starting) { + /* Install "other" pointer so subsequent switch will save last + state */ + BEGIN_BATCH(2); + OUT_BATCH(MI_SET_CONTEXT); + OUT_BATCH(pI830->other_context->offset | + CTXT_NO_RESTORE | + CTXT_PALETTE_SAVE_DISABLE | + CTXT_PALETTE_RESTORE_DISABLE); + ADVANCE_BATCH(); + /* Setup 3D engine, needed for rotation too */ + IntelEmitInvarientState(pScrn); + } else { + i830_restore_logical_context(pScrn); + } return TRUE; } diff --git a/src/i830_memory.c b/src/i830_memory.c index 2cac26b..074b3cc 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1383,6 +1383,15 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn) return FALSE; } + /* Space for "other" 3D context. */ + pI830->other_context = i830_allocate_memory(pScrn, "other 3D context", + KB(32), GTT_PAGE_SIZE, 0); + if (pI830->other_context == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to allocate other context space.\n"); + return FALSE; + } + /* even in XAA, 965G needs state mem buffer for rendering */ if (IS_I965G(pI830) && !pI830->noAccel && pI830->exa_965_state == NULL) { pI830->exa_965_state = diff --git a/src/i915_render.c b/src/i915_render.c index fe02e63..ab0089b 100644 --- a/src/i915_render.c +++ b/src/i915_render.c @@ -320,7 +320,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture, uint32_t blendctl; int out_reg = FS_OC; - IntelEmitInvarientState(pScrn); +// IntelEmitInvarientState(pScrn); *pI830->last_3d = LAST_3D_RENDER; if (!i915_get_dest_format(pDstPicture, &dst_format))