Limitation is that splash screen is drawn only on the first connector.

Signed-off-by: Vasyl Vavrychuk <vasyl.vavryc...@opensynergy.com>
---
 Makefile.am   |  12 +++-
 configure.ac  |   9 +++
 psplash-drm.c | 179 +++++++++++++++++---------------------------------
 psplash-drm.h |  17 +++++
 psplash.c     |  52 +++++++++++----
 5 files changed, 135 insertions(+), 134 deletions(-)
 create mode 100644 psplash-drm.h

diff --git a/Makefile.am b/Makefile.am
index 375b926..c3d4f03 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,12 +8,20 @@ psplash_SOURCES = psplash.c psplash.h psplash-fb.c 
psplash-fb.h \
                  psplash-poky-img.h psplash-bar-img.h $(FONT_NAME)-font.h \
                  psplash-draw.c psplash-draw.h
 BUILT_SOURCES = psplash-poky-img.h psplash-bar-img.h
+psplash_CPPFLAGS =
+psplash_LDFLAGS =
 
 psplash_write_SOURCES = psplash-write.c psplash.h
 
+if ENABLE_DRM
+psplash_SOURCES += psplash-drm.c psplash-drm.h
+psplash_CPPFLAGS += $(LIBDRM_CFLAGS) -DENABLE_DRM
+psplash_LDFLAGS += $(LIBDRM_LIBS)
+endif
+
 if HAVE_SYSTEMD
-psplash_CPPFLAGS = $(SYSTEMD_CFLAGS) -DHAVE_SYSTEMD
-psplash_LDFLAGS= $(SYSTEMD_LIBS)
+psplash_CPPFLAGS += $(SYSTEMD_CFLAGS) -DHAVE_SYSTEMD
+psplash_LDFLAGS += $(SYSTEMD_LIBS)
 bin_PROGRAMS += psplash-systemd
 psplash_systemd_CPPFLAGS = $(SYSTEMD_CFLAGS)
 psplash_systemd_LDFLAGS= $(SYSTEMD_LIBS)
diff --git a/configure.ac b/configure.ac
index 2a7da91..2e5c4f5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,6 +12,15 @@ if test "x$GCC" = "xyes"; then
         GCC_FLAGS="-g -Wall -Wextra"
 fi
 
+AC_ARG_ENABLE(drm,
+    AS_HELP_STRING([--enable-drm], [enable drm backend (default is 'no')]))
+
+AS_IF([test "x$enable_drm" = "xyes"], [
+    PKG_CHECK_MODULES(LIBDRM, libdrm)
+])
+
+AM_CONDITIONAL([ENABLE_DRM], [test "x$enable_drm" = "xyes"])
+
 AC_ARG_WITH([systemd], AS_HELP_STRING([--with-systemd], [Build with systemd
             support]))
 
diff --git a/psplash-drm.c b/psplash-drm.c
index c9a9f5c..30850ed 100644
--- a/psplash-drm.c
+++ b/psplash-drm.c
@@ -26,10 +26,8 @@
  * provided by some external library.
  */
 
-#define _GNU_SOURCE
 #include <errno.h>
 #include <fcntl.h>
-#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -39,6 +37,7 @@
 #include <unistd.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
+#include "psplash-drm.h"
 
 struct modeset_dev;
 static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
@@ -48,8 +47,6 @@ static int modeset_setup_dev(int fd, drmModeRes *res, 
drmModeConnector *conn,
                             struct modeset_dev *dev);
 static int modeset_open(int *out, const char *node);
 static int modeset_prepare(int fd);
-static void modeset_draw(void);
-static void modeset_cleanup(int fd);
 
 /*
  * When the linux kernel detects a graphics-card on your machine, it loads the
@@ -153,7 +150,7 @@ struct modeset_dev {
        uint32_t stride;
        uint32_t size;
        uint32_t handle;
-       uint8_t *map;
+       void *map;
 
        drmModeModeInfo mode;
        uint32_t fb;
@@ -187,7 +184,7 @@ static int modeset_prepare(int fd)
 {
        drmModeRes *res;
        drmModeConnector *conn;
-       unsigned int i;
+       int i;
        struct modeset_dev *dev;
        int ret;
 
@@ -338,11 +335,10 @@ static int modeset_find_crtc(int fd, drmModeRes *res, 
drmModeConnector *conn,
                             struct modeset_dev *dev)
 {
        drmModeEncoder *enc;
-       unsigned int i, j;
-       int32_t crtc;
+       int i, j, crtc;
        struct modeset_dev *iter;
 
-       /* first try the currently conected encoder+crtc */
+       /* first try the currently connected encoder+crtc */
        if (conn->encoder_id)
                enc = drmModeGetEncoder(fd, conn->encoder_id);
        else
