From 1a6bb17cb1aa974d25f1094e3e5e9a8e23940e8e Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Sun, 26 Nov 2023 10:33:51 +0100 Subject: [PATCH] drm: make optional Make DRM configurable at build time to avoid increasing the size of pbsplash. DRM support is not yet suitable to be enabled by default, but it's nice to have it merged in so the code doesn't bitrot. Signed-off-by: Caleb Connolly --- include/tfblib.h | 5 ++ include/{framebuffer.h => tfblib_drm.h} | 12 ++- meson.build | 35 +++++++- meson_options.txt | 1 + src/drawing.c | 5 +- src/drm.c | 2 +- src/drm_stub.c | 7 ++ src/fb.c | 11 ++- src/meson.build | 14 ---- src/pbsplash.c | 105 ++++++++++++++---------- 10 files changed, 129 insertions(+), 68 deletions(-) rename include/{framebuffer.h => tfblib_drm.h} (90%) create mode 100644 meson_options.txt create mode 100644 src/drm_stub.c delete mode 100644 src/meson.build diff --git a/include/tfblib.h b/include/tfblib.h index 2f809d8..ae8e105 100644 --- a/include/tfblib.h +++ b/include/tfblib.h @@ -12,6 +12,7 @@ #include #include +#include "config.h" #include "pbsplash.h" /// Convenience macro used to shorten the signatures. Undefined at the end. @@ -85,7 +86,11 @@ */ int tfb_acquire_fb(u32 flags, const char *fb_device, const char *tty_device); +#ifdef CONFIG_DRM_SUPPORT int tfb_acquire_drm(uint32_t flags, const char *device); +#else +#define tfb_acquire_drm(f, d) ({ -1; }) +#endif /** * Release the framebuffer device diff --git a/include/framebuffer.h b/include/tfblib_drm.h similarity index 90% rename from include/framebuffer.h rename to include/tfblib_drm.h index e6b7da2..da33865 100644 --- a/include/framebuffer.h +++ b/include/tfblib_drm.h @@ -1,13 +1,17 @@ -#ifndef _FRAMEBUFFER_H -#define _FRAMEBUFFER_H +#pragma once #include +#include "config.h" + +#ifdef CONFIG_DRM_SUPPORT + #include #include #include #include + struct modeset_buf { uint32_t width; uint32_t height; @@ -32,6 +36,8 @@ struct drm_framebuffer { extern struct drm_framebuffer *drm; +#endif + int drm_framebuffer_init(int *handle, const char *card); void drm_framebuffer_close(int handle); -#endif + diff --git a/meson.build b/meson.build index ca2fbad..e0560bb 100644 --- a/meson.build +++ b/meson.build @@ -3,12 +3,39 @@ cc = meson.get_compiler('c') deps = [ cc.find_library('m', required : false), - dependency('libdrm'), dependency('libudev'), ] -inc = [ - include_directories('include'), +conf_data = configuration_data() +use_drm = get_option('drm') + +src = [ + 'src/animate.c', + 'src/nanosvg.c', + 'src/timespec.c', + 'src/pbsplash.c', + 'src/fb.c', + 'src/drawing.c', ] -subdir('src') +if use_drm.enabled() + deps += dependency('libdrm') + src += 'src/drm.c' + conf_data.set('CONFIG_DRM_SUPPORT', true) +else + src += 'src/drm_stub.c' + conf_data.set('CONFIG_DRM_SUPPORT', false) +endif + +configure_file(output : 'config.h', + configuration : conf_data) + +inc = [ + include_directories('include'), + include_directories('.') +] + +executable('pbsplash', src, + include_directories: inc, + dependencies: deps, + install: true) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..aa355b5 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('drm', type : 'feature', value : 'disabled') diff --git a/src/drawing.c b/src/drawing.c index c00a9e6..a25c48f 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -8,9 +8,10 @@ #include #include "pbsplash.h" -#include "framebuffer.h" #include "tfblib.h" +#include "tfblib_drm.h" + #define DEBUGRENDER 0 extern inline uint32_t tfb_make_color(uint8_t red, uint8_t green, uint8_t blue); @@ -145,8 +146,10 @@ void tfb_fill_rect(int x, int y, int w, int h, uint32_t color) dest = __fb_buffer + y * __fb_pitch + (x * 4); /* drm alignment weirdness */ +#ifdef CONFIG_DRM_SUPPORT if (drm) w *= 4; +#endif for (uint32_t cy = y; cy < yend; cy++, dest += __fb_pitch) memset(dest, color, w); diff --git a/src/drm.c b/src/drm.c index abdcd32..36e2caa 100644 --- a/src/drm.c +++ b/src/drm.c @@ -40,7 +40,7 @@ #include #include -#include "framebuffer.h" +#include "tfblib_drm.h" struct modeset_buf; struct drm_framebuffer; diff --git a/src/drm_stub.c b/src/drm_stub.c new file mode 100644 index 0000000..a69ce30 --- /dev/null +++ b/src/drm_stub.c @@ -0,0 +1,7 @@ + +int drm_framebuffer_init(int *handle, const char *card) { + return -1; +} + +void drm_framebuffer_close(int handle) { +} diff --git a/src/fb.c b/src/fb.c index f115481..193e2b9 100644 --- a/src/fb.c +++ b/src/fb.c @@ -15,10 +15,11 @@ #include #include -#include "framebuffer.h" #include "pbsplash.h" #include "tfblib.h" +#include "tfblib_drm.h" + #define DEFAULT_FB_DEVICE "/dev/fb0" #define DEFAULT_TTY_DEVICE "/dev/tty" @@ -51,6 +52,7 @@ static int tfb_set_window(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32 return 0; } +#ifdef CONFIG_DRM_SUPPORT int tfb_acquire_drm(uint32_t flags, const char *device) { int ret; @@ -86,6 +88,7 @@ int tfb_acquire_drm(uint32_t flags, const char *device) return 0; } +#endif int tfb_acquire_fb(uint32_t flags, const char *fb_device, const char *tty_device) { @@ -259,6 +262,7 @@ void tfb_flush_window(void) int tfb_flush_fb(void) { +#ifdef CONFIG_DRM_SUPPORT int ret; struct modeset_buf *buf; if (drmfd >= 0) { @@ -276,6 +280,7 @@ int tfb_flush_fb(void) __fb_buffer = buf->map; //drm->bufs[drm->front_buf ^ 1].map; return 0; } +#endif __fbi.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &__fbi) < 0) { perror("Couldn't flush framebuffer"); @@ -287,15 +292,19 @@ int tfb_flush_fb(void) uint32_t tfb_screen_width_mm(void) { +#ifdef CONFIG_DRM_SUPPORT if (drmfd >= 0) return drm->mm_width; +#endif return __fbi.width; } uint32_t tfb_screen_height_mm(void) { +#ifdef CONFIG_DRM_SUPPORT if (drmfd >= 0) return drm->mm_height; +#endif return __fbi.height; } diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index 89879e9..0000000 --- a/src/meson.build +++ /dev/null @@ -1,14 +0,0 @@ -src = [ - 'animate.c', - 'nanosvg.c', - 'timespec.c', - 'pbsplash.c', - 'fb.c', - 'drm.c', - 'drawing.c', -] - -executable('pbsplash', src, - include_directories: inc, - dependencies: deps, - install: true) diff --git a/src/pbsplash.c b/src/pbsplash.c index 2f39fe1..fa5cb01 100644 --- a/src/pbsplash.c +++ b/src/pbsplash.c @@ -9,12 +9,13 @@ #include #include -#include -#include +#include "config.h" #include "nanosvg.h" #include "pbsplash.h" #include "tfblib.h" #include "timespec.h" +#include +#include #define MSG_MAX_LEN 4096 #define DEFAULT_FONT_PATH "/usr/share/pbsplash/OpenSans-Regular.svg" @@ -48,17 +49,20 @@ static int usage() fprintf(stderr, "pbsplash [-v] [-h] [-f font] [-s splash image] [-m message]\n"); fprintf(stderr, " [-b message bottom] [-o font size bottom]\n"); fprintf(stderr, " [-p font size] [-q max logo size] [-d] [-e]\n\n"); - fprintf(stderr, " -v enable verbose logging\n"); - fprintf(stderr, " -h show this help\n"); - fprintf(stderr, " -f path to SVG font file (default: %s)\n", DEFAULT_FONT_PATH); - fprintf(stderr, " -s path to splash image to display\n"); - fprintf(stderr, " -m message to show under the splash image\n"); fprintf(stderr, " -b message to show at the bottom\n"); + fprintf(stderr, " -d custom DPI (for testing)\n"); + fprintf(stderr, " -e error (no loading animation)\n"); + fprintf(stderr, " -f path to SVG font file (default: %s)\n", DEFAULT_FONT_PATH); + fprintf(stderr, " -h show this help\n"); + fprintf(stderr, " -m message to show under the splash image\n"); fprintf(stderr, " -o font size bottom in pt (default: %d)\n", FONT_SIZE_B_PT); fprintf(stderr, " -p font size in pt (default: %d)\n", FONT_SIZE_PT); fprintf(stderr, " -q max logo size in mm (default: %d)\n", LOGO_SIZE_MAX_MM); - fprintf(stderr, " -d custom DPI (for testing)\n"); - fprintf(stderr, " -e error (no loading animation)\n"); +#ifdef CONFIG_DRM_SUPPORT + fprintf(stderr, " -r use DRM for rendering instead of framebuffer"); +#endif + fprintf(stderr, " -s path to splash image to display\n"); + fprintf(stderr, " -v enable verbose logging\n"); // clang-format on return 1; @@ -108,7 +112,7 @@ static inline float getShapeWidth(const NSVGimage *font, const NSVGshape *shape) if (shape) { return shape->horizAdvX; } else { - //printf("WARNING: Shape for '%s' is NULL!\n", shape->unicode ?: ""); + // printf("WARNING: Shape for '%s' is NULL!\n", shape->unicode ?: ""); return font->defaultHorizAdv; } } @@ -400,6 +404,7 @@ int main(int argc, char **argv) }; int optflag; bool animation = true; + bool use_drm = false; memset(active_tty, '\0', TTY_PATH_LEN); strcat(active_tty, "/dev/"); @@ -409,7 +414,7 @@ int main(int argc, char **argv) sigaction(SIGTERM, &action, NULL); sigaction(SIGINT, &action, NULL); - while ((optflag = getopt(argc, argv, "hvf:s:m:b:o:p:q:d:e")) != -1) { + while ((optflag = getopt(argc, argv, "hvf:s:m:b:o:p:q:d:er")) != -1) { char *end = NULL; switch (optflag) { case 'h': @@ -452,6 +457,13 @@ int main(int argc, char **argv) return usage(); } break; + case 'r': +#ifndef CONFIG_DRM_SUPPORT + fprintf(stderr, "DRM support not compiled in\n"); + return usage(); +#endif + use_drm = true; + break; case 'd': dpi_info.dpi = strtol(optarg, &end, 10); if (end == optarg || dpi_info.dpi < 0) { @@ -467,27 +479,25 @@ int main(int argc, char **argv) } } - // { - // FILE *fp = fopen("/sys/devices/virtual/tty/tty0/active", "r"); - // int len = strlen(active_tty); - // char *ptr = active_tty + len; - // if (fp != NULL) { - // fgets(ptr, TTY_PATH_LEN - len, fp); - // *(ptr + strlen(ptr) - 1) = '\0'; - // fclose(fp); - // } - // } + /* Framebuffer */ + if (!use_drm) { + FILE *fp = fopen("/sys/devices/virtual/tty/tty0/active", "r"); + int len = strlen(active_tty); + char *ptr = active_tty + len; + if (fp != NULL) { + fgets(ptr, TTY_PATH_LEN - len, fp); + *(ptr + strlen(ptr) - 1) = '\0'; + fclose(fp); + } - // LOG("active tty: '%s'\n", active_tty); + LOG("active tty: '%s'\n", active_tty); - // if ((rc = tfb_acquire_fb(/*TFB_FL_NO_TTY_KD_GRAPHICS */ 0, "/dev/fb0", active_tty)) != - // TFB_SUCCESS) { - // fprintf(stderr, "tfb_acquire_fb() failed with error code: %d\n", rc); - // rc = 1; - // return rc; - // } - - if ((rc = tfb_acquire_drm(0, "/dev/dri/card0")) != 0) { + if ((rc = tfb_acquire_fb(0, "/dev/fb0", active_tty)) != 0) { + fprintf(stderr, "tfb_acquire_fb() failed with error code: %d\n", rc); + rc = 1; + return rc; + } + } else if ((rc = tfb_acquire_drm(0, "/dev/dri/card0")) != 0) { fprintf(stderr, "tfb_acquire_drm() failed with error code: %d\n", rc); rc = 1; return rc; @@ -532,11 +542,15 @@ no_messages: tfb_flush_fb(); int tick = 0; - // int tty = open(active_tty, O_RDWR); - // if (!tty) { - // fprintf(stderr, "Failed to open tty %s (%d)\n", active_tty, errno); - // goto out; - // } + int tty = 0; + + if (!use_drm) { + open(active_tty, O_RDWR); + if (!tty) { + fprintf(stderr, "Failed to open tty %s (%d)\n", active_tty, errno); + goto out; + } + } struct timespec epoch, start, end, diff; int target_fps = 60; @@ -553,7 +567,7 @@ no_messages: tfb_flush_fb(); clock_gettime(CLOCK_REALTIME, &end); diff = timespec_sub(end, start); - //printf("%05d: %09ld\n", tick, diff.tv_nsec); + // printf("%05d: %09ld\n", tick, diff.tv_nsec); if (diff.tv_nsec < 1000000000 / target_fps) { struct timespec sleep_time = { .tv_sec = 0, @@ -564,15 +578,18 @@ no_messages: } out: - // Before we exit print the logo so it will persist - if (image_info.image) { - //ioctl(tty, KDSETMODE, KD_TEXT); - draw_svg(image_info.image, image_info.x, image_info.y, image_info.width, - image_info.height); - } + /* Currently DRM doesn't persist the framebuffer after exiting */ + if (!use_drm) { + // Before we exit print the logo so it will persist + if (image_info.image) { + ioctl(tty, KDSETMODE, KD_TEXT); + draw_svg(image_info.image, image_info.x, image_info.y, image_info.width, + image_info.height); + } - // Draw the messages again so they will persist - show_messages(&msgs, &dpi_info); + // Draw the messages again so they will persist + show_messages(&msgs, &dpi_info); + } nsvgDelete(image_info.image); nsvgDelete(msgs.font);