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 <caleb.connolly@linaro.org>
This commit is contained in:
Caleb Connolly 2023-11-26 10:33:51 +01:00
parent 96d181885e
commit 1a6bb17cb1
No known key found for this signature in database
GPG key ID: 0583312B195F64B6
10 changed files with 129 additions and 68 deletions

View file

@ -12,6 +12,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "config.h"
#include "pbsplash.h" #include "pbsplash.h"
/// Convenience macro used to shorten the signatures. Undefined at the end. /// 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); 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); int tfb_acquire_drm(uint32_t flags, const char *device);
#else
#define tfb_acquire_drm(f, d) ({ -1; })
#endif
/** /**
* Release the framebuffer device * Release the framebuffer device

View file

@ -1,13 +1,17 @@
#ifndef _FRAMEBUFFER_H #pragma once
#define _FRAMEBUFFER_H
#include <stdint.h> #include <stdint.h>
#include "config.h"
#ifdef CONFIG_DRM_SUPPORT
#include <libdrm/drm.h> #include <libdrm/drm.h>
#include <libdrm/drm_mode.h> #include <libdrm/drm_mode.h>
#include <xf86drm.h> #include <xf86drm.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
struct modeset_buf { struct modeset_buf {
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
@ -32,6 +36,8 @@ struct drm_framebuffer {
extern struct drm_framebuffer *drm; extern struct drm_framebuffer *drm;
#endif
int drm_framebuffer_init(int *handle, const char *card); int drm_framebuffer_init(int *handle, const char *card);
void drm_framebuffer_close(int handle); void drm_framebuffer_close(int handle);
#endif

View file

@ -3,12 +3,39 @@ cc = meson.get_compiler('c')
deps = [ deps = [
cc.find_library('m', required : false), cc.find_library('m', required : false),
dependency('libdrm'),
dependency('libudev'), dependency('libudev'),
] ]
inc = [ conf_data = configuration_data()
include_directories('include'), 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)

1
meson_options.txt Normal file
View file

@ -0,0 +1 @@
option('drm', type : 'feature', value : 'disabled')

View file

@ -8,9 +8,10 @@
#include <string.h> #include <string.h>
#include "pbsplash.h" #include "pbsplash.h"
#include "framebuffer.h"
#include "tfblib.h" #include "tfblib.h"
#include "tfblib_drm.h"
#define DEBUGRENDER 0 #define DEBUGRENDER 0
extern inline uint32_t tfb_make_color(uint8_t red, uint8_t green, uint8_t blue); 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); dest = __fb_buffer + y * __fb_pitch + (x * 4);
/* drm alignment weirdness */ /* drm alignment weirdness */
#ifdef CONFIG_DRM_SUPPORT
if (drm) if (drm)
w *= 4; w *= 4;
#endif
for (uint32_t cy = y; cy < yend; cy++, dest += __fb_pitch) for (uint32_t cy = y; cy < yend; cy++, dest += __fb_pitch)
memset(dest, color, w); memset(dest, color, w);

View file

@ -40,7 +40,7 @@
#include <xf86drm.h> #include <xf86drm.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include "framebuffer.h" #include "tfblib_drm.h"
struct modeset_buf; struct modeset_buf;
struct drm_framebuffer; struct drm_framebuffer;

7
src/drm_stub.c Normal file
View file

@ -0,0 +1,7 @@
int drm_framebuffer_init(int *handle, const char *card) {
return -1;
}
void drm_framebuffer_close(int handle) {
}

View file

