blob: ddf24518cadceaf3c30888e91f13014ca5dac672 [file] [log] [blame]
/*
* 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);
}