summaryrefslogtreecommitdiff
path: root/src/radeon_dri2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/radeon_dri2.c')
-rw-r--r--src/radeon_dri2.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 8ebc6871..27b04e3e 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -31,6 +31,7 @@
#include "radeon.h"
#include "radeon_dri2.h"
+#include "radeon_video.h"
#ifdef DRI2
@@ -67,6 +68,8 @@
#define USE_DRI2_PRIME
#endif
+#define FALLBACK_SWAP_DELAY 16
+
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0, 0)
typedef DRI2BufferPtr BufferPtr;
#else
@@ -1263,6 +1266,14 @@ void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
free(flip);
}
+static
+CARD32 radeon_dri2_deferred_swap(OsTimerPtr timer, CARD32 now, pointer data)
+{
+ TimerFree(timer);
+ radeon_dri2_frame_event_handler(0, 0, 0, data);
+ return 0;
+}
+
/*
* ScheduleSwap is responsible for requesting a DRM vblank event for the
* appropriate frame.
@@ -1292,7 +1303,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
ScreenPtr screen = draw->pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
RADEONInfoPtr info = RADEONPTR(scrn);
- xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, FALSE);
+ xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
drmVBlank vbl;
int ret, flip = 0;
DRI2FrameEventPtr swap_info = NULL;
@@ -1314,7 +1325,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
radeon_dri2_ref_buffer(front);
radeon_dri2_ref_buffer(back);
- /* Drawable not displayed... just complete the swap */
+ /* either off-screen or CRTC not usable... just complete the swap */
if (crtc == NULL)
goto blit_fallback;
@@ -1337,6 +1348,18 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
goto blit_fallback;
}
+ /*
+ * CRTC is in DPMS off state, fallback to blit, but pace the
+ * application at the rate that roughly approximates the
+ * nominal frame rate of the relevant CRTC
+ */
+ if (!radeon_crtc_is_enabled(crtc)) {
+ TimerSet(NULL, 0, FALLBACK_SWAP_DELAY, radeon_dri2_deferred_swap,
+ swap_info);
+ *target_msc = 0;
+ return TRUE;
+ }
+
/* Get current count */
vbl.request.type = DRM_VBLANK_RELATIVE;
vbl.request.type |= populate_vbl_request_type(info, crtc);
@@ -1346,7 +1369,10 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"first get vblank counter failed: %s\n",
strerror(errno));
- goto blit_fallback;
+ TimerSet(NULL, 0, FALLBACK_SWAP_DELAY, radeon_dri2_deferred_swap,
+ swap_info);
+ *target_msc = 0;
+ return TRUE;
}
current_msc = vbl.reply.sequence;
@@ -1395,7 +1421,10 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"divisor 0 get vblank counter failed: %s\n",
strerror(errno));
- goto blit_fallback;
+ TimerSet(NULL, 0, FALLBACK_SWAP_DELAY, radeon_dri2_deferred_swap,
+ swap_info);
+ *target_msc = 0;
+ return TRUE;
}
*target_msc = vbl.reply.sequence + flip;
@@ -1440,7 +1469,10 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"final get vblank counter failed: %s\n",
strerror(errno));
- goto blit_fallback;
+ TimerSet(NULL, 0, FALLBACK_SWAP_DELAY, radeon_dri2_deferred_swap,
+ swap_info);
+ *target_msc = 0;
+ return TRUE;
}
/* Adjust returned value for 1 fame pageflip offset of flip > 0 */