* [psplash][RFC PATCH 00/14] Implement DRM backend
@ 2022-04-25 7:59 Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 01/14] Trim trailing spaces Vasyl Vavrychuk
` (14 more replies)
0 siblings, 15 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
It is needed in case display does not support FB.
The missing part is drawing splash screen over all connected displays. I think
there should be loop somewhere for this, but I am not sure which level is the
best to put it.
https://github.com/r1mikey/psplash-drm/blob/drm/implement-drm/psplash-draw.c has
psplash_draw_initial(_one), psplash_draw_msg(_one) and
psplash_draw_progress(_one) implementing loop over scanouts. I am think about
doing the same.
Vasyl Vavrychuk (14):
Trim trailing spaces
Fix 'unused-result' warnings
Remove unused save_termios
Remove 'psplash-fb.h' from 'psplash.h'
Extract plot pixel from psplash-fb
Extract draw rect/image from psplash-fb
Extract draw font from psplash-fb
psplash.c: Make psplash_draw_{msg,progress} independent of FB
Rework flip as function pointer
Import drm-howto modeset.c as psplash-drm.c
Implement drm backend
Reverse modeset_list
psplash-drm.c: Allocate resources only for the first connector
psplash-drm.c: Implement double buffering
Makefile.am | 15 +-
configure.ac | 9 +
psplash-console.c | 34 +-
psplash-console.h | 8 +-
psplash-draw.c | 295 +++++++++++++++++
psplash-draw.h | 81 +++++
psplash-drm.c | 787 ++++++++++++++++++++++++++++++++++++++++++++++
psplash-drm.h | 17 +
psplash-fb.c | 371 +++-------------------
psplash-fb.h | 74 +----
psplash-systemd.c | 36 ++-
psplash-write.c | 37 ++-
psplash.c | 186 ++++++-----
psplash.h | 7 +-
14 files changed, 1446 insertions(+), 511 deletions(-)
create mode 100644 psplash-draw.c
create mode 100644 psplash-draw.h
create mode 100644 psplash-drm.c
create mode 100644 psplash-drm.h
--
2.30.2
^ permalink raw reply [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 01/14] Trim trailing spaces
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 02/14] Fix 'unused-result' warnings Vasyl Vavrychuk
` (13 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-console.c | 34 +++++++++++-----------
psplash-console.h | 8 ++---
psplash-fb.c | 4 +--
psplash-fb.h | 34 +++++++++++-----------
psplash-write.c | 14 ++++-----
psplash.c | 74 +++++++++++++++++++++++------------------------
psplash.h | 4 +--
7 files changed, 86 insertions(+), 86 deletions(-)
diff --git a/psplash-console.c b/psplash-console.c
index 3a40620..c00c6fe 100644
--- a/psplash-console.c
+++ b/psplash-console.c
@@ -1,5 +1,5 @@
-/*
- * pslash - a lightweight framebuffer splashscreen for embedded devices.
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
*
* Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
*
@@ -27,12 +27,12 @@ vt_request (int UNUSED(sig))
perror("Error cannot switch away from console");
Visible = 0;
- /* FIXME:
- * We likely now want to signal the main loop as to exit
+ /* FIXME:
+ * We likely now want to signal the main loop as to exit
* and we've now likely switched to the X tty. Note, this
* seems to happen anyway atm due to select() call getting
* a signal interuption error - not sure if this is really
- * reliable however.
+ * reliable however.
*/
}
else
@@ -49,7 +49,7 @@ psplash_console_ignore_switches (void)
{
struct sigaction act;
struct vt_mode vt_mode;
-
+
if (ioctl(ConsoleFd, VT_GETMODE, &vt_mode) < 0)
{
perror("Error VT_SETMODE failed");
@@ -60,7 +60,7 @@ psplash_console_ignore_switches (void)
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
sigaction (SIGUSR1, &act, 0);
-
+
vt_mode.mode = VT_AUTO;
vt_mode.relsig = 0;
vt_mode.acqsig = 0;
@@ -74,7 +74,7 @@ psplash_console_handle_switches (void)
{
struct sigaction act;
struct vt_mode vt_mode;
-
+
if (ioctl(ConsoleFd, VT_GETMODE, &vt_mode) < 0)
{
perror("Error VT_SETMODE failed");
@@ -85,7 +85,7 @@ psplash_console_handle_switches (void)
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
sigaction (SIGUSR1, &act, 0);
-
+
vt_mode.mode = VT_PROCESS;
vt_mode.relsig = SIGUSR1;
vt_mode.acqsig = SIGUSR1;
@@ -94,8 +94,8 @@ psplash_console_handle_switches (void)
perror("Error VT_SETMODE failed");
}
-void
-psplash_console_switch (void)
+void
+psplash_console_switch (void)
{
char vtname[10];
int fd;
@@ -114,9 +114,9 @@ psplash_console_switch (void)
close(fd);
return;
}
-
+
close(fd);
-
+
sprintf(vtname,"/dev/tty%d", VTNum);
if ((ConsoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) < 0)
@@ -134,12 +134,12 @@ psplash_console_switch (void)
if (ioctl(ConsoleFd, VT_ACTIVATE, VTNum) != 0)
perror("Error VT_ACTIVATE failed");
-
+
if (ioctl(ConsoleFd, VT_WAITACTIVE, VTNum) != 0)
perror("Error VT_WAITACTIVE failed\n");
psplash_console_handle_switches ();
-
+
if (ioctl(ConsoleFd, KDSETMODE, KD_GRAPHICS) < 0)
perror("Error KDSETMODE KD_GRAPHICS failed\n");
@@ -156,7 +156,7 @@ psplash_console_reset (void)
return;
/* Back to text mode */
- ioctl(ConsoleFd, KDSETMODE, KD_TEXT);
+ ioctl(ConsoleFd, KDSETMODE, KD_TEXT);
psplash_console_ignore_switches ();
@@ -175,7 +175,7 @@ psplash_console_reset (void)
/* Cleanup */
- close(ConsoleFd);
+ close(ConsoleFd);
if ((fd = open ("/dev/tty0", O_RDWR|O_NDELAY, 0)) >= 0)
{
diff --git a/psplash-console.h b/psplash-console.h
index c893bf2..ad51ef2 100644
--- a/psplash-console.h
+++ b/psplash-console.h
@@ -1,5 +1,5 @@
-/*
- * pslash - a lightweight framebuffer splashscreen for embedded devices.
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
*
* Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
*
@@ -10,8 +10,8 @@
#ifndef _HAVE_PSPLASH_CONSOLE_H
#define _HAVE_PSPLASH_CONSOLE_H
-void
-psplash_console_switch (void);
+void
+psplash_console_switch (void);
void
psplash_console_reset (void);
diff --git a/psplash-fb.c b/psplash-fb.c
index 2babb5f..1d2d7db 100644
--- a/psplash-fb.c
+++ b/psplash-fb.c
@@ -429,13 +429,13 @@ psplash_fb_plot_pixel (PSplashFB *fb,
{
case 32:
*(volatile uint32_t *) (fb->bdata + off)
- = ((red >> (8 - fb->red_length)) << fb->red_offset)
+ = ((red >> (8 - fb->red_length)) << fb->red_offset)
| ((green >> (8 - fb->green_length)) << fb->green_offset)
| ((blue >> (8 - fb->blue_length)) << fb->blue_offset);
break;
case 16:
*(volatile uint16_t *) (fb->bdata + off)
- = ((red >> (8 - fb->red_length)) << fb->red_offset)
+ = ((red >> (8 - fb->red_length)) << fb->red_offset)
| ((green >> (8 - fb->green_length)) << fb->green_offset)
| ((blue >> (8 - fb->blue_length)) << fb->blue_offset);
break;
diff --git a/psplash-fb.h b/psplash-fb.h
index 16e2b20..eafa293 100644
--- a/psplash-fb.h
+++ b/psplash-fb.h
@@ -1,5 +1,5 @@
-/*
- * pslash - a lightweight framebuffer splashscreen for embedded devices.
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
*
* Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
*
@@ -20,11 +20,11 @@ enum RGBMode {
typedef struct PSplashFB
{
- int fd;
+ int fd;
struct fb_var_screeninfo fb_var;
- struct termios save_termios;
- int type;
- int visual;
+ struct termios save_termios;
+ int type;
+ int visual;
int width, height;
int bpp;
int stride;
@@ -56,20 +56,20 @@ PSplashFB*
psplash_fb_new (int angle, int fbdev_id);
void
-psplash_fb_draw_rect (PSplashFB *fb,
- int x,
- int y,
- int width,
+psplash_fb_draw_rect (PSplashFB *fb,
+ int x,
+ int y,
+ int width,
int height,
uint8 red,
uint8 green,
uint8 blue);
void
-psplash_fb_draw_image (PSplashFB *fb,
- int x,
- int y,
- int img_width,
+psplash_fb_draw_image (PSplashFB *fb,
+ int x,
+ int y,
+ int img_width,
int img_height,
int img_bytes_pre_pixel,
int img_rowstride,
@@ -82,9 +82,9 @@ psplash_fb_text_size (int *width,
const char *text);
void
-psplash_fb_draw_text (PSplashFB *fb,
- int x,
- int y,
+psplash_fb_draw_text (PSplashFB *fb,
+ int x,
+ int y,
uint8 red,
uint8 green,
uint8 blue,
diff --git a/psplash-write.c b/psplash-write.c
index a12467a..eee0ea3 100644
--- a/psplash-write.c
+++ b/psplash-write.c
@@ -1,5 +1,5 @@
-/*
- * pslash - a lightweight framebuffer splashscreen for embedded devices.
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
*
* Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
*
@@ -19,7 +19,7 @@
#include <errno.h>
#include "psplash.h"
-int main(int argc, char **argv)
+int main(int argc, char **argv)
{
char *rundir;
int pipe_fd;
@@ -29,17 +29,17 @@ int main(int argc, char **argv)
if (!rundir)
rundir = "/run";
- if (argc!=2)
+ if (argc!=2)
{
fprintf(stderr, "Wrong number of arguments\n");
exit(-1);
}
-
+
chdir(rundir);
-
+
if ((pipe_fd = open (PSPLASH_FIFO,O_WRONLY|O_NONBLOCK)) == -1)
{
- /* Silently error out instead of covering the boot process in
+ /* Silently error out instead of covering the boot process in
errors when psplash has exitted due to a VC switch */
/* perror("Error unable to open fifo"); */
exit (-1);
diff --git a/psplash.c b/psplash.c
index ee1af6b..838ac13 100644
--- a/psplash.c
+++ b/psplash.c
@@ -1,9 +1,9 @@
-/*
- * pslash - a lightweight framebuffer splashscreen for embedded devices.
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
*
* Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
*
- * Parts of this file ( fifo handling ) based on 'usplash' copyright
+ * Parts of this file ( fifo handling ) based on 'usplash' copyright
* Matthew Garret.
*
* SPDX-License-Identifier: GPL-2.0-or-later
@@ -46,15 +46,15 @@ psplash_draw_msg (PSplashFB *fb, const char *msg)
/* Clear */
- psplash_fb_draw_rect (fb,
- 0,
- SPLIT_LINE_POS(fb) - h,
+ psplash_fb_draw_rect (fb,
+ 0,
+ SPLIT_LINE_POS(fb) - h,
fb->width,
h,
PSPLASH_BACKGROUND_COLOR);
psplash_fb_draw_text (fb,
- (fb->width-w)/2,
+ (fb->width-w)/2,
SPLIT_LINE_POS(fb) - h,
PSPLASH_TEXT_COLOR,
&FONT_DEF,
@@ -70,13 +70,13 @@ psplash_draw_progress (PSplashFB *fb, int value)
/* 4 pix border */
x = ((fb->width - BAR_IMG_WIDTH)/2) + 4 ;
y = SPLIT_LINE_POS(fb) + 4;
- width = BAR_IMG_WIDTH - 8;
+ width = BAR_IMG_WIDTH - 8;
height = BAR_IMG_HEIGHT - 8;
if (value > 0)
{
barwidth = (CLAMP(value,0,100) * width) / 100;
- psplash_fb_draw_rect (fb, x + barwidth, y,
+ psplash_fb_draw_rect (fb, x + barwidth, y,
width - barwidth, height,
PSPLASH_BAR_BACKGROUND_COLOR);
psplash_fb_draw_rect (fb, x, y, barwidth,
@@ -85,7 +85,7 @@ psplash_draw_progress (PSplashFB *fb, int value)
else
{
barwidth = (CLAMP(-value,0,100) * width) / 100;
- psplash_fb_draw_rect (fb, x, y,
+ psplash_fb_draw_rect (fb, x, y,
width - barwidth, height,
PSPLASH_BAR_BACKGROUND_COLOR);
psplash_fb_draw_rect (fb, x + width - barwidth,
@@ -93,18 +93,18 @@ psplash_draw_progress (PSplashFB *fb, int value)
PSPLASH_BAR_COLOR);
}
- DBG("value: %i, width: %i, barwidth :%i\n", value,
+ DBG("value: %i, width: %i, barwidth :%i\n", value,
width, barwidth);
}
#endif /* PSPLASH_SHOW_PROGRESS_BAR */
-static int
+static int
parse_command (PSplashFB *fb, char *string)
{
char *command;
DBG("got cmd %s", string);
-
+
if (strcmp(string,"QUIT") == 0)
return 1;
@@ -116,7 +116,7 @@ parse_command (PSplashFB *fb, char *string)
if (arg)
psplash_draw_msg (fb, arg);
- }
+ }
#ifdef PSPLASH_SHOW_PROGRESS_BAR
else if (!strcmp(command,"PROGRESS"))
{
@@ -124,9 +124,9 @@ parse_command (PSplashFB *fb, char *string)
if (arg)
psplash_draw_progress (fb, atoi(arg));
- }
+ }
#endif
- else if (!strcmp(command,"QUIT"))
+ else if (!strcmp(command,"QUIT"))
{
return 1;
}
@@ -135,8 +135,8 @@ parse_command (PSplashFB *fb, char *string)
return 0;
}
-void
-psplash_main (PSplashFB *fb, int pipe_fd, int timeout)
+void
+psplash_main (PSplashFB *fb, int pipe_fd, int timeout)
{
int err;
ssize_t length = 0;
@@ -154,14 +154,14 @@ psplash_main (PSplashFB *fb, int pipe_fd, int timeout)
end = command;
- while (1)
+ while (1)
{
- if (timeout != 0)
+ if (timeout != 0)
err = select(pipe_fd+1, &descriptors, NULL, NULL, &tv);
else
err = select(pipe_fd+1, &descriptors, NULL, NULL, NULL);
-
- if (err <= 0)
+
+ if (err <= 0)
{
/*
if (errno == EINTR)
@@ -169,10 +169,10 @@ psplash_main (PSplashFB *fb, int pipe_fd, int timeout)
*/
return;
}
-
+
length += read (pipe_fd, end, sizeof(command) - (end - command));
- if (length == 0)
+ if (length == 0)
{
/* Reopen to see if there's anything more for us */
close(pipe_fd);
@@ -208,10 +208,10 @@ psplash_main (PSplashFB *fb, int pipe_fd, int timeout)
out:
end = &command[length];
-
+
tv.tv_sec = timeout;
tv.tv_usec = 0;
-
+
FD_ZERO(&descriptors);
FD_SET(pipe_fd,&descriptors);
}
@@ -219,8 +219,8 @@ psplash_main (PSplashFB *fb, int pipe_fd, int timeout)
return;
}
-int
-main (int argc, char** argv)
+int
+main (int argc, char** argv)
{
char *rundir;
int pipe_fd, i = 0, angle = 0, fbdev_id = 0, ret = 0;
@@ -253,8 +253,8 @@ main (int argc, char** argv)
}
fail:
- fprintf(stderr,
- "Usage: %s [-n|--no-console-switch][-a|--angle <0|90|180|270>][-f|--fbdev <0..9>]\n",
+ fprintf(stderr,
+ "Usage: %s [-n|--no-console-switch][-a|--angle <0|90|180|270>][-f|--fbdev <0..9>]\n",
argv[0]);
exit(-1);
}
@@ -268,7 +268,7 @@ main (int argc, char** argv)
if (mkfifo(PSPLASH_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP))
{
- if (errno!=EEXIST)
+ if (errno!=EEXIST)
{
perror("mkfifo");
exit(-1);
@@ -276,8 +276,8 @@ main (int argc, char** argv)
}
pipe_fd = open (PSPLASH_FIFO,O_RDONLY|O_NONBLOCK);
-
- if (pipe_fd==-1)
+
+ if (pipe_fd==-1)
{
perror("pipe open");
exit(-2);
@@ -301,8 +301,8 @@ main (int argc, char** argv)
PSPLASH_BACKGROUND_COLOR);
/* Draw the Poky logo */
- psplash_fb_draw_image (fb,
- (fb->width - POKY_IMG_WIDTH)/2,
+ psplash_fb_draw_image (fb,
+ (fb->width - POKY_IMG_WIDTH)/2,
#if PSPLASH_IMG_FULLSCREEN
(fb->height - POKY_IMG_HEIGHT)/2,
#else
@@ -317,8 +317,8 @@ main (int argc, char** argv)
#ifdef PSPLASH_SHOW_PROGRESS_BAR
/* Draw progress bar border */
- psplash_fb_draw_image (fb,
- (fb->width - BAR_IMG_WIDTH)/2,
+ psplash_fb_draw_image (fb,
+ (fb->width - BAR_IMG_WIDTH)/2,
SPLIT_LINE_POS(fb),
BAR_IMG_WIDTH,
BAR_IMG_HEIGHT,
diff --git a/psplash.h b/psplash.h
index 1c42ec7..3739ca3 100644
--- a/psplash.h
+++ b/psplash.h
@@ -1,5 +1,5 @@
-/*
- * pslash - a lightweight framebuffer splashscreen for embedded devices.
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
*
* Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
*
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 02/14] Fix 'unused-result' warnings
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 01/14] Trim trailing spaces Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 03/14] Remove unused save_termios Vasyl Vavrychuk
` (12 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
This fixes warnings such as:
ignoring return value of 'chdir', declared with attribute warn_unused_result [-Wunused-result]
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-systemd.c | 36 +++++++++++++++++++++++++++++++++---
psplash-write.c | 23 ++++++++++++++++++-----
psplash.c | 5 ++++-
3 files changed, 55 insertions(+), 9 deletions(-)
diff --git a/psplash-systemd.c b/psplash-systemd.c
index 840bd4e..dcf7e61 100644
--- a/psplash-systemd.c
+++ b/psplash-systemd.c
@@ -32,6 +32,7 @@ int get_progress(void)
int r;
char buffer[20];
int len;
+ ssize_t written;
/* Connect to the system bus */
r = sd_bus_new(&bus);
@@ -71,11 +72,36 @@ int get_progress(void)
current_progress = progress;
len = snprintf(buffer, 20, "PROGRESS %d", (int)(current_progress * 100));
- write(pipe_fd, buffer, len + 1);
+ written = write(pipe_fd, buffer, len + 1);
+ if (written == -1) {
+ /* EPIPE could mean that psplash detected boot complete sooner
+ then psplash-systemd and exited */
+ if (errno != EPIPE) {
+ perror("write");
+ r = -1;
+ goto finish;
+ }
+ } else if (written < len + 1) {
+ fprintf(stderr, "Wrote %zd bytes, less then expected %d bytes\n",
+ written, len + 1);
+ r = -1;
+ goto finish;
+ }
if (progress == 1.0) {
printf("Systemd reported progress of 1.0, quit psplash.\n");
- write(pipe_fd, "QUIT", 5);
+ written = write(pipe_fd, "QUIT", 5);
+ if (written == -1) {
+ /* EPIPE could mean that psplash detected boot complete
+ sooner then psplash-systemd and exited */
+ if (errno != EPIPE) {
+ perror("write");
+ r = -1;
+ goto finish;
+ }
+ } else if (written < 5)
+ fprintf(stderr, "Wrote %zd bytes, less then expected 5 bytes\n",
+ written);
r = -1;
}
@@ -123,7 +149,11 @@ int main()
if (!rundir)
rundir = "/run";
- chdir(rundir);
+ r = chdir(rundir);
+ if (r < 0) {
+ perror("chdir");
+ goto finish;
+ }
if ((pipe_fd = open (PSPLASH_FIFO,O_WRONLY|O_NONBLOCK)) == -1) {
fprintf(stderr, "Error unable to open fifo");
diff --git a/psplash-write.c b/psplash-write.c
index eee0ea3..16b87e1 100644
--- a/psplash-write.c
+++ b/psplash-write.c
@@ -21,8 +21,10 @@
int main(int argc, char **argv)
{
- char *rundir;
- int pipe_fd;
+ char *rundir;
+ int pipe_fd;
+ size_t count;
+ ssize_t written;
rundir = getenv("PSPLASH_FIFO_DIR");
@@ -35,7 +37,10 @@ int main(int argc, char **argv)
exit(-1);
}
- chdir(rundir);
+ if (chdir(rundir)) {
+ perror("chdir");
+ exit(-1);
+ }
if ((pipe_fd = open (PSPLASH_FIFO,O_WRONLY|O_NONBLOCK)) == -1)
{
@@ -45,8 +50,16 @@ int main(int argc, char **argv)
exit (-1);
}
- write(pipe_fd, argv[1], strlen(argv[1])+1);
+ count = strlen(argv[1]) + 1;
+ written = write(pipe_fd, argv[1], count);
+ if (written == -1) {
+ perror("write");
+ exit(-1);
+ } else if ((size_t)written < count) {
+ fprintf(stderr, "Wrote %zd bytes, less then expected %zu bytes\n",
+ written, count);
+ exit(-1);
+ }
return 0;
}
-
diff --git a/psplash.c b/psplash.c
index 838ac13..62244ba 100644
--- a/psplash.c
+++ b/psplash.c
@@ -264,7 +264,10 @@ main (int argc, char** argv)
if (!rundir)
rundir = "/run";
- chdir(rundir);
+ if (chdir(rundir)) {
+ perror("chdir");
+ exit(-1);
+ }
if (mkfifo(PSPLASH_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP))
{
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 03/14] Remove unused save_termios
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 01/14] Trim trailing spaces Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 02/14] Fix 'unused-result' warnings Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 04/14] Remove 'psplash-fb.h' from 'psplash.h' Vasyl Vavrychuk
` (11 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-fb.h | 1 -
psplash.h | 1 -
2 files changed, 2 deletions(-)
diff --git a/psplash-fb.h b/psplash-fb.h
index eafa293..6c4599c 100644
--- a/psplash-fb.h
+++ b/psplash-fb.h
@@ -22,7 +22,6 @@ typedef struct PSplashFB
{
int fd;
struct fb_var_screeninfo fb_var;
- struct termios save_termios;
int type;
int visual;
int width, height;
diff --git a/psplash.h b/psplash.h
index 3739ca3..8e68b7b 100644
--- a/psplash.h
+++ b/psplash.h
@@ -32,7 +32,6 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <termios.h>
#include <unistd.h>
typedef uint8_t uint8;
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 04/14] Remove 'psplash-fb.h' from 'psplash.h'
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (2 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 03/14] Remove unused save_termios Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 05/14] Extract plot pixel from psplash-fb Vasyl Vavrychuk
` (10 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
psplash might not be necessary based on framebuffer, it could use DRM
in future too.
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-fb.c | 2 +-
psplash-fb.h | 3 +++
psplash.c | 1 +
psplash.h | 2 --
4 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/psplash-fb.c b/psplash-fb.c
index 1d2d7db..5dea82a 100644
--- a/psplash-fb.c
+++ b/psplash-fb.c
@@ -8,7 +8,7 @@
*/
#include <endian.h>
-#include "psplash.h"
+#include "psplash-fb.h"
static void
psplash_wait_for_vsync(PSplashFB *fb)
diff --git a/psplash-fb.h b/psplash-fb.h
index 6c4599c..4d5c460 100644
--- a/psplash-fb.h
+++ b/psplash-fb.h
@@ -10,6 +10,9 @@
#ifndef _HAVE_PSPLASH_FB_H
#define _HAVE_PSPLASH_FB_H
+#include <linux/fb.h>
+#include "psplash.h"
+
enum RGBMode {
RGB565,
BGR565,
diff --git a/psplash.c b/psplash.c
index 62244ba..18c012b 100644
--- a/psplash.c
+++ b/psplash.c
@@ -11,6 +11,7 @@
*/
#include "psplash.h"
+#include "psplash-fb.h"
#include "psplash-config.h"
#include "psplash-colors.h"
#include "psplash-poky-img.h"
diff --git a/psplash.h b/psplash.h
index 8e68b7b..7489e75 100644
--- a/psplash.h
+++ b/psplash.h
@@ -15,7 +15,6 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <linux/fb.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include <signal.h>
@@ -78,7 +77,6 @@ typedef struct PSplashFont
PSplashFont;
-#include "psplash-fb.h"
#include "psplash-console.h"
#endif
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 05/14] Extract plot pixel from psplash-fb
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (3 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 04/14] Remove 'psplash-fb.h' from 'psplash.h' Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 06/14] Extract draw rect/image " Vasyl Vavrychuk
` (9 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
psplash_fb_plot_pixel is in fact framebuffer independent.
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
Makefile.am | 3 +-
psplash-draw.c | 120 +++++++++++++++++++++++++++++++
psplash-draw.h | 51 +++++++++++++
psplash-fb.c | 191 +++++++++++--------------------------------------
psplash-fb.h | 25 ++-----
psplash.c | 20 +++---
6 files changed, 229 insertions(+), 181 deletions(-)
create mode 100644 psplash-draw.c
create mode 100644 psplash-draw.h
diff --git a/Makefile.am b/Makefile.am
index 310e126..375b926 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,8 @@ AM_CFLAGS = $(GCC_FLAGS) $(EXTRA_GCC_FLAGS) -D_GNU_SOURCE -DFONT_HEADER=\"$(FONT
psplash_SOURCES = psplash.c psplash.h psplash-fb.c psplash-fb.h \
psplash-console.c psplash-console.h \
psplash-colors.h psplash-config.h \
- psplash-poky-img.h psplash-bar-img.h $(FONT_NAME)-font.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_write_SOURCES = psplash-write.c psplash.h
diff --git a/psplash-draw.c b/psplash-draw.c
new file mode 100644
index 0000000..570cfce
--- /dev/null
+++ b/psplash-draw.c
@@ -0,0 +1,120 @@
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
+ *
+ * Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#include "psplash-draw.h"
+
+#define OFFSET(canvas, x, y) (((y) * (canvas)->stride) + ((x) * ((canvas)->bpp >> 3)))
+
+/* TODO: change to 'static inline' as psplash_fb_plot_pixel was before */
+void
+psplash_plot_pixel(PSplashCanvas *canvas,
+ int x,
+ int y,
+ uint8 red,
+ uint8 green,
+ uint8 blue)
+{
+ /* Always write to back data (data) which points to the right data with or
+ * without double buffering support */
+ int off;
+
+ if (x < 0 || x > canvas->width-1 || y < 0 || y > canvas->height-1)
+ return;
+
+ switch (canvas->angle)
+ {
+ case 270:
+ off = OFFSET (canvas, canvas->height - y - 1, x);
+ break;
+ case 180:
+ off = OFFSET (canvas, canvas->width - x - 1, canvas->height - y - 1);
+ break;
+ case 90:
+ off = OFFSET (canvas, y, canvas->width - x - 1);
+ break;
+ case 0:
+ default:
+ off = OFFSET (canvas, x, y);
+ break;
+ }
+
+ if (canvas->rgbmode == RGB565 || canvas->rgbmode == RGB888) {
+ switch (canvas->bpp)
+ {
+ case 24:
+#if __BYTE_ORDER == __BIG_ENDIAN
+ *(canvas->data + off + 0) = red;
+ *(canvas->data + off + 1) = green;
+ *(canvas->data + off + 2) = blue;
+#else
+ *(canvas->data + off + 0) = blue;
+ *(canvas->data + off + 1) = green;
+ *(canvas->data + off + 2) = red;
+#endif
+ break;
+ case 32:
+ *(volatile uint32_t *) (canvas->data + off)
+ = (red << 16) | (green << 8) | (blue);
+ break;
+
+ case 16:
+ *(volatile uint16_t *) (canvas->data + off)
+ = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
+ break;
+ default:
+ /* depth not supported yet */
+ break;
+ }
+ } else if (canvas->rgbmode == BGR565 || canvas->rgbmode == BGR888) {
+ switch (canvas->bpp)
+ {
+ case 24:
+#if __BYTE_ORDER == __BIG_ENDIAN
+ *(canvas->data + off + 0) = blue;
+ *(canvas->data + off + 1) = green;
+ *(canvas->data + off + 2) = red;
+#else
+ *(canvas->data + off + 0) = red;
+ *(canvas->data + off + 1) = green;
+ *(canvas->data + off + 2) = blue;
+#endif
+ break;
+ case 32:
+ *(volatile uint32_t *) (canvas->data + off)
+ = (blue << 16) | (green << 8) | (red);
+ break;
+ case 16:
+ *(volatile uint16_t *) (canvas->data + off)
+ = ((blue >> 3) << 11) | ((green >> 2) << 5) | (red >> 3);
+ break;
+ default:
+ /* depth not supported yet */
+ break;
+ }
+ } else {
+ switch (canvas->bpp)
+ {
+ case 32:
+ *(volatile uint32_t *) (canvas->data + off)
+ = ((red >> (8 - canvas->red_length)) << canvas->red_offset)
+ | ((green >> (8 - canvas->green_length)) << canvas->green_offset)
+ | ((blue >> (8 - canvas->blue_length)) << canvas->blue_offset);
+ break;
+ case 16:
+ *(volatile uint16_t *) (canvas->data + off)
+ = ((red >> (8 - canvas->red_length)) << canvas->red_offset)
+ | ((green >> (8 - canvas->green_length)) << canvas->green_offset)
+ | ((blue >> (8 - canvas->blue_length)) << canvas->blue_offset);
+ break;
+ default:
+ /* depth not supported yet */
+ break;
+ }
+ }
+}
diff --git a/psplash-draw.h b/psplash-draw.h
new file mode 100644
index 0000000..ab2d4d2
--- /dev/null
+++ b/psplash-draw.h
@@ -0,0 +1,51 @@
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
+ *
+ * Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#ifndef _HAVE_PSPLASH_CANVAS_H
+#define _HAVE_PSPLASH_CANVAS_H
+
+#include "psplash.h"
+
+enum RGBMode {
+ RGB565,
+ BGR565,
+ RGB888,
+ BGR888,
+ GENERIC,
+};
+
+typedef struct PSplashCanvas
+{
+ int width, height;
+ int bpp;
+ int stride;
+ char *data;
+
+ int angle;
+
+ enum RGBMode rgbmode;
+ int red_offset;
+ int red_length;
+ int green_offset;
+ int green_length;
+ int blue_offset;
+ int blue_length;
+}
+PSplashCanvas;
+
+/* TODO: Remove after rest of drawing functions migrated to psplash-draw.c */
+void
+psplash_plot_pixel(PSplashCanvas *canvas,
+ int x,
+ int y,
+ uint8 red,
+ uint8 green,
+ uint8 blue);
+
+#endif
diff --git a/psplash-fb.c b/psplash-fb.c
index 5dea82a..a7029c5 100644
--- a/psplash-fb.c
+++ b/psplash-fb.c
@@ -42,10 +42,11 @@ psplash_fb_flip(PSplashFB *fb, int sync)
tmp = fb->fdata;
fb->fdata = fb->bdata;
fb->bdata = tmp;
+ fb->canvas.data = fb->bdata;
/* Sync new front to new back when requested */
if (sync) {
- memcpy(fb->bdata, fb->fdata, fb->stride * fb->real_height);
+ memcpy(fb->bdata, fb->fdata, fb->canvas.stride * fb->real_height);
}
}
}
@@ -220,42 +221,42 @@ psplash_fb_new (int angle, int fbdev_id)
}
}
- fb->real_width = fb->width = fb_var.xres;
- fb->real_height = fb->height = fb_var.yres;
- fb->bpp = fb_var.bits_per_pixel;
- fb->stride = fb_fix.line_length;
+ fb->real_width = fb->canvas.width = fb_var.xres;
+ fb->real_height = fb->canvas.height = fb_var.yres;
+ fb->canvas.bpp = fb_var.bits_per_pixel;
+ fb->canvas.stride = fb_fix.line_length;
fb->type = fb_fix.type;
fb->visual = fb_fix.visual;
- fb->red_offset = fb_var.red.offset;
- fb->red_length = fb_var.red.length;
- fb->green_offset = fb_var.green.offset;
- fb->green_length = fb_var.green.length;
- fb->blue_offset = fb_var.blue.offset;
- fb->blue_length = fb_var.blue.length;
-
- if (fb->red_offset == 11 && fb->red_length == 5 &&
- fb->green_offset == 5 && fb->green_length == 6 &&
- fb->blue_offset == 0 && fb->blue_length == 5) {
- fb->rgbmode = RGB565;
- } else if (fb->red_offset == 0 && fb->red_length == 5 &&
- fb->green_offset == 5 && fb->green_length == 6 &&
- fb->blue_offset == 11 && fb->blue_length == 5) {
- fb->rgbmode = BGR565;
- } else if (fb->red_offset == 16 && fb->red_length == 8 &&
- fb->green_offset == 8 && fb->green_length == 8 &&
- fb->blue_offset == 0 && fb->blue_length == 8) {
- fb->rgbmode = RGB888;
- } else if (fb->red_offset == 0 && fb->red_length == 8 &&
- fb->green_offset == 8 && fb->green_length == 8 &&
- fb->blue_offset == 16 && fb->blue_length == 8) {
- fb->rgbmode = BGR888;
+ fb->canvas.red_offset = fb_var.red.offset;
+ fb->canvas.red_length = fb_var.red.length;
+ fb->canvas.green_offset = fb_var.green.offset;
+ fb->canvas.green_length = fb_var.green.length;
+ fb->canvas.blue_offset = fb_var.blue.offset;
+ fb->canvas.blue_length = fb_var.blue.length;
+
+ if (fb->canvas.red_offset == 11 && fb->canvas.red_length == 5 &&
+ fb->canvas.green_offset == 5 && fb->canvas.green_length == 6 &&
+ fb->canvas.blue_offset == 0 && fb->canvas.blue_length == 5) {
+ fb->canvas.rgbmode = RGB565;
+ } else if (fb->canvas.red_offset == 0 && fb->canvas.red_length == 5 &&
+ fb->canvas.green_offset == 5 && fb->canvas.green_length == 6 &&
+ fb->canvas.blue_offset == 11 && fb->canvas.blue_length == 5) {
+ fb->canvas.rgbmode = BGR565;
+ } else if (fb->canvas.red_offset == 16 && fb->canvas.red_length == 8 &&
+ fb->canvas.green_offset == 8 && fb->canvas.green_length == 8 &&
+ fb->canvas.blue_offset == 0 && fb->canvas.blue_length == 8) {
+ fb->canvas.rgbmode = RGB888;
+ } else if (fb->canvas.red_offset == 0 && fb->canvas.red_length == 8 &&
+ fb->canvas.green_offset == 8 && fb->canvas.green_length == 8 &&
+ fb->canvas.blue_offset == 16 && fb->canvas.blue_length == 8) {
+ fb->canvas.rgbmode = BGR888;
} else {
- fb->rgbmode = GENERIC;
+ fb->canvas.rgbmode = GENERIC;
}
DBG("width: %i, height: %i, bpp: %i, stride: %i",
- fb->width, fb->height, fb->bpp, fb->stride);
+ fb->canvas.width, fb->canvas.height, fb->canvas.bpp, fb->canvas.stride);
fb->base = (char *) mmap ((caddr_t) NULL,
fb_fix.smem_len,
@@ -279,16 +280,17 @@ psplash_fb_new (int angle, int fbdev_id)
if (fb->fb_var.yoffset == 0) {
printf("to back\n");
fb->fdata = fb->data;
- fb->bdata = fb->data + fb->stride * fb->height;
+ fb->bdata = fb->data + fb->canvas.stride * fb->canvas.height;
} else {
printf("to front\n");
- fb->fdata = fb->data + fb->stride * fb->height;
+ fb->fdata = fb->data + fb->canvas.stride * fb->canvas.height;
fb->bdata = fb->data;
}
} else {
fb->fdata = fb->data;
fb->bdata = fb->data;
}
+ fb->canvas.data = fb->bdata;
#if 0
/* FIXME: No support for 8pp as yet */
@@ -312,14 +314,14 @@ psplash_fb_new (int angle, int fbdev_id)
status = 2;
#endif
- fb->angle = angle;
+ fb->canvas.angle = angle;
- switch (fb->angle)
+ switch (angle)
{
case 270:
case 90:
- fb->width = fb->real_height;
- fb->height = fb->real_width;
+ fb->canvas.width = fb->real_height;
+ fb->canvas.height = fb->real_width;
break;
case 180:
case 0:
@@ -337,115 +339,6 @@ psplash_fb_new (int angle, int fbdev_id)
return NULL;
}
-#define OFFSET(fb,x,y) (((y) * (fb)->stride) + ((x) * ((fb)->bpp >> 3)))
-
-static inline void
-psplash_fb_plot_pixel (PSplashFB *fb,
- int x,
- int y,
- uint8 red,
- uint8 green,
- uint8 blue)
-{
- /* Always write to back data (bdata) which points to the right data with or
- * without double buffering support */
- int off;
-
- if (x < 0 || x > fb->width-1 || y < 0 || y > fb->height-1)
- return;
-
- switch (fb->angle)
- {
- case 270:
- off = OFFSET (fb, fb->height - y - 1, x);
- break;
- case 180:
- off = OFFSET (fb, fb->width - x - 1, fb->height - y - 1);
- break;
- case 90:
- off = OFFSET (fb, y, fb->width - x - 1);
- break;
- case 0:
- default:
- off = OFFSET (fb, x, y);
- break;
- }
-
- if (fb->rgbmode == RGB565 || fb->rgbmode == RGB888) {
- switch (fb->bpp)
- {
- case 24:
-#if __BYTE_ORDER == __BIG_ENDIAN
- *(fb->bdata + off + 0) = red;
- *(fb->bdata + off + 1) = green;
- *(fb->bdata + off + 2) = blue;
-#else
- *(fb->bdata + off + 0) = blue;
- *(fb->bdata + off + 1) = green;
- *(fb->bdata + off + 2) = red;
-#endif
- break;
- case 32:
- *(volatile uint32_t *) (fb->bdata + off)
- = (red << 16) | (green << 8) | (blue);
- break;
-
- case 16:
- *(volatile uint16_t *) (fb->bdata + off)
- = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
- break;
- default:
- /* depth not supported yet */
- break;
- }
- } else if (fb->rgbmode == BGR565 || fb->rgbmode == BGR888) {
- switch (fb->bpp)
- {
- case 24:
-#if __BYTE_ORDER == __BIG_ENDIAN
- *(fb->bdata + off + 0) = blue;
- *(fb->bdata + off + 1) = green;
- *(fb->bdata + off + 2) = red;
-#else
- *(fb->bdata + off + 0) = red;
- *(fb->bdata + off + 1) = green;
- *(fb->bdata + off + 2) = blue;
-#endif
- break;
- case 32:
- *(volatile uint32_t *) (fb->bdata + off)
- = (blue << 16) | (green << 8) | (red);
- break;
- case 16:
- *(volatile uint16_t *) (fb->bdata + off)
- = ((blue >> 3) << 11) | ((green >> 2) << 5) | (red >> 3);
- break;
- default:
- /* depth not supported yet */
- break;
- }
- } else {
- switch (fb->bpp)
- {
- case 32:
- *(volatile uint32_t *) (fb->bdata + off)
- = ((red >> (8 - fb->red_length)) << fb->red_offset)
- | ((green >> (8 - fb->green_length)) << fb->green_offset)
- | ((blue >> (8 - fb->blue_length)) << fb->blue_offset);
- break;
- case 16:
- *(volatile uint16_t *) (fb->bdata + off)
- = ((red >> (8 - fb->red_length)) << fb->red_offset)
- | ((green >> (8 - fb->green_length)) << fb->green_offset)
- | ((blue >> (8 - fb->blue_length)) << fb->blue_offset);
- break;
- default:
- /* depth not supported yet */
- break;
- }
- }
-}
-
void
psplash_fb_draw_rect (PSplashFB *fb,
int x,
@@ -460,7 +353,7 @@ psplash_fb_draw_rect (PSplashFB *fb,
for (dy=0; dy < height; dy++)
for (dx=0; dx < width; dx++)
- psplash_fb_plot_pixel (fb, x+dx, y+dy, red, green, blue);
+ psplash_plot_pixel(&fb->canvas, x+dx, y+dy, red, green, blue);
}
void
@@ -493,7 +386,7 @@ psplash_fb_draw_image (PSplashFB *fb,
do
{
if ((img_bytes_per_pixel < 4 || *(p+3)) && dx < img_width)
- psplash_fb_plot_pixel (fb, x+dx, y+dy, *(p), *(p+1), *(p+2));
+ psplash_plot_pixel(&fb->canvas, x+dx, y+dy, *(p), *(p+1), *(p+2));
if (++dx * img_bytes_per_pixel >= img_rowstride) { dx=0; dy++; }
}
while (--len);
@@ -507,7 +400,7 @@ psplash_fb_draw_image (PSplashFB *fb,
do
{
if ((img_bytes_per_pixel < 4 || *(p+3)) && dx < img_width)
- psplash_fb_plot_pixel (fb, x+dx, y+dy, *(p), *(p+1), *(p+2));
+ psplash_plot_pixel(&fb->canvas, x+dx, y+dy, *(p), *(p+1), *(p+2));
if (++dx * img_bytes_per_pixel >= img_rowstride) { dx=0; dy++; }
p += img_bytes_per_pixel;
}
@@ -613,7 +506,7 @@ psplash_fb_draw_text (PSplashFB *fb,
for (cx = 0; cx < w; cx++)
{
if (g & 0x80000000)
- psplash_fb_plot_pixel (fb, x+dx+cx, y+dy+cy,
+ psplash_plot_pixel(&fb->canvas, x+dx+cx, y+dy+cy,
red, green, blue);
g <<= 1;
}
diff --git a/psplash-fb.h b/psplash-fb.h
index 4d5c460..eb02c62 100644
--- a/psplash-fb.h
+++ b/psplash-fb.h
@@ -11,25 +11,16 @@
#define _HAVE_PSPLASH_FB_H
#include <linux/fb.h>
-#include "psplash.h"
-
-enum RGBMode {
- RGB565,
- BGR565,
- RGB888,
- BGR888,
- GENERIC,
-};
+#include "psplash-draw.h"
typedef struct PSplashFB
{
+ PSplashCanvas canvas;
+
int fd;
struct fb_var_screeninfo fb_var;
int type;
int visual;
- int width, height;
- int bpp;
- int stride;
char *data;
char *base;
@@ -38,16 +29,8 @@ typedef struct PSplashFB
char *bdata;
char *fdata;
- int angle, fbdev_id;
+ int fbdev_id;
int real_width, real_height;
-
- enum RGBMode rgbmode;
- int red_offset;
- int red_length;
- int green_offset;
- int green_length;
- int blue_offset;
- int blue_length;
}
PSplashFB;
diff --git a/psplash.c b/psplash.c
index 18c012b..f23f03d 100644
--- a/psplash.c
+++ b/psplash.c
@@ -22,10 +22,10 @@
#include FONT_HEADER
#define SPLIT_LINE_POS(fb) \
- ( (fb)->height \
+ ( (fb)->canvas.height \
- (( PSPLASH_IMG_SPLIT_DENOMINATOR \
- PSPLASH_IMG_SPLIT_NUMERATOR) \
- * (fb)->height / PSPLASH_IMG_SPLIT_DENOMINATOR) \
+ * (fb)->canvas.height / PSPLASH_IMG_SPLIT_DENOMINATOR) \
)
void
@@ -50,12 +50,12 @@ psplash_draw_msg (PSplashFB *fb, const char *msg)
psplash_fb_draw_rect (fb,
0,
SPLIT_LINE_POS(fb) - h,
- fb->width,
+ fb->canvas.width,
h,
PSPLASH_BACKGROUND_COLOR);
psplash_fb_draw_text (fb,
- (fb->width-w)/2,
+ (fb->canvas.width-w)/2,
SPLIT_LINE_POS(fb) - h,
PSPLASH_TEXT_COLOR,
&FONT_DEF,
@@ -69,7 +69,7 @@ psplash_draw_progress (PSplashFB *fb, int value)
int x, y, width, height, barwidth;
/* 4 pix border */
- x = ((fb->width - BAR_IMG_WIDTH)/2) + 4 ;
+ x = ((fb->canvas.width - BAR_IMG_WIDTH)/2) + 4 ;
y = SPLIT_LINE_POS(fb) + 4;
width = BAR_IMG_WIDTH - 8;
height = BAR_IMG_HEIGHT - 8;
@@ -301,16 +301,16 @@ main (int argc, char** argv)
#endif
/* Clear the background with #ecece1 */
- psplash_fb_draw_rect (fb, 0, 0, fb->width, fb->height,
+ psplash_fb_draw_rect (fb, 0, 0, fb->canvas.width, fb->canvas.height,
PSPLASH_BACKGROUND_COLOR);
/* Draw the Poky logo */
psplash_fb_draw_image (fb,
- (fb->width - POKY_IMG_WIDTH)/2,
+ (fb->canvas.width - POKY_IMG_WIDTH)/2,
#if PSPLASH_IMG_FULLSCREEN
- (fb->height - POKY_IMG_HEIGHT)/2,
+ (fb->canvas.height - POKY_IMG_HEIGHT)/2,
#else
- (fb->height * PSPLASH_IMG_SPLIT_NUMERATOR
+ (fb->canvas.height * PSPLASH_IMG_SPLIT_NUMERATOR
/ PSPLASH_IMG_SPLIT_DENOMINATOR - POKY_IMG_HEIGHT)/2,
#endif
POKY_IMG_WIDTH,
@@ -322,7 +322,7 @@ main (int argc, char** argv)
#ifdef PSPLASH_SHOW_PROGRESS_BAR
/* Draw progress bar border */
psplash_fb_draw_image (fb,
- (fb->width - BAR_IMG_WIDTH)/2,
+ (fb->canvas.width - BAR_IMG_WIDTH)/2,
SPLIT_LINE_POS(fb),
BAR_IMG_WIDTH,
BAR_IMG_HEIGHT,
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 06/14] Extract draw rect/image from psplash-fb
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (4 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 05/14] Extract plot pixel from psplash-fb Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 07/14] Extract draw font " Vasyl Vavrychuk
` (8 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-draw.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++
psplash-draw.h | 20 +++++++++++++++
psplash-fb.c | 70 --------------------------------------------------
psplash-fb.h | 20 ---------------
psplash.c | 16 ++++++------
5 files changed, 98 insertions(+), 98 deletions(-)
diff --git a/psplash-draw.c b/psplash-draw.c
index 570cfce..6887e22 100644
--- a/psplash-draw.c
+++ b/psplash-draw.c
@@ -118,3 +118,73 @@ psplash_plot_pixel(PSplashCanvas *canvas,
}
}
}
+
+void
+psplash_draw_rect(PSplashCanvas *canvas,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint8 red,
+ uint8 green,
+ uint8 blue)
+{
+ int dx, dy;
+
+ for (dy=0; dy < height; dy++)
+ for (dx=0; dx < width; dx++)
+ psplash_plot_pixel(canvas, x+dx, y+dy, red, green, blue);
+}
+
+void
+psplash_draw_image(PSplashCanvas *canvas,
+ int x,
+ int y,
+ int img_width,
+ int img_height,
+ int img_bytes_per_pixel,
+ int img_rowstride,
+ uint8 *rle_data)
+{
+ uint8 *p = rle_data;
+ int dx = 0, dy = 0, total_len;
+ unsigned int len;
+
+ total_len = img_rowstride * img_height;
+
+ /* FIXME: Optimise, check for over runs ... */
+ while ((p - rle_data) < total_len)
+ {
+ len = *(p++);
+
+ if (len & 128)
+ {
+ len -= 128;
+
+ if (len == 0) break;
+
+ do
+ {
+ if ((img_bytes_per_pixel < 4 || *(p+3)) && dx < img_width)
+ psplash_plot_pixel(canvas, x+dx, y+dy, *(p), *(p+1), *(p+2));
+ if (++dx * img_bytes_per_pixel >= img_rowstride) { dx=0; dy++; }
+ }
+ while (--len);
+
+ p += img_bytes_per_pixel;
+ }
+ else
+ {
+ if (len == 0) break;
+
+ do
+ {
+ if ((img_bytes_per_pixel < 4 || *(p+3)) && dx < img_width)
+ psplash_plot_pixel(canvas, x+dx, y+dy, *(p), *(p+1), *(p+2));
+ if (++dx * img_bytes_per_pixel >= img_rowstride) { dx=0; dy++; }
+ p += img_bytes_per_pixel;
+ }
+ while (--len && (p - rle_data) < total_len);
+ }
+ }
+}
diff --git a/psplash-draw.h b/psplash-draw.h
index ab2d4d2..f8361da 100644
--- a/psplash-draw.h
+++ b/psplash-draw.h
@@ -48,4 +48,24 @@ psplash_plot_pixel(PSplashCanvas *canvas,
uint8 green,
uint8 blue);
+void
+psplash_draw_rect(PSplashCanvas *canvas,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint8 red,
+ uint8 green,
+ uint8 blue);
+
+void
+psplash_draw_image(PSplashCanvas *canvas,
+ int x,
+ int y,
+ int img_width,
+ int img_height,
+ int img_bytes_per_pixel,
+ int img_rowstride,
+ uint8 *rle_data);
+
#endif
diff --git a/psplash-fb.c b/psplash-fb.c
index a7029c5..07839d5 100644
--- a/psplash-fb.c
+++ b/psplash-fb.c
@@ -339,76 +339,6 @@ psplash_fb_new (int angle, int fbdev_id)
return NULL;
}
-void
-psplash_fb_draw_rect (PSplashFB *fb,
- int x,
- int y,
- int width,
- int height,
- uint8 red,
- uint8 green,
- uint8 blue)
-{
- int dx, dy;
-
- for (dy=0; dy < height; dy++)
- for (dx=0; dx < width; dx++)
- psplash_plot_pixel(&fb->canvas, x+dx, y+dy, red, green, blue);
-}
-
-void
-psplash_fb_draw_image (PSplashFB *fb,
- int x,
- int y,
- int img_width,
- int img_height,
- int img_bytes_per_pixel,
- int img_rowstride,
- uint8 *rle_data)
-{
- uint8 *p = rle_data;
- int dx = 0, dy = 0, total_len;
- unsigned int len;
-
- total_len = img_rowstride * img_height;
-
- /* FIXME: Optimise, check for over runs ... */
- while ((p - rle_data) < total_len)
- {
- len = *(p++);
-
- if (len & 128)
- {
- len -= 128;
-
- if (len == 0) break;
-
- do
- {
- if ((img_bytes_per_pixel < 4 || *(p+3)) && dx < img_width)
- psplash_plot_pixel(&fb->canvas, x+dx, y+dy, *(p), *(p+1), *(p+2));
- if (++dx * img_bytes_per_pixel >= img_rowstride) { dx=0; dy++; }
- }
- while (--len);
-
- p += img_bytes_per_pixel;
- }
- else
- {
- if (len == 0) break;
-
- do
- {
- if ((img_bytes_per_pixel < 4 || *(p+3)) && dx < img_width)
- psplash_plot_pixel(&fb->canvas, x+dx, y+dy, *(p), *(p+1), *(p+2));
- if (++dx * img_bytes_per_pixel >= img_rowstride) { dx=0; dy++; }
- p += img_bytes_per_pixel;
- }
- while (--len && (p - rle_data) < total_len);
- }
- }
-}
-
/* Font rendering code based on BOGL by Ben Pfaff */
static int
diff --git a/psplash-fb.h b/psplash-fb.h
index eb02c62..1eecb47 100644
--- a/psplash-fb.h
+++ b/psplash-fb.h
@@ -40,26 +40,6 @@ psplash_fb_destroy (PSplashFB *fb);
PSplashFB*
psplash_fb_new (int angle, int fbdev_id);
-void
-psplash_fb_draw_rect (PSplashFB *fb,
- int x,
- int y,
- int width,
- int height,
- uint8 red,
- uint8 green,
- uint8 blue);
-
-void
-psplash_fb_draw_image (PSplashFB *fb,
- int x,
- int y,
- int img_width,
- int img_height,
- int img_bytes_pre_pixel,
- int img_rowstride,
- uint8 *rle_data);
-
void
psplash_fb_text_size (int *width,
int *height,
diff --git a/psplash.c b/psplash.c
index f23f03d..2aeb583 100644
--- a/psplash.c
+++ b/psplash.c
@@ -47,7 +47,7 @@ psplash_draw_msg (PSplashFB *fb, const char *msg)
/* Clear */
- psplash_fb_draw_rect (fb,
+ psplash_draw_rect(&fb->canvas,
0,
SPLIT_LINE_POS(fb) - h,
fb->canvas.width,
@@ -77,19 +77,19 @@ psplash_draw_progress (PSplashFB *fb, int value)
if (value > 0)
{
barwidth = (CLAMP(value,0,100) * width) / 100;
- psplash_fb_draw_rect (fb, x + barwidth, y,
+ psplash_draw_rect(&fb->canvas, x + barwidth, y,
width - barwidth, height,
PSPLASH_BAR_BACKGROUND_COLOR);
- psplash_fb_draw_rect (fb, x, y, barwidth,
+ psplash_draw_rect(&fb->canvas, x, y, barwidth,
height, PSPLASH_BAR_COLOR);
}
else
{
barwidth = (CLAMP(-value,0,100) * width) / 100;
- psplash_fb_draw_rect (fb, x, y,
+ psplash_draw_rect(&fb->canvas, x, y,
width - barwidth, height,
PSPLASH_BAR_BACKGROUND_COLOR);
- psplash_fb_draw_rect (fb, x + width - barwidth,
+ psplash_draw_rect(&fb->canvas, x + width - barwidth,
y, barwidth, height,
PSPLASH_BAR_COLOR);
}
@@ -301,11 +301,11 @@ main (int argc, char** argv)
#endif
/* Clear the background with #ecece1 */
- psplash_fb_draw_rect (fb, 0, 0, fb->canvas.width, fb->canvas.height,
+ psplash_draw_rect(&fb->canvas, 0, 0, fb->canvas.width, fb->canvas.height,
PSPLASH_BACKGROUND_COLOR);
/* Draw the Poky logo */
- psplash_fb_draw_image (fb,
+ psplash_draw_image(&fb->canvas,
(fb->canvas.width - POKY_IMG_WIDTH)/2,
#if PSPLASH_IMG_FULLSCREEN
(fb->canvas.height - POKY_IMG_HEIGHT)/2,
@@ -321,7 +321,7 @@ main (int argc, char** argv)
#ifdef PSPLASH_SHOW_PROGRESS_BAR
/* Draw progress bar border */
- psplash_fb_draw_image (fb,
+ psplash_draw_image(&fb->canvas,
(fb->canvas.width - BAR_IMG_WIDTH)/2,
SPLIT_LINE_POS(fb),
BAR_IMG_WIDTH,
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 07/14] Extract draw font from psplash-fb
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (5 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 06/14] Extract draw rect/image " Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 08/14] psplash.c: Make psplash_draw_{msg,progress} independent of FB Vasyl Vavrychuk
` (7 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-draw.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++-
psplash-draw.h | 25 ++++++++----
psplash-fb.c | 108 ------------------------------------------------
psplash-fb.h | 16 --------
psplash.c | 4 +-
5 files changed, 125 insertions(+), 137 deletions(-)
diff --git a/psplash-draw.c b/psplash-draw.c
index 6887e22..aa9887a 100644
--- a/psplash-draw.c
+++ b/psplash-draw.c
@@ -11,8 +11,7 @@
#define OFFSET(canvas, x, y) (((y) * (canvas)->stride) + ((x) * ((canvas)->bpp >> 3)))
-/* TODO: change to 'static inline' as psplash_fb_plot_pixel was before */
-void
+static inline void
psplash_plot_pixel(PSplashCanvas *canvas,
int x,
int y,
@@ -188,3 +187,109 @@ psplash_draw_image(PSplashCanvas *canvas,
}
}
}
+
+/* Font rendering code based on BOGL by Ben Pfaff */
+
+static int
+psplash_font_glyph (const PSplashFont *font, wchar_t wc, u_int32_t **bitmap)
+{
+ int mask = font->index_mask;
+ int i;
+
+ for (;;)
+ {
+ for (i = font->offset[wc & mask]; font->index[i]; i += 2)
+ {
+ if ((wchar_t)(font->index[i] & ~mask) == (wc & ~mask))
+ {
+ if (bitmap != NULL)
+ *bitmap = &font->content[font->index[i+1]];
+ return font->index[i] & mask;
+ }
+ }
+ }
+ return 0;
+}
+
+void
+psplash_text_size(int *width,
+ int *height,
+ const PSplashFont *font,
+ const char *text)
+{
+ char *c = (char*)text;
+ wchar_t wc;
+ int k, n, w, h, mw;
+
+ n = strlen (text);
+ mw = h = w = 0;
+
+ mbtowc (0, 0, 0);
+ for (; (k = mbtowc (&wc, c, n)) > 0; c += k, n -= k)
+ {
+ if (*c == '\n')
+ {
+ if (w > mw)
+ mw = w;
+ w = 0;
+ h += font->height;
+ continue;
+ }
+
+ w += psplash_font_glyph (font, wc, NULL);
+ }
+
+ *width = (w > mw) ? w : mw;
+ *height = (h == 0) ? font->height : h;
+}
+
+void
+psplash_draw_text(PSplashCanvas *canvas,
+ int x,
+ int y,
+ uint8 red,
+ uint8 green,
+ uint8 blue,
+ const PSplashFont *font,
+ const char *text)
+{
+ int h, w, k, n, cx, cy, dx, dy;
+ char *c = (char*)text;
+ wchar_t wc;
+
+ n = strlen (text);
+ h = font->height;
+ dx = dy = 0;
+
+ mbtowc (0, 0, 0);
+ for (; (k = mbtowc (&wc, c, n)) > 0; c += k, n -= k)
+ {
+ u_int32_t *glyph = NULL;
+
+ if (*c == '\n')
+ {
+ dy += h;
+ dx = 0;
+ continue;
+ }
+
+ w = psplash_font_glyph (font, wc, &glyph);
+
+ if (glyph == NULL)
+ continue;
+
+ for (cy = 0; cy < h; cy++)
+ {
+ u_int32_t g = *glyph++;
+
+ for (cx = 0; cx < w; cx++)
+ {
+ if (g & 0x80000000)
+ psplash_plot_pixel(canvas, x+dx+cx, y+dy+cy, red, green, blue);
+ g <<= 1;
+ }
+ }
+
+ dx += w;
+ }
+}
diff --git a/psplash-draw.h b/psplash-draw.h
index f8361da..44546b0 100644
--- a/psplash-draw.h
+++ b/psplash-draw.h
@@ -39,15 +39,6 @@ typedef struct PSplashCanvas
}
PSplashCanvas;
-/* TODO: Remove after rest of drawing functions migrated to psplash-draw.c */
-void
-psplash_plot_pixel(PSplashCanvas *canvas,
- int x,
- int y,
- uint8 red,
- uint8 green,
- uint8 blue);
-
void
psplash_draw_rect(PSplashCanvas *canvas,
int x,
@@ -68,4 +59,20 @@ psplash_draw_image(PSplashCanvas *canvas,
int img_rowstride,
uint8 *rle_data);
+void
+psplash_text_size(int *width,
+ int *height,
+ const PSplashFont *font,
+ const char *text);
+
+void
+psplash_draw_text(PSplashCanvas *canvas,
+ int x,
+ int y,
+ uint8 red,
+ uint8 green,
+ uint8 blue,
+ const PSplashFont *font,
+ const char *text);
+
#endif
diff --git a/psplash-fb.c b/psplash-fb.c
index 07839d5..dd50a5a 100644
--- a/psplash-fb.c
+++ b/psplash-fb.c
@@ -338,111 +338,3 @@ psplash_fb_new (int angle, int fbdev_id)
return NULL;
}
-
-/* Font rendering code based on BOGL by Ben Pfaff */
-
-static int
-psplash_font_glyph (const PSplashFont *font, wchar_t wc, u_int32_t **bitmap)
-{
- int mask = font->index_mask;
- int i;
-
- for (;;)
- {
- for (i = font->offset[wc & mask]; font->index[i]; i += 2)
- {
- if ((wchar_t)(font->index[i] & ~mask) == (wc & ~mask))
- {
- if (bitmap != NULL)
- *bitmap = &font->content[font->index[i+1]];
- return font->index[i] & mask;
- }
- }
- }
- return 0;
-}
-
-void
-psplash_fb_text_size (int *width,
- int *height,
- const PSplashFont *font,
- const char *text)
-{
- char *c = (char*)text;
- wchar_t wc;
- int k, n, w, h, mw;
-
- n = strlen (text);
- mw = h = w = 0;
-
- mbtowc (0, 0, 0);
- for (; (k = mbtowc (&wc, c, n)) > 0; c += k, n -= k)
- {
- if (*c == '\n')
- {
- if (w > mw)
- mw = w;
- w = 0;
- h += font->height;
- continue;
- }
-
- w += psplash_font_glyph (font, wc, NULL);
- }
-
- *width = (w > mw) ? w : mw;
- *height = (h == 0) ? font->height : h;
-}
-
-void
-psplash_fb_draw_text (PSplashFB *fb,
- int x,
- int y,
- uint8 red,
- uint8 green,
- uint8 blue,
- const PSplashFont *font,
- const char *text)
-{
- int h, w, k, n, cx, cy, dx, dy;
- char *c = (char*)text;
- wchar_t wc;
-
- n = strlen (text);
- h = font->height;
- dx = dy = 0;
-
- mbtowc (0, 0, 0);
- for (; (k = mbtowc (&wc, c, n)) > 0; c += k, n -= k)
- {
- u_int32_t *glyph = NULL;
-
- if (*c == '\n')
- {
- dy += h;
- dx = 0;
- continue;
- }
-
- w = psplash_font_glyph (font, wc, &glyph);
-
- if (glyph == NULL)
- continue;
-
- for (cy = 0; cy < h; cy++)
- {
- u_int32_t g = *glyph++;
-
- for (cx = 0; cx < w; cx++)
- {
- if (g & 0x80000000)
- psplash_plot_pixel(&fb->canvas, x+dx+cx, y+dy+cy,
- red, green, blue);
- g <<= 1;
- }
- }
-
- dx += w;
- }
-}
-
diff --git a/psplash-fb.h b/psplash-fb.h
index 1eecb47..1b16bd5 100644
--- a/psplash-fb.h
+++ b/psplash-fb.h
@@ -40,22 +40,6 @@ psplash_fb_destroy (PSplashFB *fb);
PSplashFB*
psplash_fb_new (int angle, int fbdev_id);
-void
-psplash_fb_text_size (int *width,
- int *height,
- const PSplashFont *font,
- const char *text);
-
-void
-psplash_fb_draw_text (PSplashFB *fb,
- int x,
- int y,
- uint8 red,
- uint8 green,
- uint8 blue,
- const PSplashFont *font,
- const char *text);
-
void
psplash_fb_flip(PSplashFB *fb, int sync);
diff --git a/psplash.c b/psplash.c
index 2aeb583..1a5e543 100644
--- a/psplash.c
+++ b/psplash.c
@@ -41,7 +41,7 @@ psplash_draw_msg (PSplashFB *fb, const char *msg)
{
int w, h;
- psplash_fb_text_size (&w, &h, &FONT_DEF, msg);
+ psplash_text_size(&w, &h, &FONT_DEF, msg);
DBG("displaying '%s' %ix%i\n", msg, w, h);
@@ -54,7 +54,7 @@ psplash_draw_msg (PSplashFB *fb, const char *msg)
h,
PSPLASH_BACKGROUND_COLOR);
- psplash_fb_draw_text (fb,
+ psplash_draw_text(&fb->canvas,
(fb->canvas.width-w)/2,
SPLIT_LINE_POS(fb) - h,
PSPLASH_TEXT_COLOR,
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 08/14] psplash.c: Make psplash_draw_{msg,progress} independent of FB
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (6 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 07/14] Extract draw font " Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 09/14] Rework flip as function pointer Vasyl Vavrychuk
` (6 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash.c | 64 ++++++++++++++++++++++++++++---------------------------
1 file changed, 33 insertions(+), 31 deletions(-)
diff --git a/psplash.c b/psplash.c
index 1a5e543..c234d46 100644
--- a/psplash.c
+++ b/psplash.c
@@ -21,11 +21,11 @@
#endif
#include FONT_HEADER
-#define SPLIT_LINE_POS(fb) \
- ( (fb)->canvas.height \
- - (( PSPLASH_IMG_SPLIT_DENOMINATOR \
- - PSPLASH_IMG_SPLIT_NUMERATOR) \
- * (fb)->canvas.height / PSPLASH_IMG_SPLIT_DENOMINATOR) \
+#define SPLIT_LINE_POS(canvas) \
+ ( (canvas)->height \
+ - (( PSPLASH_IMG_SPLIT_DENOMINATOR \
+ - PSPLASH_IMG_SPLIT_NUMERATOR) \
+ * (canvas)->height / PSPLASH_IMG_SPLIT_DENOMINATOR) \
)
void
@@ -37,7 +37,7 @@ psplash_exit (int UNUSED(signum))
}
void
-psplash_draw_msg (PSplashFB *fb, const char *msg)
+psplash_draw_msg(PSplashCanvas *canvas, const char *msg)
{
int w, h;
@@ -47,16 +47,16 @@ psplash_draw_msg (PSplashFB *fb, const char *msg)
/* Clear */
- psplash_draw_rect(&fb->canvas,
+ psplash_draw_rect(canvas,
0,
- SPLIT_LINE_POS(fb) - h,
- fb->canvas.width,
+ SPLIT_LINE_POS(canvas) - h,
+ canvas->width,
h,
PSPLASH_BACKGROUND_COLOR);
- psplash_draw_text(&fb->canvas,
- (fb->canvas.width-w)/2,
- SPLIT_LINE_POS(fb) - h,
+ psplash_draw_text(canvas,
+ (canvas->width-w)/2,
+ SPLIT_LINE_POS(canvas) - h,
PSPLASH_TEXT_COLOR,
&FONT_DEF,
msg);
@@ -64,32 +64,32 @@ psplash_draw_msg (PSplashFB *fb, const char *msg)
#ifdef PSPLASH_SHOW_PROGRESS_BAR
void
-psplash_draw_progress (PSplashFB *fb, int value)
+psplash_draw_progress(PSplashCanvas *canvas, int value)
{
int x, y, width, height, barwidth;
/* 4 pix border */
- x = ((fb->canvas.width - BAR_IMG_WIDTH)/2) + 4 ;
- y = SPLIT_LINE_POS(fb) + 4;
+ x = ((canvas->width - BAR_IMG_WIDTH)/2) + 4 ;
+ y = SPLIT_LINE_POS(canvas) + 4;
width = BAR_IMG_WIDTH - 8;
height = BAR_IMG_HEIGHT - 8;
if (value > 0)
{
barwidth = (CLAMP(value,0,100) * width) / 100;
- psplash_draw_rect(&fb->canvas, x + barwidth, y,
+ psplash_draw_rect(canvas, x + barwidth, y,
width - barwidth, height,
PSPLASH_BAR_BACKGROUND_COLOR);
- psplash_draw_rect(&fb->canvas, x, y, barwidth,
+ psplash_draw_rect(canvas, x, y, barwidth,
height, PSPLASH_BAR_COLOR);
}
else
{
barwidth = (CLAMP(-value,0,100) * width) / 100;
- psplash_draw_rect(&fb->canvas, x, y,
+ psplash_draw_rect(canvas, x, y,
width - barwidth, height,
PSPLASH_BAR_BACKGROUND_COLOR);
- psplash_draw_rect(&fb->canvas, x + width - barwidth,
+ psplash_draw_rect(canvas, x + width - barwidth,
y, barwidth, height,
PSPLASH_BAR_COLOR);
}
@@ -116,7 +116,7 @@ parse_command (PSplashFB *fb, char *string)
char *arg = strtok(NULL, "\0");
if (arg)
- psplash_draw_msg (fb, arg);
+ psplash_draw_msg(&fb->canvas, arg);
}
#ifdef PSPLASH_SHOW_PROGRESS_BAR
else if (!strcmp(command,"PROGRESS"))
@@ -124,7 +124,7 @@ parse_command (PSplashFB *fb, char *string)
char *arg = strtok(NULL, "\0");
if (arg)
- psplash_draw_progress (fb, atoi(arg));
+ psplash_draw_progress(&fb->canvas, atoi(arg));
}
#endif
else if (!strcmp(command,"QUIT"))
@@ -226,6 +226,7 @@ main (int argc, char** argv)
char *rundir;
int pipe_fd, i = 0, angle = 0, fbdev_id = 0, ret = 0;
PSplashFB *fb;
+ PSplashCanvas *canvas;
bool disable_console_switch = FALSE;
signal(SIGHUP, psplash_exit);
@@ -295,22 +296,23 @@ main (int argc, char** argv)
ret = -1;
goto fb_fail;
}
+ canvas = &fb->canvas;
#ifdef HAVE_SYSTEMD
sd_notify(0, "READY=1");
#endif
/* Clear the background with #ecece1 */
- psplash_draw_rect(&fb->canvas, 0, 0, fb->canvas.width, fb->canvas.height,
+ psplash_draw_rect(canvas, 0, 0, canvas->width, canvas->height,
PSPLASH_BACKGROUND_COLOR);
/* Draw the Poky logo */
- psplash_draw_image(&fb->canvas,
- (fb->canvas.width - POKY_IMG_WIDTH)/2,
+ psplash_draw_image(canvas,
+ (canvas->width - POKY_IMG_WIDTH)/2,
#if PSPLASH_IMG_FULLSCREEN
- (fb->canvas.height - POKY_IMG_HEIGHT)/2,
+ (canvas->height - POKY_IMG_HEIGHT)/2,
#else
- (fb->canvas.height * PSPLASH_IMG_SPLIT_NUMERATOR
+ (canvas->height * PSPLASH_IMG_SPLIT_NUMERATOR
/ PSPLASH_IMG_SPLIT_DENOMINATOR - POKY_IMG_HEIGHT)/2,
#endif
POKY_IMG_WIDTH,
@@ -321,20 +323,20 @@ main (int argc, char** argv)
#ifdef PSPLASH_SHOW_PROGRESS_BAR
/* Draw progress bar border */
- psplash_draw_image(&fb->canvas,
- (fb->canvas.width - BAR_IMG_WIDTH)/2,
- SPLIT_LINE_POS(fb),
+ psplash_draw_image(canvas,
+ (canvas->width - BAR_IMG_WIDTH)/2,
+ SPLIT_LINE_POS(canvas),
BAR_IMG_WIDTH,
BAR_IMG_HEIGHT,
BAR_IMG_BYTES_PER_PIXEL,
BAR_IMG_ROWSTRIDE,
BAR_IMG_RLE_PIXEL_DATA);
- psplash_draw_progress (fb, 0);
+ psplash_draw_progress(canvas, 0);
#endif
#ifdef PSPLASH_STARTUP_MSG
- psplash_draw_msg (fb, PSPLASH_STARTUP_MSG);
+ psplash_draw_msg(canvas, PSPLASH_STARTUP_MSG);
#endif
/* Scene set so let's flip the buffers. */
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 09/14] Rework flip as function pointer
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (7 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 08/14] psplash.c: Make psplash_draw_{msg,progress} independent of FB Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 10/14] Import drm-howto modeset.c as psplash-drm.c Vasyl Vavrychuk
` (5 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
It allows making parse_command and psplash_main independent of FB.
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-draw.h | 3 +++
psplash-fb.c | 8 +++++---
psplash-fb.h | 3 ---
psplash.c | 16 ++++++++--------
4 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/psplash-draw.h b/psplash-draw.h
index 44546b0..292ddd9 100644
--- a/psplash-draw.h
+++ b/psplash-draw.h
@@ -36,6 +36,9 @@ typedef struct PSplashCanvas
int green_length;
int blue_offset;
int blue_length;
+
+ void *priv;
+ void (*flip)(struct PSplashCanvas *canvas, int sync);
}
PSplashCanvas;
diff --git a/psplash-fb.c b/psplash-fb.c
index dd50a5a..d41c477 100644
--- a/psplash-fb.c
+++ b/psplash-fb.c
@@ -18,9 +18,10 @@ psplash_wait_for_vsync(PSplashFB *fb)
fprintf(stderr, "Error, FB vsync ioctl [%d]\n", err);
}
-void
-psplash_fb_flip(PSplashFB *fb, int sync)
+static void
+psplash_fb_flip(PSplashCanvas *canvas, int sync)
{
+ PSplashFB *fb = canvas->priv;
char *tmp;
if (fb->double_buffering) {
@@ -154,7 +155,8 @@ psplash_fb_new (int angle, int fbdev_id)
}
memset (fb, 0, sizeof(PSplashFB));
-
+ fb->canvas.priv = fb;
+ fb->canvas.flip = psplash_fb_flip;
fb->fd = -1;
if ((fb->fd = open (fbdev, O_RDWR)) < 0)
diff --git a/psplash-fb.h b/psplash-fb.h
index 1b16bd5..979d23a 100644
--- a/psplash-fb.h
+++ b/psplash-fb.h
@@ -40,7 +40,4 @@ psplash_fb_destroy (PSplashFB *fb);
PSplashFB*
psplash_fb_new (int angle, int fbdev_id);
-void
-psplash_fb_flip(PSplashFB *fb, int sync);
-
#endif
diff --git a/psplash.c b/psplash.c
index c234d46..036dfb1 100644
--- a/psplash.c
+++ b/psplash.c
@@ -100,7 +100,7 @@ psplash_draw_progress(PSplashCanvas *canvas, int value)
#endif /* PSPLASH_SHOW_PROGRESS_BAR */
static int
-parse_command (PSplashFB *fb, char *string)
+parse_command(PSplashCanvas *canvas, char *string)
{
char *command;
@@ -116,7 +116,7 @@ parse_command (PSplashFB *fb, char *string)
char *arg = strtok(NULL, "\0");
if (arg)
- psplash_draw_msg(&fb->canvas, arg);
+ psplash_draw_msg(canvas, arg);
}
#ifdef PSPLASH_SHOW_PROGRESS_BAR
else if (!strcmp(command,"PROGRESS"))
@@ -124,7 +124,7 @@ parse_command (PSplashFB *fb, char *string)
char *arg = strtok(NULL, "\0");
if (arg)
- psplash_draw_progress(&fb->canvas, atoi(arg));
+ psplash_draw_progress(canvas, atoi(arg));
}
#endif
else if (!strcmp(command,"QUIT"))
@@ -132,12 +132,12 @@ parse_command (PSplashFB *fb, char *string)
return 1;
}
- psplash_fb_flip(fb, 0);
+ canvas->flip(canvas, 0);
return 0;
}
void
-psplash_main (PSplashFB *fb, int pipe_fd, int timeout)
+psplash_main(PSplashCanvas *canvas, int pipe_fd, int timeout)
{
int err;
ssize_t length = 0;
@@ -200,7 +200,7 @@ psplash_main (PSplashFB *fb, int pipe_fd, int timeout)
continue;
}
- if (parse_command(fb, cmd))
+ if (parse_command(canvas, cmd))
return;
length -= cmdlen;
@@ -345,9 +345,9 @@ main (int argc, char** argv)
* text and progress bar change which overwrite the specific areas with every
* update.
*/
- psplash_fb_flip(fb, 1);
+ canvas->flip(canvas, 1);
- psplash_main (fb, pipe_fd, 0);
+ psplash_main(canvas, pipe_fd, 0);
psplash_fb_destroy (fb);
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 10/14] Import drm-howto modeset.c as psplash-drm.c
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (8 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 09/14] Rework flip as function pointer Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 11/14] Implement drm backend Vasyl Vavrychuk
` (4 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Imported as is from
repo: https://github.com/dvdhrm/docs.git
branch: master
commit: fc5c63f
path: drm-howto/modeset.c
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-drm.c | 735 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 735 insertions(+)
create mode 100644 psplash-drm.c
diff --git a/psplash-drm.c b/psplash-drm.c
new file mode 100644
index 0000000..c9a9f5c
--- /dev/null
+++ b/psplash-drm.c
@@ -0,0 +1,735 @@
+/*
+ * modeset - DRM Modesetting Example
+ *
+ * Written 2012 by David Rheinsberg <david.rheinsberg@gmail.com>
+ * Dedicated to the Public Domain.
+ */
+
+/*
+ * DRM Modesetting Howto
+ * This document describes the DRM modesetting API. Before we can use the DRM
+ * API, we have to include xf86drm.h and xf86drmMode.h. Both are provided by
+ * libdrm which every major distribution ships by default. It has no other
+ * dependencies and is pretty small.
+ *
+ * Please ignore all forward-declarations of functions which are used later. I
+ * reordered the functions so you can read this document from top to bottom. If
+ * you reimplement it, you would probably reorder the functions to avoid all the
+ * nasty forward declarations.
+ *
+ * For easier reading, we ignore all memory-allocation errors of malloc() and
+ * friends here. However, we try to correctly handle all other kinds of errors
+ * that may occur.
+ *
+ * All functions and global variables are prefixed with "modeset_*" in this
+ * file. So it should be clear whether a function is a local helper or if it is
+ * 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>
+#include <string.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+struct modeset_dev;
+static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
+ struct modeset_dev *dev);
+static int modeset_create_fb(int fd, struct modeset_dev *dev);
+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
+ * correct device driver (located in kernel-tree at ./drivers/gpu/drm/<xy>) and
+ * provides two character-devices to control it. Udev (or whatever hotplugging
+ * application you use) will create them as:
+ * /dev/dri/card0
+ * /dev/dri/controlID64
+ * We only need the first one. You can hard-code this path into your application
+ * like we do here, but it is recommended to use libudev with real hotplugging
+ * and multi-seat support. However, this is beyond the scope of this document.
+ * Also note that if you have multiple graphics-cards, there may also be
+ * /dev/dri/card1, /dev/dri/card2, ...
+ *
+ * We simply use /dev/dri/card0 here but the user can specify another path on
+ * the command line.
+ *
+ * modeset_open(out, node): This small helper function opens the DRM device
+ * which is given as @node. The new fd is stored in @out on success. On failure,
+ * a negative error code is returned.
+ * After opening the file, we also check for the DRM_CAP_DUMB_BUFFER capability.
+ * If the driver supports this capability, we can create simple memory-mapped
+ * buffers without any driver-dependent code. As we want to avoid any radeon,
+ * nvidia, intel, etc. specific code, we depend on DUMB_BUFFERs here.
+ */
+
+static int modeset_open(int *out, const char *node)
+{
+ int fd, ret;
+ uint64_t has_dumb;
+
+ fd = open(node, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ ret = -errno;
+ fprintf(stderr, "cannot open '%s': %m\n", node);
+ return ret;
+ }
+
+ if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 ||
+ !has_dumb) {
+ fprintf(stderr, "drm device '%s' does not support dumb buffers\n",
+ node);
+ close(fd);
+ return -EOPNOTSUPP;
+ }
+
+ *out = fd;
+ return 0;
+}
+
+/*
+ * As a next step we need to find our available display devices. libdrm provides
+ * a drmModeRes structure that contains all the needed information. We can
+ * retrieve it via drmModeGetResources(fd) and free it via
+ * drmModeFreeResources(res) again.
+ *
+ * A physical connector on your graphics card is called a "connector". You can
+ * plug a monitor into it and control what is displayed. We are definitely
+ * interested in what connectors are currently used, so we simply iterate
+ * through the list of connectors and try to display a test-picture on each
+ * available monitor.
+ * However, this isn't as easy as it sounds. First, we need to check whether the
+ * connector is actually used (a monitor is plugged in and turned on). Then we
+ * need to find a CRTC that can control this connector. CRTCs are described
+ * later on. After that we create a framebuffer object. If we have all this, we
+ * can mmap() the framebuffer and draw a test-picture into it. Then we can tell
+ * the DRM device to show the framebuffer on the given CRTC with the selected
+ * connector.
+ *
+ * As we want to draw moving pictures on the framebuffer, we actually have to
+ * remember all these settings. Therefore, we create one "struct modeset_dev"
+ * object for each connector+crtc+framebuffer pair that we successfully
+ * initialized and push it into the global device-list.
+ *
+ * Each field of this structure is described when it is first used. But as a
+ * summary:
+ * "struct modeset_dev" contains: {
+ * - @next: points to the next device in the single-linked list
+ *
+ * - @width: width of our buffer object
+ * - @height: height of our buffer object
+ * - @stride: stride value of our buffer object
+ * - @size: size of the memory mapped buffer
+ * - @handle: a DRM handle to the buffer object that we can draw into
+ * - @map: pointer to the memory mapped buffer
+ *
+ * - @mode: the display mode that we want to use
+ * - @fb: a framebuffer handle with our buffer object as scanout buffer
+ * - @conn: the connector ID that we want to use with this buffer
+ * - @crtc: the crtc ID that we want to use with this connector
+ * - @saved_crtc: the configuration of the crtc before we changed it. We use it
+ * so we can restore the same mode when we exit.
+ * }
+ */
+
+struct modeset_dev {
+ struct modeset_dev *next;
+
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t size;
+ uint32_t handle;
+ uint8_t *map;
+
+ drmModeModeInfo mode;
+ uint32_t fb;
+ uint32_t conn;
+ uint32_t crtc;
+ drmModeCrtc *saved_crtc;
+};
+
+static struct modeset_dev *modeset_list = NULL;
+
+/*
+ * So as next step we need to actually prepare all connectors that we find. We
+ * do this in this little helper function:
+ *
+ * modeset_prepare(fd): This helper function takes the DRM fd as argument and
+ * then simply retrieves the resource-info from the device. It then iterates
+ * through all connectors and calls other helper functions to initialize this
+ * connector (described later on).
+ * If the initialization was successful, we simply add this object as new device
+ * into the global modeset device list.
+ *
+ * The resource-structure contains a list of all connector-IDs. We use the
+ * helper function drmModeGetConnector() to retrieve more information on each
+ * connector. After we are done with it, we free it again with
+ * drmModeFreeConnector().
+ * Our helper modeset_setup_dev() returns -ENOENT if the connector is currently
+ * unused and no monitor is plugged in. So we can ignore this connector.
+ */
+
+static int modeset_prepare(int fd)
+{
+ drmModeRes *res;
+ drmModeConnector *conn;
+ unsigned int i;
+ struct modeset_dev *dev;
+ int ret;
+
+ /* retrieve resources */
+ res = drmModeGetResources(fd);
+ if (!res) {
+ fprintf(stderr, "cannot retrieve DRM resources (%d): %m\n",
+ errno);
+ return -errno;
+ }
+
+ /* iterate all connectors */
+ for (i = 0; i < res->count_connectors; ++i) {
+ /* get information for each connector */
+ conn = drmModeGetConnector(fd, res->connectors[i]);
+ if (!conn) {
+ fprintf(stderr, "cannot retrieve DRM connector %u:%u (%d): %m\n",
+ i, res->connectors[i], errno);
+ continue;
+ }
+
+ /* create a device structure */
+ dev = malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ dev->conn = conn->connector_id;
+
+ /* call helper function to prepare this connector */
+ ret = modeset_setup_dev(fd, res, conn, dev);
+ if (ret) {
+ if (ret != -ENOENT) {
+ errno = -ret;
+ fprintf(stderr, "cannot setup device for connector %u:%u (%d): %m\n",
+ i, res->connectors[i], errno);
+ }
+ free(dev);
+ drmModeFreeConnector(conn);
+ continue;
+ }
+
+ /* free connector data and link device into global list */
+ drmModeFreeConnector(conn);
+ dev->next = modeset_list;
+ modeset_list = dev;
+ }
+
+ /* free resources again */
+ drmModeFreeResources(res);
+ return 0;
+}
+
+/*
+ * Now we dig deeper into setting up a single connector. As described earlier,
+ * we need to check several things first:
+ * * If the connector is currently unused, that is, no monitor is plugged in,
+ * then we can ignore it.
+ * * We have to find a suitable resolution and refresh-rate. All this is
+ * available in drmModeModeInfo structures saved for each crtc. We simply
+ * use the first mode that is available. This is always the mode with the
+ * highest resolution.
+ * A more sophisticated mode-selection should be done in real applications,
+ * though.
+ * * Then we need to find an CRTC that can drive this connector. A CRTC is an
+ * internal resource of each graphics-card. The number of CRTCs controls how
+ * many connectors can be controlled indepedently. That is, a graphics-cards
+ * may have more connectors than CRTCs, which means, not all monitors can be
+ * controlled independently.
+ * There is actually the possibility to control multiple connectors via a
+ * single CRTC if the monitors should display the same content. However, we
+ * do not make use of this here.
+ * So think of connectors as pipelines to the connected monitors and the
+ * CRTCs are the controllers that manage which data goes to which pipeline.
+ * If there are more pipelines than CRTCs, then we cannot control all of
+ * them at the same time.
+ * * We need to create a framebuffer for this connector. A framebuffer is a
+ * memory buffer that we can write XRGB32 data into. So we use this to
+ * render our graphics and then the CRTC can scan-out this data from the
+ * framebuffer onto the monitor.
+ */
+
+static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn,
+ struct modeset_dev *dev)
+{
+ int ret;
+
+ /* check if a monitor is connected */
+ if (conn->connection != DRM_MODE_CONNECTED) {
+ fprintf(stderr, "ignoring unused connector %u\n",
+ conn->connector_id);
+ return -ENOENT;
+ }
+
+ /* check if there is at least one valid mode */
+ if (conn->count_modes == 0) {
+ fprintf(stderr, "no valid mode for connector %u\n",
+ conn->connector_id);
+ return -EFAULT;
+ }
+
+ /* copy the mode information into our device structure */
+ memcpy(&dev->mode, &conn->modes[0], sizeof(dev->mode));
+ dev->width = conn->modes[0].hdisplay;
+ dev->height = conn->modes[0].vdisplay;
+ fprintf(stderr, "mode for connector %u is %ux%u\n",
+ conn->connector_id, dev->width, dev->height);
+
+ /* find a crtc for this connector */
+ ret = modeset_find_crtc(fd, res, conn, dev);
+ if (ret) {
+ fprintf(stderr, "no valid crtc for connector %u\n",
+ conn->connector_id);
+ return ret;
+ }
+
+ /* create a framebuffer for this CRTC */
+ ret = modeset_create_fb(fd, dev);
+ if (ret) {
+ fprintf(stderr, "cannot create framebuffer for connector %u\n",
+ conn->connector_id);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * modeset_find_crtc(fd, res, conn, dev): This small helper tries to find a
+ * suitable CRTC for the given connector. We have actually have to introduce one
+ * more DRM object to make this more clear: Encoders.
+ * Encoders help the CRTC to convert data from a framebuffer into the right
+ * format that can be used for the chosen connector. We do not have to
+ * understand any more of these conversions to make use of it. However, you must
+ * know that each connector has a limited list of encoders that it can use. And
+ * each encoder can only work with a limited list of CRTCs. So what we do is
+ * trying each encoder that is available and looking for a CRTC that this
+ * encoder can work with. If we find the first working combination, we are happy
+ * and write it into the @dev structure.
+ * But before iterating all available encoders, we first try the currently
+ * active encoder+crtc on a connector to avoid a full modeset.
+ *
+ * However, before we can use a CRTC we must make sure that no other device,
+ * that we setup previously, is already using this CRTC. Remember, we can only
+ * drive one connector per CRTC! So we simply iterate through the "modeset_list"
+ * of previously setup devices and check that this CRTC wasn't used before.
+ * Otherwise, we continue with the next CRTC/Encoder combination.
+ */
+
+static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
+ struct modeset_dev *dev)
+{
+ drmModeEncoder *enc;
+ unsigned int i, j;
+ int32_t crtc;
+ struct modeset_dev *iter;
+
+ /* first try the currently conected encoder+crtc */
+ if (conn->encoder_id)
+ enc = drmModeGetEncoder(fd, conn->encoder_id);
+ else
+ enc = NULL;
+
+ if (enc) {
+ if (enc->crtc_id) {
+ crtc = enc->crtc_id;
+ for (iter = modeset_list; iter; iter = iter->next) {
+ if (iter->crtc == crtc) {
+ crtc = -1;
+ break;
+ }
+ }
+
+ if (crtc >= 0) {
+ drmModeFreeEncoder(enc);
+ dev->crtc = crtc;
+ return 0;
+ }
+ }
+
+ drmModeFreeEncoder(enc);
+ }
+
+ /* If the connector is not currently bound to an encoder or if the
+ * encoder+crtc is already used by another connector (actually unlikely
+ * but lets be safe), iterate all other available encoders to find a
+ * matching CRTC. */
+ for (i = 0; i < conn->count_encoders; ++i) {
+ enc = drmModeGetEncoder(fd, conn->encoders[i]);
+ if (!enc) {
+ fprintf(stderr, "cannot retrieve encoder %u:%u (%d): %m\n",
+ i, conn->encoders[i], errno);
+ continue;
+ }
+
+ /* iterate all global CRTCs */
+ for (j = 0; j < res->count_crtcs; ++j) {
+ /* check whether this CRTC works with the encoder */
+ if (!(enc->possible_crtcs & (1 << j)))
+ continue;
+
+ /* 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) {
+ crtc = -1;
+ break;
+ }
+ }
+
+ /* we have found a CRTC, so save it and return */
+ if (crtc >= 0) {
+ drmModeFreeEncoder(enc);
+ dev->crtc = crtc;
+ return 0;
+ }
+ }
+
+ drmModeFreeEncoder(enc);
+ }
+
+ fprintf(stderr, "cannot find suitable CRTC for connector %u\n",
+ conn->connector_id);
+ return -ENOENT;
+}
+
+/*
+ * modeset_create_fb(fd, dev): After we have found a crtc+connector+mode
+ * combination, we need to actually create a suitable framebuffer that we can
+ * use with it. There are actually two ways to do that:
+ * * We can create a so called "dumb buffer". This is a buffer that we can
+ * memory-map via mmap() and every driver supports this. We can use it for
+ * unaccelerated software rendering on the CPU.
+ * * We can use libgbm to create buffers available for hardware-acceleration.
+ * libgbm is an abstraction layer that creates these buffers for each
+ * available DRM driver. As there is no generic API for this, each driver
+ * provides its own way to create these buffers.
+ * We can then use such buffers to create OpenGL contexts with the mesa3D
+ * library.
+ * We use the first solution here as it is much simpler and doesn't require any
+ * external libraries. However, if you want to use hardware-acceleration via
+ * OpenGL, it is actually pretty easy to create such buffers with libgbm and
+ * libEGL. But this is beyond the scope of this document.
+ *
+ * So what we do is requesting a new dumb-buffer from the driver. We specify the
+ * same size as the current mode that we selected for the connector.
+ * Then we request the driver to prepare this buffer for memory mapping. After
+ * that we perform the actual mmap() call. So we can now access the framebuffer
+ * memory directly via the dev->map memory map.
+ */
+
+static int modeset_create_fb(int fd, struct modeset_dev *dev)
+{
+ struct drm_mode_create_dumb creq;
+ struct drm_mode_destroy_dumb dreq;
+ struct drm_mode_map_dumb mreq;
+ int ret;
+
+ /* create dumb buffer */
+ memset(&creq, 0, sizeof(creq));
+ creq.width = dev->width;
+ creq.height = dev->height;
+ creq.bpp = 32;
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
+ if (ret < 0) {
+ fprintf(stderr, "cannot create dumb buffer (%d): %m\n",
+ errno);
+ return -errno;
+ }
+ dev->stride = creq.pitch;
+ dev->size = creq.size;
+ dev->handle = creq.handle;
+
+ /* create framebuffer object for the dumb-buffer */
+ ret = drmModeAddFB(fd, dev->width, dev->height, 24, 32, dev->stride,
+ dev->handle, &dev->fb);
+ if (ret) {
+ fprintf(stderr, "cannot create framebuffer (%d): %m\n",
+ errno);
+ ret = -errno;
+ goto err_destroy;
+ }
+
+ /* prepare buffer for memory mapping */
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.handle = dev->handle;
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
+ if (ret) {
+ fprintf(stderr, "cannot map dumb buffer (%d): %m\n",
+ errno);
+ ret = -errno;
+ goto err_fb;
+ }
+
+ /* perform actual memory mapping */
+ dev->map = mmap(0, dev->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, mreq.offset);
+ if (dev->map == MAP_FAILED) {
+ fprintf(stderr, "cannot mmap dumb buffer (%d): %m\n",
+ errno);
+ ret = -errno;
+ goto err_fb;
+ }
+
+ /* clear the framebuffer to 0 */
+ memset(dev->map, 0, dev->size);
+
+ return 0;
+
+err_fb:
+ drmModeRmFB(fd, dev->fb);
+err_destroy:
+ memset(&dreq, 0, sizeof(dreq));
+ dreq.handle = dev->handle;
+ drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ return ret;
+}
+
+/*
+ * 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.
+ * There is nothing special left to do. We only have to program the CRTC to
+ * connect each new framebuffer to each selected connector for each combination
+ * that we saved in the global modeset_list.
+ * This is done with a call to drmModeSetCrtc().
+ *
+ * So we are ready for our main() function. First we check whether the user
+ * specified a DRM device on the command line, otherwise we use the default
+ * /dev/dri/card0. Then we open the device via modeset_open(). modeset_prepare()
+ * prepares all connectors and we can loop over "modeset_list" and call
+ * drmModeSetCrtc() on every CRTC/connector combination.
+ *
+ * But printing empty black pages is boring so we have another helper function
+ * modeset_draw() that draws some colors into the framebuffer for 5 seconds and
+ * then returns. And then we have all the cleanup functions which correctly free
+ * all devices again after we used them. All these functions are described below
+ * the main() function.
+ *
+ * As a side note: drmModeSetCrtc() actually takes a list of connectors that we
+ * want to control with this CRTC. We pass only one connector, though. As
+ * explained earlier, if we used multiple connectors, then all connectors would
+ * have the same controlling framebuffer so the output would be cloned. This is
+ * most often not what you want so we avoid explaining this feature here.
+ * Furthermore, all connectors will have to run with the same mode, which is
+ * 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.
+ * 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)
+{
+ int ret, fd;
+ const char *card;
+ struct modeset_dev *iter;
+
+ /* check which DRM device to open */
+ if (argc > 1)
+ card = argv[1];
+ else
+ card = "/dev/dri/card0";
+
+ fprintf(stderr, "using card '%s'\n", card);
+
+ /* open the DRM device */
+ ret = modeset_open(&fd, card);
+ if (ret)
+ goto out_return;
+
+ /* prepare all connectors and CRTCs */
+ ret = modeset_prepare(fd);
+ if (ret)
+ goto out_close;
+
+ /* 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->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;
+}
+
+/*
+ * 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
+ * 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)
+{
+ struct modeset_dev *iter;
+ struct drm_mode_destroy_dumb dreq;
+
+ while (modeset_list) {
+ /* remove from global list */
+ iter = modeset_list;
+ modeset_list = iter->next;
+
+ /* restore saved CRTC configuration */
+ drmModeSetCrtc(fd,
+ iter->saved_crtc->crtc_id,
+ iter->saved_crtc->buffer_id,
+ iter->saved_crtc->x,
+ iter->saved_crtc->y,
+ &iter->conn,
+ 1,
+ &iter->saved_crtc->mode);
+ drmModeFreeCrtc(iter->saved_crtc);
+
+ /* unmap buffer */
+ munmap(iter->map, iter->size);
+
+ /* delete framebuffer */
+ drmModeRmFB(fd, iter->fb);
+
+ /* delete dumb buffer */
+ memset(&dreq, 0, sizeof(dreq));
+ dreq.handle = iter->handle;
+ drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+
+ /* free allocated memory */
+ free(iter);
+ }
+}
+
+/*
+ * I hope this was a short but easy overview of the DRM modesetting API. The DRM
+ * API offers much more capabilities including:
+ * - double-buffering or tripple-buffering (or whatever you want)
+ * - vsync'ed page-flips
+ * - hardware-accelerated rendering (for example via OpenGL)
+ * - output cloning
+ * - graphics-clients plus authentication
+ * - DRM planes/overlays/sprites
+ * - ...
+ * If you are interested in these topics, I can currently only redirect you to
+ * existing implementations, including:
+ * - plymouth (which uses dumb-buffers like this example; very easy to understand)
+ * - kmscon (which uses libuterm to do this)
+ * - wayland (very sophisticated DRM renderer; hard to understand fully as it
+ * uses more complicated techniques like DRM planes)
+ * - xserver (very hard to understand as it is split across many files/projects)
+ *
+ * But understanding how modesetting (as described in this document) works, is
+ * essential to understand all further DRM topics.
+ *
+ * Any feedback is welcome. Feel free to use this code freely for your own
+ * documentation or projects.
+ *
+ * - Hosted on http://github.com/dvdhrm/docs
+ * - Written by David Rheinsberg <david.rheinsberg@gmail.com>
+ */
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 11/14] Implement drm backend
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (9 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 10/14] Import drm-howto modeset.c as psplash-drm.c Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 12/14] Reverse modeset_list Vasyl Vavrychuk
` (3 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Limitation is that splash screen is drawn only on the first connector.
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.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 12/14] Reverse modeset_list
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (10 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 11/14] Implement drm backend Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 13/14] psplash-drm.c: Allocate resources only for the first connector Vasyl Vavrychuk
` (2 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Now, it has the same order as connectors in drmModeGetResources. As
result splash screen will be drawn on the first connector.
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-drm.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/psplash-drm.c b/psplash-drm.c
index 30850ed..2468cf1 100644
--- a/psplash-drm.c
+++ b/psplash-drm.c
@@ -185,7 +185,7 @@ static int modeset_prepare(int fd)
drmModeRes *res;
drmModeConnector *conn;
int i;
- struct modeset_dev *dev;
+ struct modeset_dev *dev, *last_dev = NULL;
int ret;
/* retrieve resources */
@@ -226,8 +226,13 @@ static int modeset_prepare(int fd)
/* free connector data and link device into global list */
drmModeFreeConnector(conn);
- dev->next = modeset_list;
- modeset_list = dev;
+ if (last_dev == NULL) {
+ modeset_list = dev;
+ last_dev = dev;
+ } else {
+ last_dev->next = dev;
+ last_dev = dev;
+ }
}
/* free resources again */
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 13/14] psplash-drm.c: Allocate resources only for the first connector
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (11 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 12/14] Reverse modeset_list Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 14/14] psplash-drm.c: Implement double buffering Vasyl Vavrychuk
2022-04-25 8:24 ` [yocto] [psplash][RFC PATCH 00/14] Implement DRM backend Alexander Kanavin
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Since splash screen is shown only on the first scanout, there is no need
to allocate resources for next connectors.
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-drm.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/psplash-drm.c b/psplash-drm.c
index 2468cf1..5e56286 100644
--- a/psplash-drm.c
+++ b/psplash-drm.c
@@ -39,6 +39,8 @@
#include <xf86drmMode.h>
#include "psplash-drm.h"
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
struct modeset_dev;
static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
struct modeset_dev *dev);
@@ -196,8 +198,10 @@ static int modeset_prepare(int fd)
return -errno;
}
- /* iterate all connectors */
- for (i = 0; i < res->count_connectors; ++i) {
+ /* ~iterate all connectors~ - Use first connector if present. It is
+ optimization related workaround since psplash supports drawing splash
+ screen on one scanout anyway. */
+ for (i = 0; i < MIN(res->count_connectors, 1); ++i) {
/* get information for each connector */
conn = drmModeGetConnector(fd, res->connectors[i]);
if (!conn) {
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [psplash][RFC PATCH 14/14] psplash-drm.c: Implement double buffering
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (12 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 13/14] psplash-drm.c: Allocate resources only for the first connector Vasyl Vavrychuk
@ 2022-04-25 7:59 ` Vasyl Vavrychuk
2022-04-25 8:24 ` [yocto] [psplash][RFC PATCH 00/14] Implement DRM backend Alexander Kanavin
14 siblings, 0 replies; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-25 7:59 UTC (permalink / raw)
To: yocto; +Cc: Vasyl Vavrychuk
Based on
https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-double-buffered.c
Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
psplash-drm.c | 176 +++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 140 insertions(+), 36 deletions(-)
diff --git a/psplash-drm.c b/psplash-drm.c
index 5e56286..fcb7507 100644
--- a/psplash-drm.c
+++ b/psplash-drm.c
@@ -29,6 +29,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -41,10 +42,12 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
+struct modeset_buf;
struct modeset_dev;
static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
struct modeset_dev *dev);
-static int modeset_create_fb(int fd, struct modeset_dev *dev);
+static int modeset_create_fb(int fd, struct modeset_buf *buf);
+static void modeset_destroy_fb(int fd, struct modeset_buf *buf);
static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn,
struct modeset_dev *dev);
static int modeset_open(int *out, const char *node);
@@ -144,18 +147,45 @@ static int modeset_open(int *out, const char *node)
* }
*/
-struct modeset_dev {
- struct modeset_dev *next;
+/*
+ * Previously, we used the modeset_dev objects to hold buffer informations, too.
+ * Technically, we could have split them but avoided this to make the
+ * example simpler.
+ * However, in this example we need 2 buffers. One back buffer and one front
+ * buffer. So we introduce a new structure modeset_buf which contains everything
+ * related to a single buffer. Each device now gets an array of two of these
+ * buffers.
+ * Each buffer consists of width, height, stride, size, handle, map and fb-id.
+ * They have the same meaning as before.
+ *
+ * Each device also gets a new integer field: front_buf. This field contains the
+ * index of the buffer that is currently used as front buffer / scanout buffer.
+ * In our example it can be 0 or 1. We flip it by using XOR:
+ * dev->front_buf ^= dev->front_buf
+ *
+ * Everything else stays the same.
+ */
+struct modeset_buf {
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t size;
uint32_t handle;
void *map;
+ uint32_t fb;
+};
+
+struct modeset_dev {
+ struct modeset_dev *next;
+
+ uint32_t width;
+ uint32_t height;
+
+ unsigned int front_buf;
+ struct modeset_buf bufs[2];
drmModeModeInfo mode;
- uint32_t fb;
uint32_t conn;
uint32_t crtc;
drmModeCrtc *saved_crtc;
@@ -292,10 +322,15 @@ static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn,
return -EFAULT;
}
- /* copy the mode information into our device structure */
+ /* copy the mode information into our device structure and into both
+ * buffers */
memcpy(&dev->mode, &conn->modes[0], sizeof(dev->mode));
dev->width = conn->modes[0].hdisplay;
dev->height = conn->modes[0].vdisplay;
+ dev->bufs[0].width = dev->width;
+ dev->bufs[0].height = dev->height;
+ dev->bufs[1].width = dev->width;
+ dev->bufs[1].height = dev->height;
fprintf(stderr, "mode for connector %u is %ux%u\n",
conn->connector_id, dev->width, dev->height);
@@ -307,14 +342,30 @@ static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn,
return ret;
}
- /* create a framebuffer for this CRTC */
- ret = modeset_create_fb(fd, dev);
+ /* create framebuffer #1 for this CRTC */
+ ret = modeset_create_fb(fd, &dev->bufs[0]);
if (ret) {
fprintf(stderr, "cannot create framebuffer for connector %u\n",
conn->connector_id);
return ret;
}
+ /* create framebuffer #2 for this CRTC */
+ ret = modeset_create_fb(fd, &dev->bufs[1]);
+ if (ret) {
+ fprintf(stderr, "cannot create framebuffer for connector %u\n",
+ conn->connector_id);
+ modeset_destroy_fb(fd, &dev->bufs[0]);
+ return ret;
+ }
+
+ if (dev->bufs[0].size != dev->bufs[1].size) {
+ fprintf(stderr, "front buffer size %" PRIu32 " does not match "
+ "back buffer size %" PRIu32 "\n",
+ dev->bufs[0].size, dev->bufs[1].size);
+ return -1;
+ }
+
return 0;
}
@@ -441,7 +492,7 @@ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
* memory directly via the dev->map memory map.
*/
-static int modeset_create_fb(int fd, struct modeset_dev *dev)
+static int modeset_create_fb(int fd, struct modeset_buf *buf)
{
struct drm_mode_create_dumb creq;
struct drm_mode_destroy_dumb dreq;
@@ -450,8 +501,8 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
/* create dumb buffer */
memset(&creq, 0, sizeof(creq));
- creq.width = dev->width;
- creq.height = dev->height;
+ creq.width = buf->width;
+ creq.height = buf->height;
creq.bpp = 32;
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
if (ret < 0) {
@@ -459,13 +510,13 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
errno);
return -errno;
}
- dev->stride = creq.pitch;
- dev->size = creq.size;
- dev->handle = creq.handle;
+ buf->stride = creq.pitch;
+ buf->size = creq.size;
+ buf->handle = creq.handle;
/* create framebuffer object for the dumb-buffer */
- ret = drmModeAddFB(fd, dev->width, dev->height, 24, 32, dev->stride,
- dev->handle, &dev->fb);
+ ret = drmModeAddFB(fd, buf->width, buf->height, 24, 32, buf->stride,
+ buf->handle, &buf->fb);
if (ret) {
fprintf(stderr, "cannot create framebuffer (%d): %m\n",
errno);
@@ -475,7 +526,7 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
/* prepare buffer for memory mapping */
memset(&mreq, 0, sizeof(mreq));
- mreq.handle = dev->handle;
+ mreq.handle = buf->handle;
ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
if (ret) {
fprintf(stderr, "cannot map dumb buffer (%d): %m\n",
@@ -485,9 +536,9 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
}
/* perform actual memory mapping */
- dev->map = mmap(0, dev->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf->map = mmap(0, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, mreq.offset);
- if (dev->map == MAP_FAILED) {
+ if (buf->map == MAP_FAILED) {
fprintf(stderr, "cannot mmap dumb buffer (%d): %m\n",
errno);
ret = -errno;
@@ -495,23 +546,73 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
}
/* clear the framebuffer to 0 */
- memset(dev->map, 0, dev->size);
+ memset(buf->map, 0, buf->size);
return 0;
err_fb:
- drmModeRmFB(fd, dev->fb);
+ drmModeRmFB(fd, buf->fb);
err_destroy:
memset(&dreq, 0, sizeof(dreq));
- dreq.handle = dev->handle;
+ dreq.handle = buf->handle;
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
return ret;
}
+/*
+ * modeset_destroy_fb() is a new function. It does exactly the reverse of
+ * modeset_create_fb() and destroys a single framebuffer. The modeset.c example
+ * used to do this directly in modeset_cleanup().
+ * We simply unmap the buffer, remove the drm-FB and destroy the memory buffer.
+ */
+
+static void modeset_destroy_fb(int fd, struct modeset_buf *buf)
+{
+ struct drm_mode_destroy_dumb dreq;
+
+ /* unmap buffer */
+ munmap(buf->map, buf->size);
+
+ /* delete framebuffer */
+ drmModeRmFB(fd, buf->fb);
+
+ /* delete dumb buffer */
+ memset(&dreq, 0, sizeof(dreq));
+ dreq.handle = buf->handle;
+ drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+}
+
static void psplash_drm_flip(PSplashCanvas *canvas, int sync)
{
- (void)canvas;
+ PSplashDRM *drm = canvas->priv;
+ struct modeset_buf *buf;
+ int ret;
+
(void)sync;
+
+ /* pick a back buffer */
+ buf = &modeset_list->bufs[modeset_list->front_buf ^ 1];
+
+ /* set back buffer as a front buffer */
+ ret = drmModeSetCrtc(drm->fd, modeset_list->crtc, buf->fb, 0, 0,
+ &modeset_list->conn, 1, &modeset_list->mode);
+ if (ret) {
+ fprintf(stderr, "cannot flip CRTC for connector %u (%d): %m\n",
+ modeset_list->conn, errno);
+ return;
+ }
+
+ /* update front buffer index */
+ modeset_list->front_buf ^= 1;
+
+ /* update back buffer pointer */
+ drm->canvas.data = modeset_list->bufs[modeset_list->front_buf ^ 1].map;
+
+ /* Sync new front to new back when requested */
+ if (sync)
+ memcpy(modeset_list->bufs[modeset_list->front_buf ^ 1].map,
+ modeset_list->bufs[modeset_list->front_buf].map,
+ modeset_list->bufs[0].size);
}
/*
@@ -555,6 +656,7 @@ PSplashDRM* psplash_drm_new(int angle, int dev_id)
int ret;
char card[] = "/dev/dri/card0";
struct modeset_dev *iter;
+ struct modeset_buf *buf;
if ((drm = malloc(sizeof(*drm))) == NULL) {
perror("malloc");
@@ -583,18 +685,28 @@ PSplashDRM* psplash_drm_new(int angle, int dev_id)
/* perform actual modesetting on each found connector+CRTC */
for (iter = modeset_list; iter; iter = iter->next) {
iter->saved_crtc = drmModeGetCrtc(drm->fd, iter->crtc);
- ret = drmModeSetCrtc(drm->fd, iter->crtc, iter->fb, 0, 0,
+ buf = &iter->bufs[iter->front_buf];
+ ret = drmModeSetCrtc(drm->fd, iter->crtc, buf->fb, 0, 0,
&iter->conn, 1, &iter->mode);
if (ret)
fprintf(stderr, "cannot set CRTC for connector %u (%d): %m\n",
iter->conn, errno);
}
- drm->canvas.data = modeset_list->map;
+ drm->canvas.data = modeset_list->bufs[modeset_list->front_buf ^ 1].map;
drm->canvas.width = modeset_list->width;
drm->canvas.height = modeset_list->height;
drm->canvas.bpp = 32;
- drm->canvas.stride = modeset_list->stride;
+
+ if (modeset_list->bufs[0].stride != modeset_list->bufs[1].stride) {
+ fprintf(stderr, "front buffer stride %" PRIu32 " does not match"
+ " back buffer stride %" PRIu32 "\n",
+ modeset_list->bufs[0].stride,
+ modeset_list->bufs[1].stride);
+ goto error;
+ }
+ drm->canvas.stride = modeset_list->bufs[0].stride;
+
drm->canvas.angle = angle;
drm->canvas.rgbmode = RGB888;
@@ -614,7 +726,6 @@ error:
void psplash_drm_destroy(PSplashDRM *drm)
{
struct modeset_dev *iter;
- struct drm_mode_destroy_dumb dreq;
if (!drm)
return;
@@ -635,16 +746,9 @@ void psplash_drm_destroy(PSplashDRM *drm)
&iter->saved_crtc->mode);
drmModeFreeCrtc(iter->saved_crtc);
- /* unmap buffer */
- munmap(iter->map, iter->size);
-
- /* delete framebuffer */
- drmModeRmFB(drm->fd, iter->fb);
-
- /* delete dumb buffer */
- memset(&dreq, 0, sizeof(dreq));
- dreq.handle = iter->handle;
- drmIoctl(drm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ /* destroy framebuffers */
+ modeset_destroy_fb(drm->fd, &iter->bufs[1]);
+ modeset_destroy_fb(drm->fd, &iter->bufs[0]);
/* free allocated memory */
free(iter);
--
2.30.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [yocto] [psplash][RFC PATCH 00/14] Implement DRM backend
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
` (13 preceding siblings ...)
2022-04-25 7:59 ` [psplash][RFC PATCH 14/14] psplash-drm.c: Implement double buffering Vasyl Vavrychuk
@ 2022-04-25 8:24 ` Alexander Kanavin
2022-04-28 13:54 ` Vasyl Vavrychuk
14 siblings, 1 reply; 18+ messages in thread
From: Alexander Kanavin @ 2022-04-25 8:24 UTC (permalink / raw)
To: Vasyl Vavrychuk; +Cc: Yocto-mailing-list
Hello Vasyl,
can you explain how this was tested? Is it possible to automate with
qemu targets?
Alex
On Mon, 25 Apr 2022 at 10:00, Vasyl Vavrychuk
<Vasyl.Vavrychuk@opensynergy.com> wrote:
>
> It is needed in case display does not support FB.
>
> The missing part is drawing splash screen over all connected displays. I think
> there should be loop somewhere for this, but I am not sure which level is the
> best to put it.
>
> https://github.com/r1mikey/psplash-drm/blob/drm/implement-drm/psplash-draw.c has
> psplash_draw_initial(_one), psplash_draw_msg(_one) and
> psplash_draw_progress(_one) implementing loop over scanouts. I am think about
> doing the same.
>
> Vasyl Vavrychuk (14):
> Trim trailing spaces
> Fix 'unused-result' warnings
> Remove unused save_termios
> Remove 'psplash-fb.h' from 'psplash.h'
> Extract plot pixel from psplash-fb
> Extract draw rect/image from psplash-fb
> Extract draw font from psplash-fb
> psplash.c: Make psplash_draw_{msg,progress} independent of FB
> Rework flip as function pointer
> Import drm-howto modeset.c as psplash-drm.c
> Implement drm backend
> Reverse modeset_list
> psplash-drm.c: Allocate resources only for the first connector
> psplash-drm.c: Implement double buffering
>
> Makefile.am | 15 +-
> configure.ac | 9 +
> psplash-console.c | 34 +-
> psplash-console.h | 8 +-
> psplash-draw.c | 295 +++++++++++++++++
> psplash-draw.h | 81 +++++
> psplash-drm.c | 787 ++++++++++++++++++++++++++++++++++++++++++++++
> psplash-drm.h | 17 +
> psplash-fb.c | 371 +++-------------------
> psplash-fb.h | 74 +----
> psplash-systemd.c | 36 ++-
> psplash-write.c | 37 ++-
> psplash.c | 186 ++++++-----
> psplash.h | 7 +-
> 14 files changed, 1446 insertions(+), 511 deletions(-)
> create mode 100644 psplash-draw.c
> create mode 100644 psplash-draw.h
> create mode 100644 psplash-drm.c
> create mode 100644 psplash-drm.h
>
> --
> 2.30.2
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#56871): https://lists.yoctoproject.org/g/yocto/message/56871
> Mute This Topic: https://lists.yoctoproject.org/mt/90680297/1686489
> Group Owner: yocto+owner@lists.yoctoproject.org
> Unsubscribe: https://lists.yoctoproject.org/g/yocto/unsub [alex.kanavin@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [yocto] [psplash][RFC PATCH 00/14] Implement DRM backend
2022-04-25 8:24 ` [yocto] [psplash][RFC PATCH 00/14] Implement DRM backend Alexander Kanavin
@ 2022-04-28 13:54 ` Vasyl Vavrychuk
2022-04-28 14:57 ` Alexander Kanavin
0 siblings, 1 reply; 18+ messages in thread
From: Vasyl Vavrychuk @ 2022-04-28 13:54 UTC (permalink / raw)
To: Alexander Kanavin; +Cc: Yocto-mailing-list
Hi, Alex,
Thanks for feedback.
> can you explain how this was tested?
In "Implement drm backend" commit I added "--drm" switch to use DRM/KMS
instead of FB in psplash. I use this switch to test by changes, I run
them without this switch to check that FB keeps working too.
Before weston starts I do
echo QUIT > /run/psplash_fifo
to stop psplash.
I did not tried personally but it should work under QEMU too.
> Is it possible to automate with qemu targets?
Depends if QEMU/yocto test automation support screenshots.
Unfortunately, I don't have expirience with it.
> Alex
>
> On Mon, 25 Apr 2022 at 10:00, Vasyl Vavrychuk
> <Vasyl.Vavrychuk@opensynergy.com> wrote:
>>
>> It is needed in case display does not support FB.
>>
>> The missing part is drawing splash screen over all connected displays. I think
>> there should be loop somewhere for this, but I am not sure which level is the
>> best to put it.
>>
>> https://github.com/r1mikey/psplash-drm/blob/drm/implement-drm/psplash-draw.c has
>> psplash_draw_initial(_one), psplash_draw_msg(_one) and
>> psplash_draw_progress(_one) implementing loop over scanouts. I am think about
>> doing the same.
>>
>> Vasyl Vavrychuk (14):
>> Trim trailing spaces
>> Fix 'unused-result' warnings
>> Remove unused save_termios
>> Remove 'psplash-fb.h' from 'psplash.h'
>> Extract plot pixel from psplash-fb
>> Extract draw rect/image from psplash-fb
>> Extract draw font from psplash-fb
>> psplash.c: Make psplash_draw_{msg,progress} independent of FB
>> Rework flip as function pointer
>> Import drm-howto modeset.c as psplash-drm.c
>> Implement drm backend
>> Reverse modeset_list
>> psplash-drm.c: Allocate resources only for the first connector
>> psplash-drm.c: Implement double buffering
>>
>> Makefile.am | 15 +-
>> configure.ac | 9 +
>> psplash-console.c | 34 +-
>> psplash-console.h | 8 +-
>> psplash-draw.c | 295 +++++++++++++++++
>> psplash-draw.h | 81 +++++
>> psplash-drm.c | 787 ++++++++++++++++++++++++++++++++++++++++++++++
>> psplash-drm.h | 17 +
>> psplash-fb.c | 371 +++-------------------
>> psplash-fb.h | 74 +----
>> psplash-systemd.c | 36 ++-
>> psplash-write.c | 37 ++-
>> psplash.c | 186 ++++++-----
>> psplash.h | 7 +-
>> 14 files changed, 1446 insertions(+), 511 deletions(-)
>> create mode 100644 psplash-draw.c
>> create mode 100644 psplash-draw.h
>> create mode 100644 psplash-drm.c
>> create mode 100644 psplash-drm.h
>>
>> --
>> 2.30.2
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [yocto] [psplash][RFC PATCH 00/14] Implement DRM backend
2022-04-28 13:54 ` Vasyl Vavrychuk
@ 2022-04-28 14:57 ` Alexander Kanavin
0 siblings, 0 replies; 18+ messages in thread
From: Alexander Kanavin @ 2022-04-28 14:57 UTC (permalink / raw)
To: Vasyl Vavrychuk; +Cc: Yocto-mailing-list
On Thu, 28 Apr 2022 at 15:54, Vasyl Vavrychuk
<vasyl.vavrychuk@opensynergy.com> wrote:
> I did not tried personally but it should work under QEMU too.
>
> > Is it possible to automate with qemu targets?
>
> Depends if QEMU/yocto test automation support screenshots.
> Unfortunately, I don't have expirience with it.
We do need to find some way to test this code in our CI system: I
would recommend the following:
- make it possible to switch psplash recipe between drm and fb backends
- use drm by default
- find a way to check at runtime that the code didn't crash or error
out: perhaps checking logs for some kind of success message would be
good
- investigate qemu and particularly qmp protocol for ability to take screenshots
I can help with all of these if you have specific problems.
Alex
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2022-04-28 14:57 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-25 7:59 [psplash][RFC PATCH 00/14] Implement DRM backend Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 01/14] Trim trailing spaces Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 02/14] Fix 'unused-result' warnings Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 03/14] Remove unused save_termios Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 04/14] Remove 'psplash-fb.h' from 'psplash.h' Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 05/14] Extract plot pixel from psplash-fb Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 06/14] Extract draw rect/image " Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 07/14] Extract draw font " Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 08/14] psplash.c: Make psplash_draw_{msg,progress} independent of FB Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 09/14] Rework flip as function pointer Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 10/14] Import drm-howto modeset.c as psplash-drm.c Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 11/14] Implement drm backend Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 12/14] Reverse modeset_list Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 13/14] psplash-drm.c: Allocate resources only for the first connector Vasyl Vavrychuk
2022-04-25 7:59 ` [psplash][RFC PATCH 14/14] psplash-drm.c: Implement double buffering Vasyl Vavrychuk
2022-04-25 8:24 ` [yocto] [psplash][RFC PATCH 00/14] Implement DRM backend Alexander Kanavin
2022-04-28 13:54 ` Vasyl Vavrychuk
2022-04-28 14:57 ` Alexander Kanavin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.