summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/radeon.h12
-rw-r--r--src/radeon_dri.c46
-rw-r--r--src/radeon_reg.h3
3 files changed, 18 insertions, 43 deletions
diff --git a/src/radeon.h b/src/radeon.h
index d13beeb..4c3cbcc 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 70ff288..e223825 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 9503dde..a6bbe69 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)