diff options
author | Russell King <rmk@arm.linux.org.uk> | 2016-01-28 15:14:55 +0000 |
---|---|---|
committer | Russell King <rmk@arm.linux.org.uk> | 2016-01-28 15:30:27 +0000 |
commit | 3be52b4b7eb30d4d3c3124276cf703a355227f1d (patch) | |
tree | 2b795bbf145106f7853c0ae61cdd530eb2b042a2 | |
parent | 48cb1763e9701ce0698eacd0457c40689b744ed3 (diff) |
src: dri2: fix MSC handling when a pixmap is moved between CRTCs
We need to ensure that a drawable has monotonic MSC values irrespective
of what happens to the drawable - this includes when a drawable is
dragged between different CRTCs. Arrange to handle this, by noticing
that the CRTC has changed, and adapt the MSC value accordingly. We
also need to handle this when setting an event against the current
CRTC.
Signed-off-by: Russell King <rmk@arm.linux.org.uk>
-rw-r--r-- | src/common_drm.c | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/src/common_drm.c b/src/common_drm.c index 8cf277e..92700ce 100644 --- a/src/common_drm.c +++ b/src/common_drm.c @@ -18,6 +18,7 @@ #include "xf86.h" #include "boxutil.h" +#include "pixmaputil.h" #include "common_drm.h" #include "common_drm_helper.h" @@ -69,6 +70,10 @@ static DevPrivateKeyRec pixmap_key; struct common_pixmap { uint32_t handle; void *data; + xf86CrtcPtr crtc; + uint64_t last_ust; + uint64_t last_msc; + int64_t delta_msc; }; static struct common_pixmap *common_drm_pixmap(PixmapPtr pixmap) @@ -1443,14 +1448,45 @@ _X_EXPORT int common_drm_get_drawable_msc(xf86CrtcPtr crtc, DrawablePtr pDraw, uint64_t *ust, uint64_t *msc) { - /* Drawable not displayed, make up a value */ - if (!crtc) { - *ust = 0; - *msc = 0; + struct common_pixmap *drawc; + int ret = Success; + + if (!pDraw && !crtc) { + *ust = *msc = 0; return Success; } - return common_drm_get_msc(crtc, ust, msc); + if (!pDraw) + return common_drm_get_msc(crtc, ust, msc); + + drawc = common_drm_pixmap(drawable_pixmap(pDraw)); + + if (drawc->crtc) { + uint64_t old_ust, old_msc; + + ret = common_drm_get_msc(drawc->crtc, &old_ust, &old_msc); + if (ret == Success) { + drawc->last_ust = old_ust; + drawc->last_msc = old_msc + drawc->delta_msc; + } + } + + if (drawc->crtc != crtc) { + uint64_t new_ust, new_msc; + + drawc->crtc = crtc; + + if (crtc) { + ret = common_drm_get_msc(crtc, &new_ust, &new_msc); + if (ret == Success) + drawc->delta_msc = drawc->last_msc - new_msc; + } + } + + *ust = drawc->last_ust; + *msc = drawc->last_msc; + + return ret; } _X_EXPORT @@ -1483,11 +1519,30 @@ int common_drm_queue_msc_event(ScrnInfoPtr pScrn, xf86CrtcPtr crtc, _X_EXPORT int common_drm_queue_drawable_msc_event(ScrnInfoPtr pScrn, xf86CrtcPtr crtc, - DrawablePtr pDraw, uint64_t *msc, const char *func, Bool nextonmiss, + DrawablePtr pDraw, uint64_t *pmsc, const char *func, Bool nextonmiss, struct common_drm_event *event) { - return common_drm_queue_msc_event(pScrn, crtc, msc, func, nextonmiss, - event); + struct common_pixmap *drawc; + uint64_t msc = *pmsc; + int64_t delta = 0; + int ret; + + /* + * If we have a drawable, we need to correct the MSC for the + * drawable delta. + */ + if (pDraw) { + drawc = common_drm_pixmap(drawable_pixmap(pDraw)); + delta = drawc->delta_msc; + msc -= delta; + } + + ret = common_drm_queue_msc_event(pScrn, crtc, &msc, func, nextonmiss, + event); + + *pmsc = msc + delta; + + return ret; } _X_EXPORT |