mirror of
https://git.sr.ht/~calebccff/pbsplash
synced 2026-01-12 20:48:40 -09:00
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:
parent
96d181885e
commit
1a6bb17cb1
10 changed files with 129 additions and 68 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
35
meson.build
35
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)
|
||||
|
|
|
|||
1
meson_options.txt
Normal file
1
meson_options.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
option('drm', type : 'feature', value : 'disabled')
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
7
src/drm_stub.c
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
int drm_framebuffer_init(int *handle, const char *card) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void drm_framebuffer_close(int handle) {
|
||||
}
|
||||
11
src/fb.c
11
src/fb.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
105
src/pbsplash.c
105
src/pbsplash.c
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue