uterm: video: modularize video backends

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>
This commit is contained in:
David Herrmann 2013-01-11 12:16:43 +01:00
parent 81b691b742
commit 694f451ae8
7 changed files with 137 additions and 168 deletions

View 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 {

View 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
if (!mod)
return false;
if (mod == UTERM_VIDEO_DUMB || mod == UTERM_VIDEO_DRM)
return video_drm_available();
#endif
return false;
case UTERM_VIDEO_DUMB:
#ifdef BUILD_ENABLE_VIDEO_DUMB
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);

View 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 */

View 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;

View 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;

View 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;

View 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 */