@ -15,10 +15,11 @@
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include "framebuffer.h"
#include "pbsplash.h" #include "pbsplash.h"
#include "tfblib.h" #include "tfblib.h"
#include "tfblib_drm.h"
#define DEFAULT_FB_DEVICE "/dev/fb0" #define DEFAULT_FB_DEVICE "/dev/fb0"
#define DEFAULT_TTY_DEVICE "/dev/tty" #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; return 0;
} }
#ifdef CONFIG_DRM_SUPPORT
int tfb_acquire_drm(uint32_t flags, const char *device) int tfb_acquire_drm(uint32_t flags, const char *device)
{ {
int ret; int ret;
@ -86,6 +88,7 @@ int tfb_acquire_drm(uint32_t flags, const char *device)
return 0; return 0;
} }
#endif
int tfb_acquire_fb(uint32_t flags, const char *fb_device, const char *tty_device) 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) int tfb_flush_fb(void)
{ {
#ifdef CONFIG_DRM_SUPPORT
int ret; int ret;
struct modeset_buf *buf; struct modeset_buf *buf;
if (drmfd >= 0) { if (drmfd >= 0) {
@ -276,6 +280,7 @@ int tfb_flush_fb(void)
__fb_buffer = buf->map; //drm->bufs[drm->front_buf ^ 1].map; __fb_buffer = buf->map; //drm->bufs[drm->front_buf ^ 1].map;
return 0; return 0;
} }
#endif
__fbi.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; __fbi.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &__fbi) < 0) { if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &__fbi) < 0) {
perror("Couldn't flush framebuffer"); perror("Couldn't flush framebuffer");
@ -287,15 +292,19 @@ int tfb_flush_fb(void)
uint32_t tfb_screen_width_mm(void) uint32_t tfb_screen_width_mm(void)
{ {
#ifdef CONFIG_DRM_SUPPORT
if (drmfd >= 0) if (drmfd >= 0)
return drm->mm_width; return drm->mm_width;
#endif
return __fbi.width; return __fbi.width;
} }
uint32_t tfb_screen_height_mm(void) uint32_t tfb_screen_height_mm(void)
{ {
#ifdef CONFIG_DRM_SUPPORT
if (drmfd >= 0) if (drmfd >= 0)
return drm->mm_height; return drm->mm_height;
#endif
return __fbi.height; return __fbi.height;
} }

View file

@ -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)

View file

