From 7e9a31aa4e0de1e4594a64ebafbe5c0846c9201b Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 25 Apr 2012 17:35:03 +0200 Subject: [PATCH] uterm_video: allow explicitely activating GL ctx We may have to use multiple GL contexts if we mix DRM and fbdev devices. Therefore, we need explicit GL-ctx management. We now allow to explicitely activate a specific GL context. This means, the user needs to use the right GL context before he creates textures or similar. Signed-off-by: David Herrmann --- src/main.c | 4 ++++ src/uterm.h | 1 + src/uterm_internal.h | 6 ++++++ src/uterm_video.c | 8 +++++++ src/uterm_video_drm.c | 49 +++++++++++++++++++++++++++++++------------ 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/main.c b/src/main.c index 6fd0dcb..29d2df8 100644 --- a/src/main.c +++ b/src/main.c @@ -122,6 +122,10 @@ static int setup_app(struct kmscon_app *app) if (ret) goto err_app; + ret = uterm_video_use(app->video); + if (ret) + goto err_app; + ret = kmscon_input_new(&app->input); if (ret) goto err_app; diff --git a/src/uterm.h b/src/uterm.h index fce4dde..dc8d793 100644 --- a/src/uterm.h +++ b/src/uterm.h @@ -183,6 +183,7 @@ void uterm_video_ref(struct uterm_video *video); void uterm_video_unref(struct uterm_video *video); void uterm_video_segfault(struct uterm_video *video); +int uterm_video_use(struct uterm_video *video); struct uterm_display *uterm_video_get_displays(struct uterm_video *video); int uterm_video_register_cb(struct uterm_video *video, uterm_video_cb cb, void *data); diff --git a/src/uterm_internal.h b/src/uterm_internal.h index e845008..a65f6c0 100644 --- a/src/uterm_internal.h +++ b/src/uterm_internal.h @@ -60,6 +60,7 @@ struct video_ops { int (*init) (struct uterm_video *video); void (*destroy) (struct uterm_video *video); void (*segfault) (struct uterm_video *video); + int (*use) (struct uterm_video *video); int (*poll) (struct uterm_video *video, int mask); void (*sleep) (struct uterm_video *video); int (*wake_up) (struct uterm_video *video); @@ -288,4 +289,9 @@ static inline bool video_need_hotplug(const struct uterm_video *video) .action = (act), \ }) +static inline int video_do_use(struct uterm_video *video) +{ + return VIDEO_CALL(video->ops->use, 0, video); +} + #endif /* UTERM_INTERNAL_H */ diff --git a/src/uterm_video.c b/src/uterm_video.c index 444f412..913af9d 100644 --- a/src/uterm_video.c +++ b/src/uterm_video.c @@ -518,6 +518,14 @@ void uterm_video_segfault(struct uterm_video *video) VIDEO_CALL(video->ops->segfault, 0, video); } +int uterm_video_use(struct uterm_video *video) +{ + if (!video) + return -EINVAL; + + return video_do_use(video); +} + struct uterm_display *uterm_video_get_displays(struct uterm_video *video) { if (!video) diff --git a/src/uterm_video_drm.c b/src/uterm_video_drm.c index 15b80e2..e867a62 100644 --- a/src/uterm_video_drm.c +++ b/src/uterm_video_drm.c @@ -163,6 +163,10 @@ static int display_activate(struct uterm_display *disp, struct uterm_mode *mode) if (display_is_online(disp)) return 0; + ret = video_do_use(disp->video); + if (ret) + return ret; + log_info("activating display %p to %ux%u", disp, mode->drm.info.hdisplay, mode->drm.info.vdisplay); @@ -251,6 +255,8 @@ err_saved: static void display_deactivate(struct uterm_display *disp) { + int ret; + if (!display_is_online(disp)) return; @@ -269,6 +275,10 @@ static void display_deactivate(struct uterm_display *disp) disp->drm.saved_crtc = NULL; } + ret = video_do_use(disp->video); + if (ret) + return; + glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &disp->drm.fb); destroy_rb(disp, &disp->drm.rb[1]); @@ -344,9 +354,15 @@ static int display_set_dpms(struct uterm_display *disp, int state) static int display_use(struct uterm_display *disp) { + int ret; + if (!display_is_online(disp)) return -EINVAL; + ret = video_do_use(disp->video); + if (ret) + return ret; + /* TODO: we need triple buffering as a VSYNC may still be pending */ glBindFramebuffer(GL_FRAMEBUFFER, disp->drm.fb); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -622,18 +638,6 @@ static int init_device(struct uterm_video *video, struct udev_device *dev) goto err_disp; } - /* - * We allow only one global video object. See uterm_video_new for the - * reasons. If we every change this we need proper context-management - * and should remove this call here. - */ - if (!eglMakeCurrent(drm->disp, EGL_NO_SURFACE, EGL_NO_SURFACE, - drm->ctx)) { - log_err("cannot activate egl context"); - ret = -EFAULT; - goto err_ctx; - } - ret = ev_eloop_new_fd(video->eloop, &drm->efd, drm->fd, EV_READABLE, event, video); if (ret) @@ -755,7 +759,11 @@ static void video_destroy(struct uterm_video *video) log_info("free drm device"); ev_eloop_rm_fd(drm->efd); - eglMakeCurrent(drm->disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (eglGetCurrentContext() == drm->ctx) + eglMakeCurrent(drm->disp, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + EGL_NO_CONTEXT); eglDestroyContext(drm->disp, drm->ctx); eglTerminate(drm->disp); gbm_device_destroy(drm->gbm); @@ -763,6 +771,20 @@ static void video_destroy(struct uterm_video *video) close(drm->fd); } +static int video_use(struct uterm_video *video) +{ + if (eglGetCurrentContext() == video->drm.ctx) + return 0; + + if (!eglMakeCurrent(video->drm.disp, EGL_NO_SURFACE, EGL_NO_SURFACE, + video->drm.ctx)) { + log_err("cannot activate egl context"); + return -EFAULT; + } + + return 0; +} + static int hotplug(struct uterm_video *video) { drmModeRes *res; @@ -931,6 +953,7 @@ const struct video_ops drm_video_ops = { .init = video_init, .destroy = video_destroy, .segfault = NULL, /* TODO: reset all saved CRTCs on segfault */ + .use = video_use, .poll = video_poll, .sleep = video_sleep, .wake_up = video_wake_up,