@@ -352,7 +348,7 @@ static int modeset_find_crtc(int fd, drmModeRes *res, 
drmModeConnector *conn,
                if (enc->crtc_id) {
                        crtc = enc->crtc_id;
                        for (iter = modeset_list; iter; iter = iter->next) {
-                               if (iter->crtc == crtc) {
+                               if (iter->crtc == (uint32_t)crtc) {
                                        crtc = -1;
                                        break;
                                }
@@ -389,7 +385,7 @@ static int modeset_find_crtc(int fd, drmModeRes *res, 
drmModeConnector *conn,
                        /* check that no other device already uses this CRTC */
                        crtc = res->crtcs[j];
                        for (iter = modeset_list; iter; iter = iter->next) {
-                               if (iter->crtc == crtc) {
+                               if (iter->crtc == (uint32_t)crtc) {
                                        crtc = -1;
                                        break;
                                }
@@ -503,6 +499,12 @@ err_destroy:
        return ret;
 }
 
+static void psplash_drm_flip(PSplashCanvas *canvas, int sync)
+{
+       (void)canvas;
+       (void)sync;
+}
+
 /*
  * Finally! We have a connector with a suitable CRTC. We know which mode we 
want
  * to use and we have a framebuffer of the correct size that we can write to.
@@ -532,155 +534,89 @@ err_destroy:
  * also often not guaranteed. So instead, we only use one connector per CRTC.
  *
  * Before calling drmModeSetCrtc() we also save the current CRTC configuration.
- * This is used in modeset_cleanup() to restore the CRTC to the same mode as 
was
- * before we changed it.
+ * This is used in psplash_drm_destroy() to restore the CRTC to the same mode 
as
+ * was before we changed it.
  * If we don't do this, the screen will stay blank after we exit until another
  * application performs modesetting itself.
  */
 
-int main(int argc, char **argv)
+PSplashDRM* psplash_drm_new(int angle, int dev_id)
 {
-       int ret, fd;
-       const char *card;
+       PSplashDRM *drm = NULL;
+       int ret;
+       char card[] = "/dev/dri/card0";
        struct modeset_dev *iter;
 
-       /* check which DRM device to open */
-       if (argc > 1)
-               card = argv[1];
-       else
-               card = "/dev/dri/card0";
+       if ((drm = malloc(sizeof(*drm))) == NULL) {
+               perror("malloc");
+               goto error;
+       }
+       drm->canvas.priv = drm;
+       drm->canvas.flip = psplash_drm_flip;
+
+       if (dev_id > 0 && dev_id < 10) {
+               // Conversion from integer to ascii.
+               card[13] = dev_id + 48;
+       }
 
        fprintf(stderr, "using card '%s'\n", card);
 
        /* open the DRM device */
-       ret = modeset_open(&fd, card);
+       ret = modeset_open(&drm->fd, card);
        if (ret)
-               goto out_return;
+               goto error;
 
        /* prepare all connectors and CRTCs */
-       ret = modeset_prepare(fd);
+       ret = modeset_prepare(drm->fd);
        if (ret)
-               goto out_close;
+               goto error;
 
        /* perform actual modesetting on each found connector+CRTC */
        for (iter = modeset_list; iter; iter = iter->next) {
-               iter->saved_crtc = drmModeGetCrtc(fd, iter->crtc);
-               ret = drmModeSetCrtc(fd, iter->crtc, iter->fb, 0, 0,
+               iter->saved_crtc = drmModeGetCrtc(drm->fd, iter->crtc);
+               ret = drmModeSetCrtc(drm->fd, iter->crtc, iter->fb, 0, 0,
                                     &iter->conn, 1, &iter->mode);
                if (ret)
                        fprintf(stderr, "cannot set CRTC for connector %u (%d): 
%m\n",
                                iter->conn, errno);
        }
 
-       /* draw some colors for 5seconds */
-       modeset_draw();
-
-       /* cleanup everything */
-       modeset_cleanup(fd);
-
-       ret = 0;
-
-out_close:
-       close(fd);
-out_return:
-       if (ret) {
-               errno = -ret;
-               fprintf(stderr, "modeset failed with error %d: %m\n", errno);
-       } else {
-               fprintf(stderr, "exiting\n");
-       }
-       return ret;
+       drm->canvas.data = modeset_list->map;
+       drm->canvas.width = modeset_list->width;
+       drm->canvas.height = modeset_list->height;
+       drm->canvas.bpp = 32;
+       drm->canvas.stride = modeset_list->stride;
+       drm->canvas.angle = angle;
+       drm->canvas.rgbmode = RGB888;
+
+       return drm;
+error:
+       psplash_drm_destroy(drm);
+       return NULL;
 }
 
 /*
- * A short helper function to compute a changing color value. No need to
- * understand it.
- */
-
-static uint8_t next_color(bool *up, uint8_t cur, unsigned int mod)
-{
-       uint8_t next;
-
-       next = cur + (*up ? 1 : -1) * (rand() % mod);
-       if ((*up && next < cur) || (!*up && next > cur)) {
-               *up = !*up;
-               next = cur;
-       }
-
-       return next;
-}
-
-/*
- * modeset_draw(): This draws a solid color into all configured framebuffers.
- * Every 100ms the color changes to a slightly different color so we get some
- * kind of smoothly changing color-gradient.
- *
- * The color calculation can be ignored as it is pretty boring. So the
- * interesting stuff is iterating over "modeset_list" and then through all 
lines
- * and width. We then set each pixel individually to the current color.
- *
- * We do this 50 times as we sleep 100ms after each redraw round. This makes
- * 50*100ms = 5000ms = 5s so it takes about 5seconds to finish this loop.
- *
- * Please note that we draw directly into the framebuffer. This means that you
- * will see flickering as the monitor might refresh while we redraw the screen.
- * To avoid this you would need to use two framebuffers and a call to
- * drmModeSetCrtc() to switch between both buffers.
- * You can also use drmModePageFlip() to do a vsync'ed pageflip. But this is
- * beyond the scope of this document.
- */
-
-static void modeset_draw(void)
-{
-       uint8_t r, g, b;
-       bool r_up, g_up, b_up;
-       unsigned int i, j, k, off;
-       struct modeset_dev *iter;
-
-       srand(time(NULL));
-       r = rand() % 0xff;
-       g = rand() % 0xff;
-       b = rand() % 0xff;
-       r_up = g_up = b_up = true;
-
-       for (i = 0; i < 50; ++i) {
-               r = next_color(&r_up, r, 20);
-               g = next_color(&g_up, g, 10);
-               b = next_color(&b_up, b, 5);
-
-               for (iter = modeset_list; iter; iter = iter->next) {
-                       for (j = 0; j < iter->height; ++j) {
-                               for (k = 0; k < iter->width; ++k) {
-                                       off = iter->stride * j + k * 4;
-                                       *(uint32_t*)&iter->map[off] =
-                                                    (r << 16) | (g << 8) | b;
-                               }
-                       }
-               }
-
-               usleep(100000);
-       }
-}
-
-/*
- * modeset_cleanup(fd): This cleans up all the devices we created during
+ * psplash_drm_destroy(drm): This cleans up all the devices we created during
  * modeset_prepare(). It resets the CRTCs to their saved states and deallocates
  * all memory.
  * It should be pretty obvious how all of this works.
  */
 
-static void modeset_cleanup(int fd)
+void psplash_drm_destroy(PSplashDRM *drm)
 {
        struct modeset_dev *iter;
        struct drm_mode_destroy_dumb dreq;
 
+       if (!drm)
+               return;
+
        while (modeset_list) {
                /* remove from global list */
                iter = modeset_list;
                modeset_list = iter->next;
 
                /* restore saved CRTC configuration */
-               drmModeSetCrtc(fd,
+               drmModeSetCrtc(drm->fd,
                               iter->saved_crtc->crtc_id,
                               iter->saved_crtc->buffer_id,
                               iter->saved_crtc->x,
@@ -694,16 +630,19 @@ static void modeset_cleanup(int fd)
                munmap(iter->map, iter->size);
 
                /* delete framebuffer */
-               drmModeRmFB(fd, iter->fb);
+               drmModeRmFB(drm->fd, iter->fb);
 
                /* delete dumb buffer */
                memset(&dreq, 0, sizeof(dreq));
                dreq.handle = iter->handle;
-               drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+               drmIoctl(drm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
 
                /* free allocated memory */
                free(iter);
        }
+
+       close(drm->fd);
+       free(drm);
 }
 
 /*
diff --git a/psplash-drm.h b/psplash-drm.h
new file mode 100644
index 0000000..e987fd6
--- /dev/null
+++ b/psplash-drm.h
@@ -0,0 +1,17 @@
+#ifndef _HAVE_PSPLASH_DRM_H
+#define _HAVE_PSPLASH_DRM_H
+
+#include "psplash-draw.h"
+
+typedef struct PSplashDRM
+{
+  PSplashCanvas canvas;
+  int fd;
+}
+PSplashDRM;
+
+void psplash_drm_destroy(PSplashDRM *drm);
+
+PSplashDRM* psplash_drm_new(int angle, int dev_id);
+
+#endif
diff --git a/psplash.c b/psplash.c
index 036dfb1..ebf8d7a 100644
--- a/psplash.c
+++ b/psplash.c
@@ -12,6 +12,9 @@
 
 #include "psplash.h"
 #include "psplash-fb.h"
+#ifdef ENABLE_DRM
+#include "psplash-drm.h"
+#endif
 #include "psplash-config.h"
 #include "psplash-colors.h"
 #include "psplash-poky-img.h"
@@ -224,8 +227,11 @@ int
 main (int argc, char** argv)
 {
   char      *rundir;
-  int        pipe_fd, i = 0, angle = 0, fbdev_id = 0, ret = 0;
-  PSplashFB *fb;
+  int        pipe_fd, i = 0, angle = 0, dev_id = 0, use_drm = 0, ret = 0;
+  PSplashFB *fb = NULL;
+#ifdef ENABLE_DRM
+  PSplashDRM *drm = NULL;
+#endif
   PSplashCanvas *canvas;
   bool       disable_console_switch = FALSE;
 
@@ -247,16 +253,24 @@ main (int argc, char** argv)
         continue;
       }
 
-    if (!strcmp(argv[i],"-f") || !strcmp(argv[i],"--fbdev"))
+    if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--fbdev") ||
+        !strcmp(argv[i], "-d") || !strcmp(argv[i], "--dev"))
       {
         if (++i >= argc) goto fail;
-        fbdev_id = atoi(argv[i]);
+        dev_id = atoi(argv[i]);
         continue;
       }
 
+#ifdef ENABLE_DRM
+    if (!strcmp(argv[i], "--drm")) {
+        use_drm = 1;
+        continue;
+    }
+#endif
+
     fail:
       fprintf(stderr,
-              "Usage: %s [-n|--no-console-switch][-a|--angle 
<0|90|180|270>][-f|--fbdev <0..9>]\n",
+              "Usage: %s [-n|--no-console-switch][-a|--angle 
<0|90|180|270>][-f|--fbdev|-d|--dev <0..9>][--drm]\n",
               argv[0]);
       exit(-1);
   }
@@ -291,12 +305,21 @@ main (int argc, char** argv)
   if (!disable_console_switch)
     psplash_console_switch ();
 
-  if ((fb = psplash_fb_new(angle,fbdev_id)) == NULL)
-    {
-         ret = -1;
-         goto fb_fail;
+  if (use_drm) {
+#ifdef ENABLE_DRM
+    if ((drm = psplash_drm_new(angle, dev_id)) == NULL) {
+      ret = -1;
+      goto error;
+    }
+    canvas = &drm->canvas;
+#endif
+  } else {
+    if ((fb = psplash_fb_new(angle, dev_id)) == NULL) {
+      ret = -1;
+      goto error;
     }
-  canvas = &fb->canvas;
+    canvas = &fb->canvas;
+  }
 
 #ifdef HAVE_SYSTEMD
   sd_notify(0, "READY=1");
@@ -349,9 +372,14 @@ main (int argc, char** argv)
 
   psplash_main(canvas, pipe_fd, 0);
 
-  psplash_fb_destroy (fb);
+  if (fb)
+    psplash_fb_destroy(fb);
+#ifdef ENABLE_DRM
+  if (drm)
+    psplash_drm_destroy(drm);
+#endif
 
- fb_fail:
+ error:
   unlink(PSPLASH_FIFO);
 
   if (!disable_console_switch)
-- 
2.30.2

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#56862): https://lists.yoctoproject.org/g/yocto/message/56862
Mute This Topic: https://lists.yoctoproject.org/mt/90680281/21656
Group Owner: yocto+ow...@lists.yoctoproject.org
Unsubscribe: https://lists.yoctoproject.org/g/yocto/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to