}
}
+static void vt_timeout(struct ev_timer *timer, uint64_t exp, void *data)
+{
+ struct uterm_video *video = data;
+ struct uterm_drm_video *vdrm = video->data;
+ struct uterm_display *disp;
+ struct shl_dlist *iter;
+ int r;
+
+ r = uterm_drm_video_wake_up(video);
+ if (!r) {
+ ev_timer_update(vdrm->vt_timer, NULL);
+ shl_dlist_for_each(iter, &video->displays) {
+ disp = shl_dlist_entry(iter, struct uterm_display, list);
+ VIDEO_CB(video, disp, UTERM_REFRESH);
+ }
+ }
+}
+
+void uterm_drm_video_arm_vt_timer(struct uterm_video *video)
+{
+ struct uterm_drm_video *vdrm = video->data;
+ struct itimerspec spec;
+
+ spec.it_value.tv_sec = 0;
+ spec.it_value.tv_nsec = 20L * 1000L * 1000L; /* 20ms */
+ spec.it_interval = spec.it_value;
+
+ ev_timer_update(vdrm->vt_timer, &spec);
+}
+
int uterm_drm_video_init(struct uterm_video *video, const char *node,
+ const struct display_ops *display_ops,
uterm_drm_page_flip_t pflip, void *data)
{
struct uterm_drm_video *vdrm;
video->data = vdrm;
vdrm->data = data;
vdrm->page_flip = pflip;
+ vdrm->display_ops = display_ops;
vdrm->fd = open(node, O_RDWR | O_CLOEXEC | O_NONBLOCK);
if (vdrm->fd < 0) {
if (ret)
goto err_fd;
+ ret = ev_eloop_new_timer(video->eloop, &vdrm->vt_timer, NULL,
+ vt_timeout, video);
+ if (ret)
+ goto err_timer;
+
video->flags |= VIDEO_HOTPLUG;
return 0;
+err_timer:
+ shl_timer_free(vdrm->timer);
err_fd:
ev_eloop_rm_fd(vdrm->efd);
err_close:
{
struct uterm_drm_video *vdrm = video->data;
+ ev_eloop_rm_timer(vdrm->vt_timer);
ev_eloop_unregister_idle_cb(video->eloop, do_pflips, video, EV_SINGLE);
shl_timer_free(vdrm->timer);
ev_eloop_rm_fd(vdrm->efd);
}
static void bind_display(struct uterm_video *video, drmModeRes *res,
- drmModeConnector *conn,
- const struct display_ops *ops)
+ drmModeConnector *conn)
{
struct uterm_drm_video *vdrm = video->data;
struct uterm_display *disp;
struct uterm_mode *mode;
int ret, i;
- ret = display_new(&disp, ops);
+ ret = display_new(&disp, vdrm->display_ops);
if (ret)
return;
ddrm = disp->data;
}
int uterm_drm_video_hotplug(struct uterm_video *video,
- const struct display_ops *ops,
- bool read_dpms)
+ bool read_dpms, bool modeset)
{
struct uterm_drm_video *vdrm = video->data;
drmModeRes *res;
if (!video_is_awake(video) || !video_need_hotplug(video))
return 0;
+ log_debug("testing DRM hotplug status");
+
res = drmModeGetResources(vdrm->fd);
if (!res) {
log_err("cannot retrieve drm resources");
continue;
disp->flags |= DISPLAY_AVAILABLE;
- if (!read_dpms || !display_is_online(disp))
+ if (!display_is_online(disp))
break;
- dpms = uterm_drm_get_dpms(vdrm->fd, conn);
- if (dpms != disp->dpms) {
- log_debug("DPMS state for display %p changed",
- disp);
- uterm_drm_display_set_dpms(disp, disp->dpms);
+ if (read_dpms) {
+ dpms = uterm_drm_get_dpms(vdrm->fd, conn);
+ if (dpms != disp->dpms) {
+ log_debug("DPMS state for display %p changed",
+ disp);
+ uterm_drm_display_set_dpms(disp, disp->dpms);
+ }
}
+
+ if (modeset) {
+ log_debug("re-activate display %p", disp);
+ uterm_display_use(disp, NULL);
+ uterm_display_swap(disp, true);
+ }
+
break;
}
if (iter == &video->displays)
- bind_display(video, res, conn, ops);
+ bind_display(video, res, conn);
drmModeFreeConnector(conn);
}
return 0;
}
-int uterm_drm_video_wake_up(struct uterm_video *video,
- const struct display_ops *ops)
+int uterm_drm_video_wake_up(struct uterm_video *video)
{
int ret;
struct uterm_drm_video *vdrm = video->data;
return -EACCES;
}
- video->flags |= VIDEO_AWAKE;
- ret = uterm_drm_video_hotplug(video, ops, true);
+ video->flags |= VIDEO_AWAKE | VIDEO_HOTPLUG;
+ ret = uterm_drm_video_hotplug(video, true, true);
if (ret) {
drmDropMaster(vdrm->fd);
return ret;
struct uterm_drm_video *vdrm = video->data;
drmDropMaster(vdrm->fd);
+ ev_timer_drain(vdrm->vt_timer, NULL);
+ ev_timer_update(vdrm->vt_timer, NULL);
}
-int uterm_drm_video_poll(struct uterm_video *video,
- const struct display_ops *ops)
+int uterm_drm_video_poll(struct uterm_video *video)
{
video->flags |= VIDEO_HOTPLUG;
- return uterm_drm_video_hotplug(video, ops, false);
+ return uterm_drm_video_hotplug(video, false, false);
}
/* Waits for events on DRM fd for \mtimeout milliseconds and returns 0 if the