@ -9,12 +9,13 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <math.h> #include "config.h"
#include <string.h>
#include "nanosvg.h" #include "nanosvg.h"
#include "pbsplash.h" #include "pbsplash.h"
#include "tfblib.h" #include "tfblib.h"
#include "timespec.h" #include "timespec.h"
#include <math.h>
#include <string.h>
#define MSG_MAX_LEN 4096 #define MSG_MAX_LEN 4096
#define DEFAULT_FONT_PATH "/usr/share/pbsplash/OpenSans-Regular.svg" #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, "pbsplash [-v] [-h] [-f font] [-s splash image] [-m message]\n");
fprintf(stderr, " [-b message bottom] [-o font size bottom]\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, " [-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, " -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, " -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, " -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, " -q max logo size in mm (default: %d)\n", LOGO_SIZE_MAX_MM);
fprintf(stderr, " -d custom DPI (for testing)\n"); #ifdef CONFIG_DRM_SUPPORT
fprintf(stderr, " -e error (no loading animation)\n"); 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 // clang-format on
return 1; return 1;
@ -108,7 +112,7 @@ static inline float getShapeWidth(const NSVGimage *font, const NSVGshape *shape)
if (shape) { if (shape) {
return shape->horizAdvX; return shape->horizAdvX;
} else { } else {
//printf("WARNING: Shape for '%s' is NULL!\n", shape->unicode ?: ""); // printf("WARNING: Shape for '%s' is NULL!\n", shape->unicode ?: "");
return font->defaultHorizAdv; return font->defaultHorizAdv;
} }
} }
@ -400,6 +404,7 @@ int main(int argc, char **argv)
}; };
int optflag; int optflag;
bool animation = true; bool animation = true;
bool use_drm = false;
memset(active_tty, '\0', TTY_PATH_LEN); memset(active_tty, '\0', TTY_PATH_LEN);
strcat(active_tty, "/dev/"); strcat(active_tty, "/dev/");
@ -409,7 +414,7 @@ int main(int argc, char **argv)
sigaction(SIGTERM, &action, NULL); sigaction(SIGTERM, &action, NULL);
sigaction(SIGINT, &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; char *end = NULL;
switch (optflag) { switch (optflag) {
case 'h': case 'h':
@ -452,6 +457,13 @@ int main(int argc, char **argv)
return usage(); return usage();
} }
break; break;
case 'r':
#ifndef CONFIG_DRM_SUPPORT
fprintf(stderr, "DRM support not compiled in\n");
return usage();
#endif
use_drm = true;
break;
case 'd': case 'd':
dpi_info.dpi = strtol(optarg, &end, 10); dpi_info.dpi = strtol(optarg, &end, 10);
if (end == optarg || dpi_info.dpi < 0) { if (end == optarg || dpi_info.dpi < 0) {
@ -467,27 +479,25 @@ int main(int argc, char **argv)
} }
} }
// { /* Framebuffer */
// FILE *fp = fopen("/sys/devices/virtual/tty/tty0/active", "r"); if (!use_drm) {
// int len = strlen(active_tty); FILE *fp = fopen("/sys/devices/virtual/tty/tty0/active", "r");
// char *ptr = active_tty + len; int len = strlen(active_tty);
// if (fp != NULL) { char *ptr = active_tty + len;
// fgets(ptr, TTY_PATH_LEN - len, fp); if (fp != NULL) {
// *(ptr + strlen(ptr) - 1) = '\0'; fgets(ptr, TTY_PATH_LEN - len, fp);
// fclose(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)) != if ((rc = tfb_acquire_fb(0, "/dev/fb0", active_tty)) != 0) {
// TFB_SUCCESS) { fprintf(stderr, "tfb_acquire_fb() failed with error code: %d\n", rc);
// fprintf(stderr, "tfb_acquire_fb() failed with error code: %d\n", rc); rc = 1;
// rc = 1; return rc;
// return rc; }
// } } else if ((rc = tfb_acquire_drm(0, "/dev/dri/card0")) != 0) {
if ((rc = tfb_acquire_drm(0, "/dev/dri/card0")) != 0) {
fprintf(stderr, "tfb_acquire_drm() failed with error code: %d\n", rc); fprintf(stderr, "tfb_acquire_drm() failed with error code: %d\n", rc);
rc = 1; rc = 1;
return rc; return rc;
@ -532,11 +542,15 @@ no_messages:
tfb_flush_fb(); tfb_flush_fb();
int tick = 0; int tick = 0;
// int tty = open(active_tty, O_RDWR); int tty = 0;
// if (!tty) {
// fprintf(stderr, "Failed to open tty %s (%d)\n", active_tty, errno); if (!use_drm) {
// goto out; 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; struct timespec epoch, start, end, diff;
int target_fps = 60; int target_fps = 60;
@ -553,7 +567,7 @@ no_messages:
tfb_flush_fb(); tfb_flush_fb();
clock_gettime(CLOCK_REALTIME, &end); clock_gettime(CLOCK_REALTIME, &end);
diff = timespec_sub(end, start); 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) { if (diff.tv_nsec < 1000000000 / target_fps) {
struct timespec sleep_time = { struct timespec sleep_time = {
.tv_sec = 0, .tv_sec = 0,
@ -564,15 +578,18 @@ no_messages:
} }
out: out:
// Before we exit print the logo so it will persist /* Currently DRM doesn't persist the framebuffer after exiting */
if (image_info.image) { if (!use_drm) {
//ioctl(tty, KDSETMODE, KD_TEXT); // Before we exit print the logo so it will persist
draw_svg(image_info.image, image_info.x, image_info.y, image_info.width, if (image_info.image) {
image_info.height); 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 // Draw the messages again so they will persist
show_messages(&msgs, &dpi_info); show_messages(&msgs, &dpi_info);
}
nsvgDelete(image_info.image); nsvgDelete(image_info.image);
nsvgDelete(msgs.font); nsvgDelete(msgs.font);