int display_new(struct uterm_display **out, const struct display_ops *ops) { struct uterm_display *disp; int ret; if (!out || !ops) return -EINVAL; disp = malloc(sizeof(*disp)); if (!disp) return -ENOMEM; memset(disp, 0, sizeof(*disp)); disp->ref = 1; disp->ops = ops; shl_dlist_init(&disp->modes); log_info("new display %p", disp); ret = shl_hook_new(&disp->hook); if (ret) goto err_free; disp->vblank_spec.it_value.tv_nsec = 15 * 1000 * 1000; ret = ev_timer_new(&disp->vblank_timer, NULL, display_vblank_timer_event, disp, NULL, NULL); if (ret) goto err_hook; ret = VIDEO_CALL(disp->ops->init, 0, disp); if (ret) goto err_timer; *out = disp; return 0; err_timer: ev_timer_unref(disp->vblank_timer); err_hook: shl_hook_free(disp->hook); err_free: free(disp); return ret; }
SHL_EXPORT 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; if (!out || !eloop) 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->mod = mod; video->ops = mod->ops; video->eloop = eloop; shl_dlist_init(&video->displays); ret = shl_hook_new(&video->hook); if (ret) goto err_free; ret = VIDEO_CALL(video->ops->init, 0, video, node); if (ret) goto err_hook; ev_eloop_ref(video->eloop); log_info("new device %p", video); *out = video; return 0; err_hook: shl_hook_free(video->hook); err_free: free(video); return ret; }
void uterm_video_unref(struct uterm_video *video) { struct uterm_display *disp; if (!video || !video->ref || --video->ref) return; log_info("free device %p", video); VIDEO_CALL(video->ops->destroy, 0, video); while ((disp = video->displays)) { video->displays = disp->next; disp->next = NULL; uterm_display_unref(disp); } shl_hook_free(video->hook); ev_eloop_unref(video->eloop); free(video); }
SHL_EXPORT void uterm_video_unref(struct uterm_video *video) { struct uterm_display *disp; if (!video || !video->ref || --video->ref) return; log_info("free device %p", video); while (!shl_dlist_empty(&video->displays)) { disp = shl_dlist_entry(video->displays.prev, struct uterm_display, list); uterm_display_unbind(disp); } VIDEO_CALL(video->ops->destroy, 0, video); shl_hook_free(video->hook); ev_eloop_unref(video->eloop); free(video); }
SHL_EXPORT void uterm_display_unref(struct uterm_display *disp) { struct uterm_mode *mode; if (!disp || !disp->ref || --disp->ref) return; log_info("free display %p", disp); while (!shl_dlist_empty(&disp->modes)) { mode = shl_dlist_entry(disp->modes.prev, struct uterm_mode, list); uterm_mode_unbind(mode); } VIDEO_CALL(disp->ops->destroy, 0, disp); ev_timer_unref(disp->vblank_timer); shl_hook_free(disp->hook); free(disp); }
int uterm_video_new(struct uterm_video **out, struct ev_eloop *eloop, unsigned int type, const char *node) { 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; } video = malloc(sizeof(*video)); if (!video) return -ENOMEM; memset(video, 0, sizeof(*video)); video->ref = 1; video->ops = ops; video->eloop = eloop; ret = shl_hook_new(&video->hook); if (ret) goto err_free; ret = VIDEO_CALL(video->ops->init, 0, video, node); if (ret) goto err_hook; ev_eloop_ref(video->eloop); log_info("new device %p", video); *out = video; return 0; err_hook: shl_hook_free(video->hook); err_free: free(video); return ret; }