diff options
-rw-r--r-- | src/radeon.h | 12 | ||||
-rw-r--r-- | src/radeon_dri.c | 46 | ||||
-rw-r--r-- | src/radeon_reg.h | 3 |
3 files changed, 18 insertions, 43 deletions
diff --git a/src/radeon.h b/src/radeon.h index d13beeb6..4c3cbcca 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -621,6 +621,7 @@ typedef struct { int CPMode; /* CP mode that server/clients use */ int CPFifoSize; /* Size of the CP command FIFO */ int CPusecTimeout; /* CP timeout in usecs */ + Bool needCacheFlush; /* CP ring buffer data */ unsigned long ringStart; /* Offset into GART space */ @@ -986,6 +987,11 @@ do { \ #define RADEONCP_REFRESH(pScrn, info) \ do { \ if (!info->CPInUse) { \ + if (info->needCacheFlush) { \ + RADEON_PURGE_CACHE(); \ + RADEON_PURGE_ZCACHE(); \ + info->needCacheFlush = FALSE; \ + } \ RADEON_WAIT_UNTIL_IDLE(); \ BEGIN_RING(6); \ OUT_RING_REG(RADEON_RE_TOP_LEFT, info->re_top_left); \ @@ -1132,6 +1138,12 @@ do { \ ADVANCE_RING(); \ } while (0) +#define RADEON_PURGE_ZCACHE() \ +do { \ + OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL); \ +} while (0) + #endif /* XF86DRI */ static __inline__ void RADEON_MARK_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn) diff --git a/src/radeon_dri.c b/src/radeon_dri.c index 70ff288b..e2238252 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -357,50 +357,10 @@ static void RADEONEnterServer(ScreenPtr pScreen) RADEON_MARK_SYNC(info, pScrn); pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - if (pSAREAPriv->ctxOwner != DRIGetContext(pScrn->pScreen)) + if (pSAREAPriv->ctxOwner != DRIGetContext(pScrn->pScreen)) { info->XInited3D = FALSE; - - - /* TODO: Fix this more elegantly. - * Sometimes (especially with multiple DRI clients), this code - * runs immediately after a DRI client issues a rendering command. - * - * The accel code regularly inserts WAIT_UNTIL_IDLE into the - * command buffer that is sent with the indirect buffer below. - * The accel code fails to set the 3D cache flush registers for - * the R300 before sending WAIT_UNTIL_IDLE. Sending a cache flush - * on these new registers is not necessary for pure 2D functionality, - * but it *is* necessary after 3D operations. - * Without the cache flushes before WAIT_UNTIL_IDLE, the R300 locks up. - * - * The CP_IDLE call into the DRM indirectly flushes all caches and - * thus avoids the lockup problem, but the solution is far from ideal. - * Better solutions could be: - * - always flush caches when entering the X server - * - track the type of rendering commands somewhere and issue - * cache flushes when they change - * However, I don't feel confident enough with the control flow - * inside the X server to implement either fix. -- nh - */ - - /* On my computer (Radeon Mobility M10) - The fix below results in x11perf -shmput500 rate of 245.0/sec - which is lower than 264.0/sec I get without it. - - Doing the same each time before indirect buffer is submitted - results in x11perf -shmput500 rate of 225.0/sec. - - On the other hand, not using CP acceleration at all benchmarks - at 144.0/sec. - - For now let us accept this as a lesser evil, especially as the - DRM driver for R300 is still in flux. - - Once the code is more stable this should probably be moved into DRM driver. - */ - - if (info->ChipFamily>=CHIP_FAMILY_R300) - drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE); + info->needCacheFlush = (info->ChipFamily >= CHIP_FAMILY_R300); + } #ifdef DAMAGE if (!info->pDamage && info->allowPageFlip) { diff --git a/src/radeon_reg.h b/src/radeon_reg.h index 9503ddeb..a6bbe697 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -1280,6 +1280,9 @@ # define RADEON_RB2D_DC_BUSY (1 << 31) #define RADEON_RB2D_DSTCACHE_MODE 0x3428 +#define RADEON_RB3D_ZCACHE_MODE 0x3250 +#define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254 +# define RADEON_RB3D_ZC_FLUSH_ALL 0x5 #define RADEON_RB3D_DSTCACHE_MODE 0x3258 # define RADEON_RB3D_DC_CACHE_ENABLE (0) # define RADEON_RB3D_DC_2D_CACHE_DISABLE (1) |