Hi all,

DirectFB may belong to the past, but here is a patch for people still
interested in using it.
A screenshot with NetSurf running directly on top of DirectFB is available on
the HiGFXback (History of graphics backends) project.

Nicolas Caramelli

diff --git a/Makefile b/Makefile
index dd6bbac..9c4d73b 100644
--- a/Makefile
+++ b/Makefile
@@ -44,11 +44,19 @@ NSFB_XCB_PKG_NAMES := xcb xcb-icccm xcb-image
xcb-keysyms xcb-atom

 # determine which surface handlers can be compiled based upon avalable library
 $(eval $(call pkg_config_package_available,NSFB_VNC_AVAILABLE,libvncserver))
+$(eval $(call pkg_config_package_available,NSFB_DIRECTFB_AVAILABLE,directfb))
 $(eval $(call pkg_config_package_available,NSFB_SDL_AVAILABLE,sdl))
 $(eval $(call 
pkg_config_package_available,NSFB_XCB_AVAILABLE,$(NSFB_XCB_PKG_NAMES)))
 $(eval $(call pkg_config_package_available,NSFB_WLD_AVAILABLE,wayland-client))

 # Flags and setup for each support library
+ifeq ($(NSFB_DIRECTFB_AVAILABLE),yes)
+  $(eval $(call pkg_config_package_add_flags,directfb,CFLAGS,LDFLAGS))
+  $(eval $(call pkg_config_package_add_flags,directfb,TESTCFLAGS,TESTLDFLAGS))
+
+  REQUIRED_PKGS := $(REQUIRED_PKGS) directfb
+endif
+
 ifeq ($(NSFB_SDL_AVAILABLE),yes)
   $(eval $(call pkg_config_package_add_flags,sdl,CFLAGS))
   $(eval $(call pkg_config_package_add_flags,sdl,TESTCFLAGS,TESTLDFLAGS))
diff --git a/README b/README
index b4a1685..d4a3820 100644
--- a/README
+++ b/README
@@ -18,6 +18,7 @@ Requirements

   The following libraries may also be installed:

+    +  DirectFB (for the DirectFB surface)
     +  SDL 1.2 (for the SDL surface)
     +  libxcb* (for the X11 surface)
     *  wayland-client (for wayland surface)
