uterm: video: modularize video backends
authorDavid Herrmann <dh.herrmann@googlemail.com>
Fri, 11 Jan 2013 11:16:43 +0000 (12:16 +0100)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Fri, 11 Jan 2013 11:16:43 +0000 (12:16 +0100)
We want to allow dynamic backend loading during runtime so we need to
avoid static definitions. This converts the backend IDs into module
structures which are then linked into the binary.

To make this fully modular, we need to load the backends dynamicly via
dlsym() and move all the static declarations from uterm_video.h into the
backends. But for now at least the backends can be easily exchanged and
configured during compile-time.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
src/kmscon_main.c
src/uterm_video.c
src/uterm_video.h
src/uterm_video_drm.c
src/uterm_video_dumb.c
src/uterm_video_fbdev.c
src/uterm_video_internal.h

index bf07cdc..927ca4d 100644 (file)
@@ -320,7 +320,7 @@ static int app_seat_add_video(struct app_seat *seat,
                              struct uterm_monitor_dev *udev)
 {
        int ret;
-       unsigned int mode;
+       const struct uterm_video_module *mode;
        struct app_video *vid;
 
        if (seat->app->exiting)
@@ -362,13 +362,13 @@ static int app_seat_add_video(struct app_seat *seat,
                mode = UTERM_VIDEO_FBDEV;
        }
 
-       ret = uterm_video_new(&vid->video, seat->app->eloop, mode, node);
+       ret = uterm_video_new(&vid->video, seat->app->eloop, node, mode);
        if (ret) {
                if (mode == UTERM_VIDEO_DRM) {
                        log_info("cannot create drm device %s on seat %s (%d); trying dumb drm mode",
                                 vid->node, seat->name, ret);
                        ret = uterm_video_new(&vid->video, seat->app->eloop,
-                                             UTERM_VIDEO_DUMB, node);
+                                             node, UTERM_VIDEO_DUMB);
                        if (ret)
                                goto err_node;
                } else {
index 082038d..78cf661 100644 (file)
@@ -58,27 +58,15 @@ const char *uterm_dpms_to_name(int dpms)
        }
 }
 
-bool uterm_video_available(unsigned int type)
+bool uterm_video_available(const struct uterm_video_module *mod)
 {
-       switch (type) {
-       case UTERM_VIDEO_DRM:
-#ifdef BUILD_ENABLE_VIDEO_DRM
-               return video_drm_available();
-#endif
+       if (!mod)
                return false;
-       case UTERM_VIDEO_DUMB:
-#ifdef BUILD_ENABLE_VIDEO_DUMB
+
+       if (mod == UTERM_VIDEO_DUMB || mod == UTERM_VIDEO_DRM)
                return video_drm_available();
-#endif
-               return false;
-       case UTERM_VIDEO_FBDEV:
-#ifdef BUILD_ENABLE_VIDEO_FBDEV
-               return true;
-#endif
-               return false;
-       default:
-               return false;
-       }
+
+       return true;
 }
 
 int mode_new(struct uterm_mode **out, const struct mode_ops *ops)
@@ -459,51 +447,24 @@ int uterm_display_fake_blendv(struct uterm_display *disp,
        return VIDEO_CALL(disp->ops->fake_blendv, -EOPNOTSUPP, disp, req, num);
 }
 
