summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shared-core/radeon_state.c14
-rw-r--r--shared/radeon_state.c14
2 files changed, 26 insertions, 2 deletions
diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c
index 15cd759a..42b48df6 100644
--- a/shared-core/radeon_state.c
+++ b/shared-core/radeon_state.c
@@ -1692,6 +1692,19 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
if ( i < cmdbuf->nbox ) {
if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
return DRM_ERR(EFAULT);
+ /* FIXME The second and subsequent times round this loop, send a
+ * WAIT_UNTIL_3D_IDLE before calling emit_clip_rect(). This
+ * fixes a lockup on fast machines when sending several
+ * cliprects with a cmdbuf, as when waving a 2D window over
+ * a 3D window. Something in the commands from user space
+ * seems to hang the card when they're sent several times
+ * in a row. That would be the correct place to fix it but
+ * this works around it until I can figure that out - Tim Smith */
+ if ( i ) {
+ BEGIN_RING( 2 );
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+ }
radeon_emit_clip_rect( dev_priv, &box );
}
@@ -1700,7 +1713,6 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
ADVANCE_RING();
} while ( ++i < cmdbuf->nbox );
-
if (cmdbuf->nbox == 1)
cmdbuf->nbox = 0;
diff --git a/shared/radeon_state.c b/shared/radeon_state.c
index 15cd759a..42b48df6 100644
--- a/shared/radeon_state.c
+++ b/shared/radeon_state.c
@@ -1692,6 +1692,19 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
if ( i < cmdbuf->nbox ) {
if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
return DRM_ERR(EFAULT);
+ /* FIXME The second and subsequent times round this loop, send a
+ * WAIT_UNTIL_3D_IDLE before calling emit_clip_rect(). This
+ * fixes a lockup on fast machines when sending several
+ * cliprects with a cmdbuf, as when waving a 2D window over
+ * a 3D window. Something in the commands from user space
+ * seems to hang the card when they're sent several times
+ * in a row. That would be the correct place to fix it but
+ * this works around it until I can figure that out - Tim Smith */
+ if ( i ) {
+ BEGIN_RING( 2 );
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+ }
radeon_emit_clip_rect( dev_priv, &box );
}
@@ -1700,7 +1713,6 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
ADVANCE_RING();
} while ( ++i < cmdbuf->nbox );
-
if (cmdbuf->nbox == 1)
cmdbuf->nbox = 0;