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 <string.h>
#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

View file

@ -1,13 +1,17 @@
#ifndef _FRAMEBUFFER_H
#define _FRAMEBUFFER_H
#pragma once
#include <stdint.h>
#include "config.h"
#ifdef CONFIG_DRM_SUPPORT
#include <libdrm/drm.h>
#include <libdrm/drm_mode.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
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

View file

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

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 "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);

View file

@ -40,7 +40,7 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "framebuffer.h"
#include "tfblib_drm.h"
struct modeset_buf;
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 <unistd.h>
#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;
}

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 <unistd.h>
#include <math.h>
#include <string.h>
#include "config.h"
#include "nanosvg.h"
#include "pbsplash.h"
#include "tfblib.h"
#include "timespec.h"
#include <math.h>
#include <string.h>
#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;
@ -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;
@ -564,15 +578,18 @@ no_messages:
}
out:
/* 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);
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);
}
nsvgDelete(image_info.image);
nsvgDelete(msgs.font);