sna: Enable kernel support for asynchronous flips
If a flip fails, attempt to restore the previous working configuration (using a modeset) then disable further flipping. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
c95a4002d1
commit
c17d704a5b
|
|
@ -243,6 +243,8 @@ struct sna {
|
|||
#define SNA_PERFORMANCE 0x100
|
||||
#define SNA_POWERSAVE 0x200
|
||||
#define SNA_REMOVE_OUTPUTS 0x400
|
||||
#define SNA_HAS_FLIP 0x10000
|
||||
#define SNA_HAS_ASYNC_FLIP 0x20000
|
||||
#define SNA_REDISCOVER 0x40000000
|
||||
#define SNA_REPROBE 0x80000000
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ union compat_mode_get_connector{
|
|||
#define DEFAULT_DPI 96
|
||||
#endif
|
||||
|
||||
#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
|
||||
|
||||
#if 0
|
||||
#define __DBG DBG
|
||||
#else
|
||||
|
|
@ -4096,6 +4098,9 @@ static int do_page_flip(struct sna *sna, struct kgem_bo *bo,
|
|||
int count = 0;
|
||||
int i;
|
||||
|
||||
if ((sna->flags & (data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP)) == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Queue flips on all enabled CRTCs
|
||||
* Note that if/when we get per-CRTC buffers, we'll have to update this.
|
||||
|
|
@ -4118,32 +4123,42 @@ static int do_page_flip(struct sna *sna, struct kgem_bo *bo,
|
|||
|
||||
arg.crtc_id = crtc->id;
|
||||
arg.fb_id = get_fb(sna, bo, width, height);
|
||||
if (arg.fb_id == 0)
|
||||
goto disable;
|
||||
if (arg.fb_id == 0) {
|
||||
assert(count == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only the reference crtc will finally deliver its page flip
|
||||
* completion event. All other crtc's events will be discarded.
|
||||
*/
|
||||
arg.user_data = (uintptr_t)data;
|
||||
arg.user_data |= crtc->pipe == pipe;
|
||||
arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
|
||||
if (data) {
|
||||
arg.user_data = (uintptr_t)data;
|
||||
arg.user_data |= crtc->pipe == pipe;
|
||||
arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
|
||||
} else {
|
||||
arg.user_data = 0;
|
||||
arg.flags = DRM_MODE_PAGE_FLIP_ASYNC;
|
||||
}
|
||||
arg.reserved = 0;
|
||||
|
||||
DBG(("%s: crtc %d id=%d, pipe=%d, [ref? %d] --> fb %d\n",
|
||||
__FUNCTION__, i, crtc->id, crtc->pipe,
|
||||
crtc->pipe == pipe, arg.fb_id));
|
||||
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
|
||||
DBG(("%s: flip [fb=%d] on crtc %d id=%d failed - %d\n",
|
||||
DBG(("%s: flip [fb=%d] on crtc %d id=%d pipe=%d failed - %d\n",
|
||||
__FUNCTION__, arg.fb_id, i, crtc->id, crtc->pipe, errno));
|
||||
disable:
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
|
||||
"%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
|
||||
__FUNCTION__, crtc->id, crtc->pipe);
|
||||
sna_crtc_disable(config->crtc[i]);
|
||||
continue;
|
||||
"page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
|
||||
crtc->id, crtc->pipe, data ? "synchronous": "asynchronous");
|
||||
if (count && !xf86SetDesiredModes(sna->scrn)) {
|
||||
xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
|
||||
"failed to restore display configuration\n");
|
||||
for (; i < sna->mode.num_real_crtc; i++)
|
||||
sna_crtc_disable(config->crtc[i]);
|
||||
}
|
||||
|
||||
sna->flags &= ~(data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (crtc->bo != bo) {
|
||||
|
|
@ -4522,6 +4537,58 @@ sanitize_outputs(struct sna *sna)
|
|||
config->output[i]->crtc = NULL;
|
||||
}
|
||||
|
||||
static bool has_flip(struct sna *sna)
|
||||
{
|
||||
drm_i915_getparam_t gp;
|
||||
int v;
|
||||
|
||||
if (sna->flags & SNA_NO_FLIP)
|
||||
return false;
|
||||
|
||||
v = 0;
|
||||
|
||||
VG_CLEAR(gp);
|
||||
gp.param = I915_PARAM_HAS_PAGEFLIPPING;
|
||||
gp.value = &v;
|
||||
|
||||
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GETPARAM, &gp))
|
||||
return false;
|
||||
|
||||
VG(VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v)));
|
||||
return v > 0;
|
||||
}
|
||||
|
||||
static bool has_flip__async(struct sna *sna)
|
||||
{
|
||||
#define LOCAL_IOCTL_GET_CAP DRM_IOWR(0x0c, struct local_get_cap)
|
||||
#define DRM_CAP_ASYNC_PAGE_FLIP 0x7
|
||||
struct local_get_cap {
|
||||
uint64_t name;
|
||||
uint64_t value;
|
||||
} cap = { DRM_CAP_ASYNC_PAGE_FLIP };
|
||||
|
||||
if (sna->flags & SNA_NO_FLIP)
|
||||
return false;
|
||||
|
||||
if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_GET_CAP, &cap) == 0)
|
||||
return cap.value > 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
probe_capabilities(struct sna *sna)
|
||||
{
|
||||
sna->flags &= ~(SNA_HAS_FLIP | SNA_HAS_ASYNC_FLIP);
|
||||
if (has_flip(sna))
|
||||
sna->flags |= SNA_HAS_FLIP;
|
||||
if (has_flip__async(sna))
|
||||
sna->flags |= SNA_HAS_ASYNC_FLIP;
|
||||
DBG(("%s: page flips? %s, async? %s\n", __FUNCTION__,
|
||||
sna->flags & SNA_HAS_FLIP ? "enabled" : "disabled",
|
||||
sna->flags & SNA_HAS_ASYNC_FLIP ? "enabled" : "disabled"));
|
||||
}
|
||||
|
||||
static void
|
||||
sna_crtc_config_notify(ScreenPtr screen)
|
||||
{
|
||||
|
|
@ -4529,6 +4596,8 @@ sna_crtc_config_notify(ScreenPtr screen)
|
|||
|
||||
DBG(("%s\n", __FUNCTION__));
|
||||
|
||||
probe_capabilities(sna);
|
||||
|
||||
sna_dri2_reset_scanout(sna);
|
||||
|
||||
sna_mode_update(sna);
|
||||
|
|
@ -4552,6 +4621,8 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
|
|||
return true;
|
||||
}
|
||||
|
||||
probe_capabilities(sna);
|
||||
|
||||
if (!xf86GetOptValInteger(sna->Options, OPTION_VIRTUAL, &num_fake))
|
||||
num_fake = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -1330,7 +1330,7 @@ can_flip(struct sna * sna,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (sna->flags & SNA_NO_FLIP) {
|
||||
if ((sna->flags & (SNA_HAS_FLIP | SNA_HAS_ASYNC_FLIP)) == 0) {
|
||||
DBG(("%s: no, pageflips disabled\n", __FUNCTION__));
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,27 +294,6 @@ static bool has_vsync(struct sna *sna)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool has_pageflipping(struct sna *sna)
|
||||
{
|
||||
drm_i915_getparam_t gp;
|
||||
int v;
|
||||
|
||||
if (sna->flags & SNA_IS_HOSTED)
|
||||
return false;
|
||||
|
||||
v = 0;
|
||||
|
||||
VG_CLEAR(gp);
|
||||
gp.param = I915_PARAM_HAS_PAGEFLIPPING;
|
||||
gp.value = &v;
|
||||
|
||||
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GETPARAM, &gp))
|
||||
return false;
|
||||
|
||||
VG(VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v)));
|
||||
return v > 0;
|
||||
}
|
||||
|
||||
static void sna_setup_capabilities(ScrnInfoPtr scrn, int fd)
|
||||
{
|
||||
#if HAS_PIXMAP_SHARING && defined(DRM_CAP_PRIME)
|
||||
|
|
@ -576,7 +555,7 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
|
|||
sna->flags |= SNA_NO_VSYNC;
|
||||
DBG(("%s: vsync? %s\n", __FUNCTION__, sna->flags & SNA_NO_VSYNC ? "disabled" : "enabled"));
|
||||
|
||||
if (!has_pageflipping(sna) ||
|
||||
if (sna->flags & SNA_IS_HOSTED ||
|
||||
!xf86ReturnOptValBool(sna->Options, OPTION_PAGEFLIP, TRUE))
|
||||
sna->flags |= SNA_NO_FLIP;
|
||||
DBG(("%s: page flips? %s\n", __FUNCTION__, sna->flags & SNA_NO_FLIP ? "disabled" : "enabled"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue