summaryrefslogtreecommitdiff
path: root/modules/directfb/directfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/directfb/directfb.c')
-rw-r--r--modules/directfb/directfb.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/modules/directfb/directfb.c b/modules/directfb/directfb.c
new file mode 100644
index 0000000..ad98e2b
--- /dev/null
+++ b/modules/directfb/directfb.c
@@ -0,0 +1,191 @@
+/**
+ * @file directfb.c DirectFB video display module
+ *
+ * Copyright (C) 2010 Creytiv.com
+ * Copyright (C) 2013 Andreas Shimokawa <andi@fischlustig.de>
+ */
+#include <re.h>
+#include <rem.h>
+#include <baresip.h>
+#include <directfb.h>
+
+
+struct vidisp_st {
+ struct vidisp *vd; /**< Inheritance (1st) */
+ struct vidsz size; /**< Current size */
+ IDirectFBWindow *window; /**< DirectFB Window */
+ IDirectFBSurface *surface; /**< Surface for pixels */
+ IDirectFBDisplayLayer *layer; /**< Display layer */
+};
+
+
+static IDirectFB *dfb;
+static struct vidisp *vid;
+
+
+static void destructor(void *arg)
+{
+ struct vidisp_st *st = arg;
+
+ if (st->surface)
+ st->surface->Release(st->surface);
+ if (st->window)
+ st->window->Release(st->window);
+ if (st->layer)
+ st->layer->Release(st->layer);
+
+ mem_deref(st->vd);
+}
+
+
+static int alloc(struct vidisp_st **stp, struct vidisp *vd,
+ struct vidisp_prm *prm, const char *dev,
+ vidisp_resize_h *resizeh, void *arg)
+{
+ struct vidisp_st *st;
+ int err = 0;
+
+ /* Not used by DirectFB */
+ (void) prm;
+ (void) dev;
+ (void) resizeh;
+ (void) arg;
+
+ st = mem_zalloc(sizeof(*st), destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->vd = mem_ref(vd);
+
+ dfb->GetDisplayLayer(dfb, DLID_PRIMARY, &st->layer);
+
+ if (err)
+ mem_deref(st);
+ else
+ *stp = st;
+
+ return err;
+}
+
+
+static int display(struct vidisp_st *st, const char *title,
+ const struct vidframe *frame)
+{
+ void *pixels;
+ int pitch, i;
+ unsigned h;
+ uint8_t *p;
+ (void) title;
+
+ if (!vidsz_cmp(&st->size, &frame->size)) {
+ if (st->size.w && st->size.h) {
+ info("directfb: reset: %u x %u ---> %u x %u\n",
+ st->size.w, st->size.h,
+ frame->size.w, frame->size.h);
+ }
+
+ if (st->surface) {
+ st->surface->Release(st->surface);
+ st->surface = NULL;
+ }
+ if (st->window) {
+ st->window->Release(st->window);
+ st->window = NULL;
+ }
+ }
+
+ if (!st->window) {
+ DFBWindowDescription desc;
+
+ desc.flags = DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_PIXELFORMAT;
+ desc.width = frame->size.w;
+ desc.height = frame->size.h;
+ desc.pixelformat = DSPF_I420;
+
+ st->layer->CreateWindow(st->layer, &desc, &st->window);
+
+ st->size = frame->size;
+ st->window->SetOpacity(st->window, 0xff);
+ st->window->GetSurface(st->window, &st->surface);
+ }
+
+ st->surface->Lock(st->surface, DSLF_WRITE, &pixels, &pitch);
+
+ p = pixels;
+ for (i=0; i<3; i++) {
+
+ const uint8_t *s = frame->data[i];
+ const unsigned stp = frame->linesize[0] / frame->linesize[i];
+ const unsigned sz = frame->size.w / stp;
+
+ for (h = 0; h < frame->size.h; h += stp) {
+
+ memcpy(p, s, sz);
+
+ s += frame->linesize[i];
+ p += (pitch / stp);
+ }
+ }
+
+ st->surface->Unlock(st->surface);
+
+ /* Update the screen! */
+ st->surface->Flip(st->surface, 0, 0);
+
+ return 0;
+}
+
+
+static void hide(struct vidisp_st *st)
+{
+ if (!st || !st->window)
+ return;
+
+ st->window->SetOpacity(st->window, 0x00);
+}
+
+
+static int module_init(void)
+{
+ int err = 0;
+ DFBResult ret;
+
+ ret = DirectFBInit(NULL, NULL);
+ if (ret) {
+ DirectFBError("DirectFBInit() failed", ret);
+ return (int) ret;
+ }
+
+ ret = DirectFBCreate(&dfb);
+ if (ret) {
+ DirectFBError("DirectFBCreate() failed", ret);
+ return (int) ret;
+ }
+
+ err = vidisp_register(&vid, "directfb", alloc, NULL, display, hide);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+
+static int module_close(void)
+{
+ vid = mem_deref(vid);
+
+ if (dfb) {
+ dfb->Release(dfb);
+ dfb = NULL;
+ }
+
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(directfb) = {
+ "directfb",
+ "vidisp",
+ module_init,
+ module_close
+};