-int uterm_video_new(struct uterm_video **out,
-                       struct ev_eloop *eloop,
-                       unsigned int type,
-                       const char *node)
+int uterm_video_new(struct uterm_video **out, struct ev_eloop *eloop,
+                   const char *node, const struct uterm_video_module *mod)
 {
        struct uterm_video *video;
        int ret;
-       const struct video_ops *ops;
 
        if (!out || !eloop)
                return -EINVAL;
-
-       switch (type) {
-       case UTERM_VIDEO_DRM:
-               if (!drm_available) {
-                       log_err("DRM backend is not available");
-                       return -EOPNOTSUPP;
-               }
-               ops = &drm_video_ops;
-               break;
-       case UTERM_VIDEO_DUMB:
-               if (!dumb_available) {
-                       log_err("Dumb DRM backend is not available");
-                       return -EOPNOTSUPP;
-               }
-               ops = &dumb_video_ops;
-               break;
-       case UTERM_VIDEO_FBDEV:
-               if (!fbdev_available) {
-                       log_err("FBDEV backend is not available");
-                       return -EOPNOTSUPP;
-               }
-               ops = &fbdev_video_ops;
-               break;
-       default:
-               log_err("invalid video backend %d", type);
-               return -EINVAL;
-       }
+       if (!mod || !mod->ops)
+               return -EOPNOTSUPP;
 
        video = malloc(sizeof(*video));
        if (!video)
                return -ENOMEM;
        memset(video, 0, sizeof(*video));
        video->ref = 1;
-       video->ops = ops;
+       video->mod = mod;
+       video->ops = mod->ops;
        video->eloop = eloop;
 
        ret = shl_hook_new(&video->hook);
index e30194b..7a2e2f2 100644 (file)
@@ -58,6 +58,7 @@
 struct uterm_mode;
 struct uterm_display;
 struct uterm_video;
+struct uterm_video_module;
 
 enum uterm_display_state {
        UTERM_DISPLAY_ACTIVE,
@@ -74,12 +75,6 @@ enum uterm_display_dpms {
        UTERM_DPMS_UNKNOWN,
 };
 
-enum uterm_video_type {
-       UTERM_VIDEO_DRM,
-       UTERM_VIDEO_DUMB,
-       UTERM_VIDEO_FBDEV,
-};
-
 enum uterm_video_action {
        UTERM_WAKE_UP,
        UTERM_SLEEP,
@@ -135,7 +130,7 @@ typedef void (*uterm_display_cb) (struct uterm_display *disp,
 /* misc */
 
 const char *uterm_dpms_to_name(int dpms);
-bool uterm_video_available(unsigned int type);
+bool uterm_video_available(const struct uterm_video_module *mod);
 
 /* display modes interface */
 
@@ -191,7 +186,7 @@ int uterm_display_fake_blendv(struct uterm_display *disp,
 /* video interface */
 
 int uterm_video_new(struct uterm_video **out, struct ev_eloop *eloop,
-                   unsigned int type, const char *node);
+                   const char *node, const struct uterm_video_module *mod);
 void uterm_video_ref(struct uterm_video *video);
 void uterm_video_unref(struct uterm_video *video);
 
@@ -208,4 +203,24 @@ int uterm_video_wake_up(struct uterm_video *video);
 bool uterm_video_is_awake(struct uterm_video *video);
 void uterm_video_poll(struct uterm_video *video);
 
+/* external modules */
+
+#ifdef BUILD_ENABLE_VIDEO_FBDEV
+extern const struct uterm_video_module *UTERM_VIDEO_FBDEV;
+#else
+#define UTERM_VIDEO_FBDEV NULL
+#endif
+
+#ifdef BUILD_ENABLE_VIDEO_DUMB
+extern const struct uterm_video_module *UTERM_VIDEO_DUMB;
+#else
+#define UTERM_VIDEO_DUMB NULL
+#endif
+
+#ifdef BUILD_ENABLE_VIDEO_DRM
+extern const struct uterm_video_module *UTERM_VIDEO_DRM;
+#else
+#define UTERM_VIDEO_DRM NULL
+#endif
+
 #endif /* UTERM_UTERM_VIDEO_H */
index 0ba6863..3a3ec93 100644 (file)
@@ -66,6 +66,14 @@ static unsigned int mode_get_height(const struct uterm_mode *mode)
        return mode->drm.info.vdisplay;
 }
 
+static const struct mode_ops drm_mode_ops = {
+       .init = NULL,
+       .destroy = NULL,
+       .get_name = mode_get_name,
+       .get_width = mode_get_width,
+       .get_height = mode_get_height,
+};
+
 static void bo_destroy_event(struct gbm_bo *bo, void *data)
 {
        struct drm_rb *rb = data;
@@ -960,6 +968,21 @@ static int display_fill(struct uterm_display *disp,
        return 0;
 }
 
+static const struct display_ops drm_display_ops = {
+       .init = NULL,
+       .destroy = NULL,
+       .activate = display_activate,
+       .deactivate = display_deactivate,
+       .set_dpms = display_set_dpms,
+       .use = display_use,
+       .swap = display_swap,
+       .blit = display_blit,
+       .blend = display_blend,
+       .blendv = display_fake_blendv,
+       .fake_blendv = display_fake_blendv,
+       .fill = display_fill,
+};
+
 static void show_displays(struct uterm_video *video)
 {
        int ret;
@@ -1378,30 +1401,7 @@ static int video_wake_up(struct uterm_video *video)
        return 0;
 }
 
-const struct mode_ops drm_mode_ops = {
-       .init = NULL,
-       .destroy = NULL,
-       .get_name = mode_get_name,
-       .get_width = mode_get_width,
-       .get_height = mode_get_height,
-};
-
-const struct display_ops drm_display_ops = {
-       .init = NULL,
-       .destroy = NULL,
-       .activate = display_activate,
-       .deactivate = display_deactivate,
-       .set_dpms = display_set_dpms,
-       .use = display_use,
-       .swap = display_swap,
-       .blit = display_blit,
-       .blend = display_blend,
-       .blendv = display_fake_blendv,
-       .fake_blendv = display_fake_blendv,
-       .fill = display_fill,
-};
-
-const struct video_ops drm_video_ops = {
+static const struct video_ops drm_video_ops = {
        .init = video_init,
        .destroy = video_destroy,
        .segfault = NULL, /* TODO: reset all saved CRTCs on segfault */
@@ -1410,3 +1410,9 @@ const struct video_ops drm_video_ops = {
        .sleep = video_sleep,
        .wake_up = video_wake_up,
 };
+
+static const struct uterm_video_module drm_module = {
+       .ops = &drm_video_ops,
+};
+
+const struct uterm_video_module *UTERM_VIDEO_DRM = &drm_module;
index cf721d9..b224bb3 100644 (file)
@@ -59,6 +59,14 @@ static unsigned int mode_get_height(const struct uterm_mode *mode)
        return mode->dumb.info.vdisplay;
 }
 
+static const struct mode_ops dumb_mode_ops = {
+       .init = NULL,
+       .destroy = NULL,
+       .get_name = mode_get_name,
+       .get_width = mode_get_width,
+       .get_height = mode_get_height,
+};
+
 static int init_rb(struct uterm_display *disp, struct dumb_rb *rb)
 {
        int ret;
@@ -622,6 +630,21 @@ static int display_fill(struct uterm_display *disp,
        return 0;
 }
 
+static const struct display_ops dumb_display_ops = {
+       .init = NULL,
+       .destroy = NULL,
+       .activate = display_activate,
+       .deactivate = display_deactivate,
+       .set_dpms = display_set_dpms,
+       .use = NULL,
+       .swap = display_swap,
+       .blit = display_blit,
+       .blend = display_blend,
+       .blendv = display_fake_blendv,
+       .fake_blendv = display_fake_blendv,
+       .fill = display_fill,
+};
+
 static void show_displays(struct uterm_video *video)
 {
        int ret;
@@ -929,30 +952,7 @@ static int video_wake_up(struct uterm_video *video)
        return 0;
 }
 
-const struct mode_ops dumb_mode_ops = {
-       .init = NULL,
-       .destroy = NULL,
-       .get_name = mode_get_name,
-       .get_width = mode_get_width,
-       .get_height = mode_get_height,
-};
-
-const struct display_ops dumb_display_ops = {
-       .init = NULL,
-       .destroy = NULL,
-       .activate = display_activate,
-       .deactivate = display_deactivate,
-       .set_dpms = display_set_dpms,
-       .use = NULL,
-       .swap = display_swap,
-       .blit = display_blit,
-       .blend = display_blend,
-       .blendv = display_fake_blendv,
-       .fake_blendv = display_fake_blendv,
-       .fill = display_fill,
-};
-
-const struct video_ops dumb_video_ops = {
+static const struct video_ops dumb_video_ops = {
        .init = video_init,
        .destroy = video_destroy,
        .segfault = NULL, /* TODO: reset all saved CRTCs on segfault */
@@ -961,3 +961,9 @@ const struct video_ops dumb_video_ops = {
        .sleep = video_sleep,
        .wake_up = video_wake_up,
 };
+
+static const struct uterm_video_module dumb_module = {
+       .ops = &dumb_video_ops,
+};
+
+const struct uterm_video_module *UTERM_VIDEO_DUMB = &dumb_module;
index 3285baa..ae96371 100644 (file)
@@ -57,6 +57,14 @@ static unsigned int mode_get_height(const struct uterm_mode *mode)
        return mode->fbdev.height;
 }
 
+static const struct mode_ops fbdev_mode_ops = {
+       .init = NULL,
+       .destroy = NULL,
+       .get_name = mode_get_name,
+       .get_width = mode_get_width,
+       .get_height = mode_get_height,
+};
+
 static int refresh_info(struct uterm_display *disp)
 {
        int ret;
@@ -868,6 +876,21 @@ static int display_fill(struct uterm_display *disp,
        return 0;
 }
 
+static const struct display_ops fbdev_display_ops = {
+       .init = NULL,
+       .destroy = NULL,
+       .activate = display_activate,
+       .deactivate = display_deactivate,
+       .set_dpms = display_set_dpms,
+       .use = NULL,
+       .swap = display_swap,
+       .blit = display_blit,
+       .blend = display_blend,
+       .blendv = display_fake_blendv,
+       .fake_blendv = display_fake_blendv,
+       .fill = display_fill,
+};
+
 static void intro_idle_event(struct ev_eloop *eloop, void *unused, void *data)
 {
        struct uterm_display *disp = data;
@@ -976,30 +999,7 @@ static int video_wake_up(struct uterm_video *video)
        return 0;
 }
 
-const struct mode_ops fbdev_mode_ops = {
-       .init = NULL,
-       .destroy = NULL,
-       .get_name = mode_get_name,
-       .get_width = mode_get_width,
-       .get_height = mode_get_height,
-};
-
-const struct display_ops fbdev_display_ops = {
-       .init = NULL,
-       .destroy = NULL,
-       .activate = display_activate,
-       .deactivate = display_deactivate,
-       .set_dpms = display_set_dpms,
-       .use = NULL,
-       .swap = display_swap,
-       .blit = display_blit,
-       .blend = display_blend,
-       .blendv = display_fake_blendv,
-       .fake_blendv = display_fake_blendv,
-       .fill = display_fill,
-};
-
-const struct video_ops fbdev_video_ops = {
+static const struct video_ops fbdev_video_ops = {
        .init = video_init,
        .destroy = video_destroy,
        .segfault = NULL, /* TODO */
@@ -1008,3 +1008,9 @@ const struct video_ops fbdev_video_ops = {
        .sleep = video_sleep,
        .wake_up = video_wake_up,
 };
+
+static const struct uterm_video_module fbdev_module = {
+       .ops = &fbdev_video_ops,
+};
+
+const struct uterm_video_module *UTERM_VIDEO_FBDEV = &fbdev_module;
index d34b200..e61f107 100644 (file)
@@ -25,8 +25,8 @@
 
 /* Internal definitions */
 
-#ifndef UTERM_VIDEO_H
-#define UTERM_VIDEO_H
+#ifndef UTERM_VIDEO_INTERNAL_H
+#define UTERM_VIDEO_INTERNAL_H
 
 #include <inttypes.h>
 #include <limits.h>
@@ -82,6 +82,10 @@ struct video_ops {
        int (*wake_up) (struct uterm_video *video);
 };
 
+struct uterm_video_module {
+       const struct video_ops *ops;
+};
+
 #define VIDEO_CALL(func, els, ...) (func ? func(__VA_ARGS__) : els)
 
 /* drm */
@@ -145,11 +149,6 @@ struct drm_video {
        GLuint uni_blit_tex;
 };
 
-static const bool drm_available = true;
-extern const struct mode_ops drm_mode_ops;
-extern const struct display_ops drm_display_ops;
-extern const struct video_ops drm_video_ops;
-
 #else /* !BUILD_ENABLE_VIDEO_DRM */
 
 struct drm_mode {
@@ -164,11 +163,6 @@ struct drm_video {
        int unused;
 };
 
-static const bool drm_available = false;
-static const struct mode_ops drm_mode_ops;
-static const struct display_ops drm_display_ops;
-static const struct video_ops drm_video_ops;
-
 #endif /* BUILD_ENABLE_VIDEO_DRM */
 
 /* dumb drm */
@@ -205,11 +199,6 @@ struct dumb_video {
        struct ev_fd *efd;
 };
 
-static const bool dumb_available = true;
-extern const struct mode_ops dumb_mode_ops;
-extern const struct display_ops dumb_display_ops;
-extern const struct video_ops dumb_video_ops;
-
 #else /* !BUILD_ENABLE_VIDEO_DUMB */
 
 struct dumb_mode {
@@ -224,11 +213,6 @@ struct dumb_video {
        int unused;
 };
 
-static const bool dumb_available = false;
-static const struct mode_ops dumb_mode_ops;
-static const struct display_ops dumb_display_ops;
-static const struct video_ops dumb_video_ops;
-
 #endif /* BUILD_ENABLE_VIDEO_DUMB */
 
 /* fbdev */
@@ -275,11 +259,6 @@ struct fbdev_video {
        int unused;
 };
 
-static const bool fbdev_available = true;
-extern const struct mode_ops fbdev_mode_ops;
-extern const struct display_ops fbdev_display_ops;
-extern const struct video_ops fbdev_video_ops;
-
 #else /* !BUILD_ENABLE_VIDEO_FBDEV */
 
 struct fbdev_mode {
@@ -294,11 +273,6 @@ struct fbdev_video {
        int unused;
 };
 
-static const bool fbdev_available = false;
-static const struct mode_ops fbdev_mode_ops;
-static const struct display_ops fbdev_display_ops;
-static const struct video_ops fbdev_video_ops;
-
 #endif /* BUILD_ENABLE_VIDEO_FBDEV */
 
 /* uterm_mode */
@@ -384,6 +358,7 @@ struct uterm_video {
        struct uterm_display *displays;
        struct shl_hook *hook;
 
+       const struct uterm_video_module *mod;
        const struct video_ops *ops;
        union {
                struct drm_video drm;
@@ -429,4 +404,4 @@ static inline bool video_drm_available(void)
 
 #endif
 
-#endif /* UTERM_VIDEO_H */
+#endif /* UTERM_VIDEO_INTERNAL_H */