From: Geert Uytterhoeven <geert@linux-m68k.org>
To: linux-fbdev@vger.kernel.org
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Subject: [PATCH fbtest 01/17] Add support for exporting virtual test images
Date: Sun, 15 Dec 2024 11:44:52 +0100 [thread overview]
Message-ID: <20241215104508.191237-2-geert@linux-m68k.org> (raw)
In-Reply-To: <20241215104508.191237-1-geert@linux-m68k.org>
Add support for operating on a virtual buffer in RAM instead of on a
real frame buffer device, and exporting the result as a PPM image.
The size of the virtual buffer is configurable, but for now the format
is fixed to Truecolor 8:8:8:0.
This is useful for e.g. testing drawing algorithms on screen sizes not
supported by your hardware.
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
export.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++
fb.c | 9 +++
include/export.h | 14 ++++
include/util.h | 1 +
main.c | 33 ++++++---
tests.c | 3 +
util.c | 6 ++
7 files changed, 233 insertions(+), 9 deletions(-)
create mode 100644 export.c
create mode 100644 include/export.h
diff --git a/export.c b/export.c
new file mode 100644
index 0000000000000000..ddf24518cadceaf3
--- /dev/null
+++ b/export.c
@@ -0,0 +1,176 @@
+
+/*
+ * Virtual Frame Buffer Export
+ *
+ * (C) Copyright 2024 Glider bv
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+#include "export.h"
+#include "fb.h"
+#include "util.h"
+
+
+static const char *export_prefix;
+static unsigned int export_xres = DEFAULT_EXPORT_XRES;
+static unsigned int export_yres = DEFAULT_EXPORT_YRES;
+
+static void export_setup(void)
+{
+ const char *param = Opt_Export;
+ char *end;
+
+ /* Prefix */
+ end = strchr(param, ',');
+ if (end)
+ *end++ = '\0';
+
+ export_prefix = param;
+ Debug("export_prefix = %s\n", export_prefix);
+
+ /* Optional horizontal resolution */
+ param = end;
+ if (!param)
+ return;
+
+ end = strchr(param, ',');
+ if (end)
+ *end++ = '\0';
+
+ export_xres = atoi(param);
+ Debug("export_xres = %u\n", export_xres);
+
+ /* Optional vertical resolution */
+ param = end;
+ if (!param)
+ return;
+
+ end = strchr(param, ',');
+ if (end)
+ *end++ = '\0';
+
+ export_yres = atoi(param);
+ Debug("export_yres = %u\n", export_yres);
+}
+
+void export_init(void)
+{
+ export_setup();
+
+ fb_var.xres = export_xres;
+ fb_var.yres = export_yres;
+ fb_var.xres_virtual = export_xres;
+ fb_var.yres_virtual = export_yres;
+ fb_var.xoffset = 0;
+ fb_var.yoffset = 0;
+ fb_var.bits_per_pixel = 32;
+ fb_var.grayscale = 0;
+ fb_var.red.offset = 16;
+ fb_var.red.length = 8;
+ fb_var.red.msb_right = 0;
+ fb_var.green.offset = 8;
+ fb_var.green.length = 8;
+ fb_var.green.msb_right = 0;
+ fb_var.blue.offset = 0;
+ fb_var.blue.length = 8;
+ fb_var.blue.msb_right = 0;
+ fb_var.transp.offset = 0;
+ fb_var.transp.length = 0;
+ fb_var.transp.msb_right = 0;
+ fb_var.nonstd = 0;
+ fb_var.activate = 0;
+ fb_var.height = fb_var.xres / 4;
+ fb_var.width = fb_var.yres / 4;
+ fb_var.accel_flags = 0;
+ fb_var.pixclock = 0;
+ fb_var.left_margin = 0;
+ fb_var.right_margin = 0;
+ fb_var.upper_margin = 0;
+ fb_var.lower_margin = 0;
+ fb_var.hsync_len = 0;
+ fb_var.vsync_len = 0;
+ fb_var.sync = 0;
+ fb_var.vmode = FB_VMODE_NONINTERLACED;
+ fb_var.rotate = 0;
+ fb_var.colorspace = 0;
+ fb_var.reserved[0] = 0;
+ fb_var.reserved[1] = 0;
+ fb_var.reserved[2] = 0;
+ fb_var.reserved[3] = 0;
+
+ strcpy(fb_fix.id, "fbtest");
+ fb_fix.smem_start = 0;
+ fb_fix.smem_len = fb_var.xres * fb_var.yres * 4;
+ fb_fix.type = FB_TYPE_PACKED_PIXELS;
+ fb_fix.type_aux = 0;
+ fb_fix.visual = FB_VISUAL_TRUECOLOR;
+ fb_fix.xpanstep = 0;
+ fb_fix.ypanstep = 0;
+ fb_fix.ywrapstep = 0;
+ fb_fix.line_length = fb_var.xres * 4;
+ fb_fix.mmio_start = 0;
+ fb_fix.mmio_len = 0;
+ fb_fix.accel = FB_ACCEL_NONE;
+ fb_fix.capabilities = 0;
+ fb_fix.reserved[0] = 0;
+ fb_fix.reserved[1] = 0;
+
+ fb = malloc(fb_fix.smem_len);
+ if (!fb)
+ Fatal("malloc %u: %s\n", fb_fix.smem_len, strerror(errno));
+}
+
+void export_fb(const char *name)
+{
+ unsigned int x, y;
+ u32 *src, pixel;
+ char *filename;
+ u8 *line, *dst;
+ FILE *stream;
+ int res;
+
+ res = asprintf(&filename, "%s%s.ppm", export_prefix, name);
+ if (res < 0)
+ Fatal("asprintf: %s\n", strerror(errno));
+
+ line = malloc(fb_var.xres * 3);
+ if (!line)
+ Fatal("malloc %u: %s\n", fb_var.xres * 3, strerror(errno));
+
+ Debug("Exporting to %s\n", filename);
+ stream = fopen(filename, "w");
+ if (!stream)
+ Fatal("fopen %s: %s\n", filename, strerror(errno));
+
+ fputs("P6\n", stream);
+ fprintf(stream, "%u %u 255\n", fb_var.xres, fb_var.yres);
+
+ src = (u32 *)fb;
+ for (y = 0; y < fb_var.yres; y++) {
+ dst = line;
+ for (x = 0; x < fb_var.xres; x++) {
+ pixel = *src++;
+ *dst++ = (pixel >> fb_var.red.offset) & 0xff;
+ *dst++ = (pixel >> fb_var.green.offset) & 0xff;
+ *dst++ = (pixel >> fb_var.blue.offset) & 0xff;
+ }
+ res = fwrite(line, 3, fb_var.xres, stream);
+ if (res < fb_var.xres)
+ Fatal("fwrite: %s\n", strerror(errno));
+ }
+
+ fclose(stream);
+ free(line);
+ free(filename);
+}
diff --git a/fb.c b/fb.c
index c22bdece6dfeb654..ab351d15c82e09d9 100644
--- a/fb.c
+++ b/fb.c
@@ -20,6 +20,7 @@
#include <unistd.h>
#include "types.h"
+#include "export.h"
#include "fb.h"
#include "util.h"
#include "colormap.h"
@@ -429,6 +430,11 @@ static void var_fix_validate(void)
void fb_init(void)
{
+ if (Opt_Export) {
+ export_init();
+ return;
+ }
+
Debug("fb_init()\n");
fb_open();
fb_get_var();
@@ -490,6 +496,9 @@ void fb_init(void)
void fb_cleanup(void)
{
+ if (Opt_Export)
+ return;
+
Debug("fb_cleanup()\n");
if (saved_fb)
fb_restore();
diff --git a/include/export.h b/include/export.h
new file mode 100644
index 0000000000000000..e3ef18b7b8e3ec14
--- /dev/null
+++ b/include/export.h
@@ -0,0 +1,14 @@
+
+/*
+ * (C) Copyright 2024 Glider bv
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#define DEFAULT_EXPORT_XRES 640
+#define DEFAULT_EXPORT_YRES 480
+
+extern void export_init(void);
+extern void export_fb(const char *name);
diff --git a/include/util.h b/include/util.h
index 64d810448d5779e4..5a6b5ab40d383d5a 100644
--- a/include/util.h
+++ b/include/util.h
@@ -103,6 +103,7 @@ extern double benchmark(void (*func)(unsigned long n, void *data), void *data);
* Command line options
*/
+extern const char *Opt_Export;
extern const char *Opt_Fbdev;
extern int Opt_Debug;
extern int Opt_List;
diff --git a/main.c b/main.c
index a13c80078543c7d1..9887fbd6936ecc1c 100644
--- a/main.c
+++ b/main.c
@@ -16,6 +16,7 @@
#include "types.h"
#include "util.h"
+#include "export.h"
#include "fb.h"
#include "drawops.h"
#include "visual.h"
@@ -28,6 +29,7 @@
const char *ProgramName;
const char *Opt_Fbdev = DEFAULT_FBDEV;
+const char *Opt_Export;
int Opt_Debug = 0;
int Opt_List = 0;
int Opt_Quiet = 0;
@@ -42,16 +44,21 @@ static void Usage(void) __attribute__ ((noreturn));
static void Usage(void)
{
- printf("%s: [options] [test ...]\n\n"
+ printf("%s: [options] [<test> ...]\n\n"
"Valid options are:\n"
- " -h, --help Display this usage information\n"
- " -f, --fbdev dev Specify frame buffer device (default: %s)\n"
- " -d, --debug Enable debug mode\n"
- " -l, --list List tests only, don't run them\n"
- " -q, --quiet Suppress messages\n"
- " -v, --verbose Enable verbose mode\n"
+ " -h, --help Display this usage information\n"
+ " -e, --export <prefix>[,<xres>[,<yres>]]\n"
+ " Do not use a frame buffer device, but operate on a\n"
+ " virtual buffer in RAM, and export the result as a PPM\n"
+ " image in <prefix><test>.ppm (default size: %ux%u)\n"
+ " -f, --fbdev <dev> Specify frame buffer device (default: %s)\n"
+ " -d, --debug Enable debug mode\n"
+ " -l, --list List tests only, don't run them\n"
+ " -q, --quiet Suppress messages\n"
+ " -v, --verbose Enable verbose mode\n"
"\n",
- ProgramName, DEFAULT_FBDEV);
+ ProgramName, DEFAULT_EXPORT_XRES, DEFAULT_EXPORT_YRES,
+ DEFAULT_FBDEV);
exit(1);
}
@@ -78,7 +85,15 @@ int main(int argc, char *argv[])
while (argc > 1 && argv[1][0] == '-') {
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
Usage();
- else if (!strcmp(argv[1], "-f") || !strcmp(argv[1], "--fbdev")) {
+ else if (!strcmp(argv[1], "-e") || !strcmp(argv[1], "--export")) {
+ if (argc <= 2)
+ Usage();
+ else {
+ Opt_Export = argv[2];
+ argv += 2;
+ argc -= 2;
+ }
+ } else if (!strcmp(argv[1], "-f") || !strcmp(argv[1], "--fbdev")) {
if (argc <= 2)
Usage();
else {
diff --git a/tests.c b/tests.c
index 6f6f818ac4ade8b3..c92236f869f41594 100644
--- a/tests.c
+++ b/tests.c
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <string.h>
+#include "export.h"
#include "types.h"
#include "fb.h"
#include "visual.h"
@@ -81,6 +82,8 @@ static void run_one_test(const struct test *test)
switch (res) {
case TEST_OK:
Message("%s: PASSED\n", test->name);
+ if (Opt_Export)
+ export_fb(test->name);
break;
case TEST_FAIL:
diff --git a/util.c b/util.c
index f199ace3501b0362..a946c12091f608f0 100644
--- a/util.c
+++ b/util.c
@@ -125,6 +125,9 @@ void Fatal(const char *fmt, ...)
void wait_for_key(int timeout)
{
+ if (Opt_Export)
+ return;
+
/* FIXME: no keypress handling yet */
sleep(2);
}
@@ -138,6 +141,9 @@ void wait_ms(int ms)
{
struct timespec req;
+ if (Opt_Export)
+ return;
+
req.tv_sec = ms/1000;
req.tv_nsec = (ms % 1000)*1000000;
nanosleep(&req, NULL);
--
2.34.1
next prev parent reply other threads:[~2024-12-15 10:45 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-15 10:44 [PATCH fbtest 00/17] Export feature and large ellipses support Geert Uytterhoeven
2024-12-15 10:44 ` Geert Uytterhoeven [this message]
2024-12-15 10:44 ` [PATCH fbtest 02/17] tests: Print test description in debug mode Geert Uytterhoeven
2024-12-15 10:44 ` [PATCH fbtest 03/17] Test002: Fix test description Geert Uytterhoeven
2024-12-15 10:44 ` [PATCH fbtest 04/17] drawops: Extract do_circle() Geert Uytterhoeven
2024-12-15 10:44 ` [PATCH fbtest 05/17] drawops: Use "y == 0" in draw_ellipse_points() Geert Uytterhoeven
2024-12-15 10:44 ` [PATCH fbtest 06/17] drawops: Remove always-false check in generic_fill_ellipse() Geert Uytterhoeven
2024-12-15 10:44 ` [PATCH fbtest 07/17] drawops: Refactor generic_draw_ellipse() Geert Uytterhoeven
2024-12-15 10:44 ` [PATCH fbtest 08/17] drawops: Return early in generic_{draw,fill}_ellipse() Geert Uytterhoeven
2024-12-15 10:45 ` [PATCH fbtest 09/17] drawops: Extract do_ellipse() Geert Uytterhoeven
2024-12-15 10:45 ` [PATCH fbtest 10/17] drawops: Make de in do_circle() unsigned Geert Uytterhoeven
2024-12-15 10:45 ` [PATCH fbtest 11/17] drawops: Make dT1 and dS1 in do_ellipse() unsigned Geert Uytterhoeven
2024-12-15 10:45 ` [PATCH fbtest 12/17] drawops: Fix crash when drawing large ellipses Geert Uytterhoeven
2024-12-15 15:08 ` Helge Deller
2024-12-18 16:29 ` Geert Uytterhoeven
2024-12-18 18:00 ` Helge Deller
2024-12-15 10:45 ` [PATCH fbtest 13/17] tests: Clear frame buffer before each test Geert Uytterhoeven
2024-12-15 10:45 ` [PATCH fbtest 14/17] Make variables that are never negative unsigned Geert Uytterhoeven
2024-12-15 10:45 ` [PATCH fbtest 15/17] test013: Fix off-by-one error in maximum circle calculation Geert Uytterhoeven
2024-12-15 10:45 ` [PATCH fbtest 16/17] visops: Mark fall-through switch case Geert Uytterhoeven
2024-12-15 10:45 ` [PATCH fbtest 17/17] util: Use __attribute__ Geert Uytterhoeven
2024-12-24 13:07 ` [PATCH fbtest 00/17] Export feature and large ellipses support Geert Uytterhoeven
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241215104508.191237-2-geert@linux-m68k.org \
--to=geert@linux-m68k.org \
--cc=linux-fbdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).