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 -Naur libnsfb.orig/Makefile libnsfb/Makefile
--- libnsfb.orig/Makefile	2019-09-05 15:05:20.000000000 +0000
+++ libnsfb/Makefile	2019-09-05 15:05:32.000000000 +0000
@@ -44,11 +44,19 @@
 
 # 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 -Naur libnsfb.orig/README libnsfb/README
--- libnsfb.orig/README	2019-09-05 15:05:20.000000000 +0000
+++ libnsfb/README	2019-09-05 15:05:32.000000000 +0000
@@ -18,6 +18,7 @@
 
   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 -Naur libnsfb.orig/include/libnsfb.h libnsfb/include/libnsfb.h
--- libnsfb.orig/include/libnsfb.h	2019-09-05 15:05:20.000000000 +0000
+++ libnsfb/include/libnsfb.h	2019-09-05 15:05:32.000000000 +0000
@@ -36,6 +36,7 @@
 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 -Naur libnsfb.orig/src/surface/Makefile libnsfb/src/surface/Makefile
--- libnsfb.orig/src/surface/Makefile	2019-09-05 15:05:20.000000000 +0000
+++ libnsfb/src/surface/Makefile	2019-09-05 15:05:32.000000000 +0000
@@ -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 -Naur libnsfb.orig/src/surface/directfb.c libnsfb/src/surface/directfb.c
--- libnsfb.orig/src/surface/directfb.c	1970-01-01 00:00:00.000000000 +0000
+++ libnsfb/src/surface/directfb.c	2019-09-05 15:05:32.000000000 +0000
@@ -0,0 +1,271 @@
+/*
+ * 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));
+        free(directfb_priv);
+        return -1;
+    }
+
+    ret = DirectFBCreate(&directfb_priv->dfb);
+    if (ret) {
+        fprintf(stderr, "DirectFBCreate failed: %s\n",
+                DirectFBErrorString(ret));
+        free(directfb_priv);
+        return -1;
+    }
+
+    ret = directfb_priv->dfb->GetDisplayLayer(directfb_priv->dfb, DLID_PRIMARY,
+                                              &directfb_priv->layer);
+    if (ret) {
+        fprintf(stderr, "GetDisplayLayer failed: %s\n",
+                DirectFBErrorString(ret));
+        directfb_priv->dfb->Release(directfb_priv->dfb);
+        free(directfb_priv);
+        return -1;
+    }
+
+    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));
+        directfb_priv->layer->Release(directfb_priv->layer);
+        directfb_priv->dfb->Release(directfb_priv->dfb);
+        free(directfb_priv);
+        return -1;
+    }
+
+    ret = directfb_priv->window->GetSurface(directfb_priv->window,
+                                            &directfb_priv->surface);
+    if (ret) {
+        fprintf(stderr, "GetSurface failed: %s\n", DirectFBErrorString(ret));
+        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 -1;
+    }
+
+    directfb_priv->surface->Lock(directfb_priv->surface, DSLF_WRITE,
+                                 (void **)&nsfb->ptr, &nsfb->linelen);
+    directfb_priv->surface->Unlock(directfb_priv->surface);
+
+    ret = directfb_priv->window->SetOpacity(directfb_priv->window, 0xff);
+    if (ret) {
+        fprintf(stderr, "SetOpacity failed: %s\n", DirectFBErrorString(ret));
+        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 -1;
+    }
+
+    ret = directfb_priv->dfb->CreateEventBuffer(directfb_priv->dfb,
+                                                &directfb_priv->buffer);
+    if (ret) {
+        fprintf(stderr, "CreateEventBuffer failed: %s\n",
+                DirectFBErrorString(ret));
+        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 -1;
+    }
+
+    ret = directfb_priv->window->AttachEventBuffer(directfb_priv->window,
+                                                   directfb_priv->buffer);
+    if (ret) {
+        fprintf(stderr, "AttachEventBuffer failed: %s\n",
+                DirectFBErrorString(ret));
+        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 -1;
+    }
+
+    nsfb->surface_priv = directfb_priv;
+
+    return 0;
+}
+
+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