summaryrefslogtreecommitdiffstats
path: root/meta-agl-drm-lease/recipes-core/psplash/files/0012-Implement-drm-backend.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-agl-drm-lease/recipes-core/psplash/files/0012-Implement-drm-backend.patch')
-rw-r--r--meta-agl-drm-lease/recipes-core/psplash/files/0012-Implement-drm-backend.patch507
1 files changed, 507 insertions, 0 deletions
diff --git a/meta-agl-drm-lease/recipes-core/psplash/files/0012-Implement-drm-backend.patch b/meta-agl-drm-lease/recipes-core/psplash/files/0012-Implement-drm-backend.patch
new file mode 100644
index 00000000..1d1e281d
--- /dev/null
+++ b/meta-agl-drm-lease/recipes-core/psplash/files/0012-Implement-drm-backend.patch
@@ -0,0 +1,507 @@
+From edc84300b5e5d8b15a87fbb4aee0c83e1a80e9e6 Mon Sep 17 00:00:00 2001
+From: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
+Date: Mon, 25 Apr 2022 10:59:51 +0300
+Subject: [PATCH 12/17] Implement drm backend
+
+Limitation is that splash screen is drawn only on the first connector.
+
+drm-backend backport from:
+https://patchwork.yoctoproject.org/project/yocto/cover/20220425075954.10427-1-vasyl.vavrychuk@opensynergy.com/
+
+Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@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.25.1
+