diff --git a/include/libnsfb.h b/include/libnsfb.h
index dfb720c..9aec3dd 100644
--- a/include/libnsfb.h
+++ b/include/libnsfb.h
@@ -36,6 +36,7 @@ typedef struct nsfb_bbox_s {
 enum nsfb_type_e {
     NSFB_SURFACE_NONE = 0, /**< No surface */
     NSFB_SURFACE_RAM, /**< RAM surface */
+    NSFB_SURFACE_DIRECTFB, /**< DirectFB surface */
     NSFB_SURFACE_SDL, /**< SDL surface */
     NSFB_SURFACE_LINUX, /**< Linux framebuffer surface */
     NSFB_SURFACE_VNC, /**< VNC surface */
diff --git a/src/surface/Makefile b/src/surface/Makefile
index 848c3d4..d35d1cc 100644
--- a/src/surface/Makefile
+++ b/src/surface/Makefile
@@ -4,6 +4,7 @@
 SURFACE_HANDLER_yes := surface.c ram.c

 # optional surface handlers
+SURFACE_HANDLER_$(NSFB_DIRECTFB_AVAILABLE) += directfb.c
 SURFACE_HANDLER_$(NSFB_SDL_AVAILABLE) += sdl.c
 SURFACE_HANDLER_$(NSFB_XCB_AVAILABLE) += x.c
 SURFACE_HANDLER_$(NSFB_VNC_AVAILABLE) += vnc.c
diff --git a/src/surface/directfb.c b/src/surface/directfb.c
new file mode 100644
index 0000000..4a108a0
--- /dev/null
+++ b/src/surface/directfb.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2019 Nicolas Caramelli
+ *
+ * This file is part of libnsfb, http://www.netsurf-browser.org/
+ * Licenced under the MIT License,
+ *                http://www.opensource.org/licenses/mit-license.php
+ */
+
+#include <directfb.h>
+
+#include "libnsfb.h"
+#include "libnsfb_event.h"
+
+#include "surface.h"
+#include "plot.h"
+
+typedef struct directfb_priv_s {
+    IDirectFB *dfb;
+    IDirectFBDisplayLayer *layer;
+    IDirectFBWindow *window;
+    IDirectFBSurface *surface;
+    IDirectFBEventBuffer *buffer;
+} directfb_priv_t;
+
+static int directfb_set_geometry(nsfb_t *nsfb, int width, int height,
+        enum nsfb_format_e format)
+{
+    if (nsfb->surface_priv != NULL) {
+        return -1;
+    }
+
+    nsfb->width = width;
+    nsfb->height = height;
+    if (format != NSFB_FMT_XRGB8888) {
+        return -1;
+    }
+
+    select_plotters(nsfb);
+
+    return 0;
+}
+
+static int directfb_initialise(nsfb_t *nsfb)
+{
+    directfb_priv_t *directfb_priv;
+    int ret = DFB_OK;
+    DFBWindowDescription desc;
+
+    if (nsfb->surface_priv != NULL) {
+        return -1;
+    }
+
+    directfb_priv = calloc(1, sizeof(directfb_priv_t));
+    if (directfb_priv == NULL) {
+        fprintf(stderr, "DirectFB private data allocation failed\n");
+        return -1;
+    }
+
+    ret = DirectFBInit(NULL, NULL);
+    if (ret) {
+        fprintf(stderr, "DirectFBInit failed: %s\n", DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    ret = DirectFBCreate(&directfb_priv->dfb);
+    if (ret) {
+        fprintf(stderr, "DirectFBCreate failed: %s\n",
+                DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    ret = directfb_priv->dfb->GetDisplayLayer(directfb_priv->dfb, DLID_PRIMARY,
+                                              &directfb_priv->layer);
+    if (ret) {
+        fprintf(stderr, "GetDisplayLayer failed: %s\n",
+                DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    desc.flags = DWDESC_WIDTH | DWDESC_HEIGHT | DSDESC_PIXELFORMAT;
+    desc.width = nsfb->width;
+    desc.height = nsfb->height;
+    desc.pixelformat = DSPF_ARGB;
+    ret = directfb_priv->layer->CreateWindow(directfb_priv->layer, &desc,
+                                             &directfb_priv->window);
+    if (ret) {
+        fprintf(stderr, "CreateWindow failed: %s\n", DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    ret = directfb_priv->window->GetSurface(directfb_priv->window,
+                                            &directfb_priv->surface);
+    if (ret) {
+        fprintf(stderr, "GetSurface failed: %s\n", DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    ret = directfb_priv->surface->Lock(directfb_priv->surface, DSLF_WRITE,
+                                       (void **)&nsfb->ptr, &nsfb->linelen);
+    if (ret) {
+        fprintf(stderr, "Lock failed: %s\n", DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    ret = directfb_priv->surface->Unlock(directfb_priv->surface);
+    if (ret) {
+        fprintf(stderr, "Unlock failed: %s\n", DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    ret = directfb_priv->window->CreateEventBuffer(directfb_priv->window,
+                                                   &directfb_priv->buffer);
+    if (ret) {
+        fprintf(stderr, "CreateEventBuffer failed: %s\n",
+                DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    ret = directfb_priv->window->SetOpacity(directfb_priv->window, 0xff);
+    if (ret) {
+        fprintf(stderr, "SetOpacity failed: %s\n", DirectFBErrorString(ret));
+        goto fail;
+    }
+
+    nsfb->surface_priv = directfb_priv;
+
+    return 0;
+
+fail:
+    if (directfb_priv->buffer)
+        directfb_priv->buffer->Release(directfb_priv->buffer);
+    if (directfb_priv->surface)
+        directfb_priv->surface->Release(directfb_priv->surface);
+    if (directfb_priv->window)
+        directfb_priv->window->Release(directfb_priv->window);
+    if (directfb_priv->layer)
+        directfb_priv->layer->Release(directfb_priv->layer);
+    if (directfb_priv->dfb)
+        directfb_priv->dfb->Release(directfb_priv->dfb);
+    free(directfb_priv);
+    return -1;
+}
+
+static int directfb_finalise(nsfb_t *nsfb)
+{
+    directfb_priv_t *directfb_priv = nsfb->surface_priv;
+
+    if (directfb_priv == NULL) {
+        return 0;
+    }
+
+    directfb_priv->buffer->Release(directfb_priv->buffer);
+    directfb_priv->surface->Release(directfb_priv->surface);
+    directfb_priv->window->Release(directfb_priv->window);
+    directfb_priv->layer->Release(directfb_priv->layer);
+    directfb_priv->dfb->Release(directfb_priv->dfb);
+    free(directfb_priv);
+
+    return 0;
+}
+
+static bool directfb_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
+{
+    directfb_priv_t *directfb_priv = nsfb->surface_priv;
+    int ret = DFB_OK;
+    DFBWindowEvent dfb_event;
+
+    if (directfb_priv == NULL) {
+        return false;
+    }
+
+    ret = directfb_priv->buffer->WaitForEventWithTimeout(directfb_priv->buffer,
+                                                         timeout / 1000,
+                                                         timeout % 1000);
+    if (ret == DFB_TIMEOUT) {
+        event->type = NSFB_EVENT_CONTROL;
+        event->value.controlcode = NSFB_CONTROL_TIMEOUT;
+        return true;
+    }
+
+    directfb_priv->buffer->GetEvent(directfb_priv->buffer,
+                                    (DFBEvent *)&dfb_event);
+
+    if (dfb_event.type == DWET_KEYDOWN) {
+        event->type = NSFB_EVENT_KEY_DOWN;
+        event->value.keycode = dfb_event.key_symbol;
+    } else if (dfb_event.type == DWET_KEYUP) {
+        event->type = NSFB_EVENT_KEY_UP;
+        event->value.keycode = dfb_event.key_symbol;
+    } else if (dfb_event.type == DWET_BUTTONDOWN) {
+        event->type = NSFB_EVENT_KEY_DOWN;
+        switch (dfb_event.button) {
+        case DIBI_LEFT:
+            event->value.keycode = NSFB_KEY_MOUSE_1;
+            break;
+        case DIBI_MIDDLE:
+            event->value.keycode = NSFB_KEY_MOUSE_2;
+            break;
+        case DIBI_RIGHT:
+            event->value.keycode = NSFB_KEY_MOUSE_3;
+            break;
+        default:
+            break;
+        }
+    } else if (dfb_event.type == DWET_BUTTONUP) {
+        event->type = NSFB_EVENT_KEY_UP;
+        switch (dfb_event.button) {
+        case DIBI_LEFT:
+            event->value.keycode = NSFB_KEY_MOUSE_1;
+            break;
+        case DIBI_MIDDLE:
+            event->value.keycode = NSFB_KEY_MOUSE_2;
+            break;
+        case DIBI_RIGHT:
+            event->value.keycode = NSFB_KEY_MOUSE_3;
+            break;
+        default:
+            break;
+      }
+    } else if (dfb_event.type == DWET_MOTION) {
+        event->type = NSFB_EVENT_MOVE_ABSOLUTE;
+        event->value.vector.x = dfb_event.x;
+        event->value.vector.y = dfb_event.y;
+        event->value.vector.z = 0;
+    } else {
+        event->type = NSFB_EVENT_NONE;
+    }
+
+    return true;
+}
+
+static int directfb_update(nsfb_t *nsfb, nsfb_bbox_t *box)
+{
+    directfb_priv_t *directfb_priv = nsfb->surface_priv;
+
+    if (directfb_priv != NULL) {
+        directfb_priv->surface->Flip(directfb_priv->surface,
+                                     (DFBRegion *)box, DSFLIP_WAITFORSYNC);
+    }
+
+    return 0;
+}
+
+const nsfb_surface_rtns_t directfb_rtns = {
+    .geometry = directfb_set_geometry,
+    .initialise = directfb_initialise,
+    .finalise = directfb_finalise,
+    .input = directfb_input,
+    .update = directfb_update,
+};
+
+NSFB_SURFACE_DEF(directfb, NSFB_SURFACE_DIRECTFB, &directfb_rtns)
+
+/*
+ * Local variables:
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ * End:
+ */

Reply via email to