diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kern-linux.c | 91 | ||||
-rw-r--r-- | src/kern.h | 5 | ||||
-rw-r--r-- | src/png.c | 1 | ||||
-rw-r--r-- | src/scrotty.c | 31 |
4 files changed, 72 insertions, 56 deletions
diff --git a/src/kern-linux.c b/src/kern-linux.c index e6ca1a2..071d3fc 100644 --- a/src/kern-linux.c +++ b/src/kern-linux.c @@ -20,6 +20,9 @@ #include "kern.h" #include "png.h" +#include <sys/ioctl.h> +#include <linux/fb.h> + /** @@ -27,6 +30,14 @@ */ const int alt_fbpath_limit = 2; +struct data +{ + unsigned long start; + unsigned long end; + long hblank; + unsigned long position; +}; + /** @@ -67,53 +78,49 @@ get_fbpath (int altpath, int fbno) * Get the dimensions of a framebuffer. * * @param fbno The number of the framebuffer. - * @param fbpath The path to the framebuffer device.. + * @param fbfd File descriptor for framebuffer device. * @param width Output parameter for the width of the image. * @param height Output parameter for the height of the image. * @parma data Additional data to pass to `convert_fb_to_png`. * @return Zero on success, -1 on error. */ int -measure (int fbno, char *restrict fbpath, long *restrict width, - long *restrict height, void **restrict data) +measure (int fbno, int fbfd, long *restrict width, long *restrict height, void **restrict data) { - static char buf[sizeof (SYSDIR "/class/graphics/fb/virtual_size") + 3 * sizeof(int)]; - /* The string "/class/graphics/fb/virtual_size" is large enought for the call (*) "*/ - char *delim; - int sizefd = -1; - ssize_t got; - int saved_errno; + static struct data d; + struct fb_fix_screeninfo fixinfo; + struct fb_var_screeninfo varinfo; + unsigned long int linelength; - /* Open the file with the framebuffer's dimensions. */ - sprintf (buf, "%s/class/graphics/fb%i/virtual_size", SYSDIR, fbno); - sizefd = open (buf, O_RDONLY); - if (sizefd == -1) - FILE_FAILURE (buf); + if (ioctl (fbfd, FBIOGET_FSCREENINFO, &fixinfo)) + goto fail; - /* Get the dimensions of the framebuffer. */ - got = read (sizefd, buf, sizeof (buf) / sizeof (char) - 1); /* (*) */ - if (got < 0) + if (ioctl (fbfd, FBIOGET_VSCREENINFO, &varinfo)) goto fail; - close (sizefd); - /* The read content is formated as `%{width},%{height}\n`, - convert it to `%{width}\0%{height}\0` and parse it. */ - buf[got] = '\0'; - delim = strchr (buf, ','); - *delim++ = '\0'; - *width = atol (buf); - *height = atol (delim); + *width = varinfo.xres; + *height = varinfo.yres; - return 0; + if (varinfo.bits_per_pixel & 7) + { + fprintf(stderr, _("%s: Unsupported framebuffer configurations: " + "pixels are not encoded in whole bytes.\n"), execname); + exit(1); + } + linelength = fixinfo.line_length / (varinfo.bits_per_pixel / 8); + d.start = varinfo.yoffset * linelength; + d.start += varinfo.xoffset; + d.end = d.start + linelength * varinfo.yres; + d.hblank = linelength - *width; + d.position = 0; + + /* TODO depth support */ + + *data = &d; + return 0; fail: - saved_errno = errno; - if (sizefd >= 0) - close (sizefd); - errno = saved_errno; return -1; - - (void) fbpath; } @@ -133,16 +140,19 @@ measure (int fbno, char *restrict fbpath, long *restrict width, * @param data Data from `measure`. * @return Zero on success, -1 on error. */ -int convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char *restrict buf, - size_t n, long width3, size_t *restrict adjustment, long *restrict state, - void *restrict data) +int +convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char *restrict buf, size_t n, + long width3, size_t *restrict adjustment, long *restrict state, void *restrict data) { const uint32_t *restrict pixel; int r, g, b; size_t off; long x3 = *state; + struct data d = *(struct data *)data; + unsigned long pos = d.position; + long lineend = width3 + d.hblank * 3; - for (off = 0; off < n; off += 4) + for (off = 0; off < n; off += 4, pos++) { /* A pixel in the framebuffer is formatted as `%{blue}%{green}%{red}%{x}` in big-endian binary, or `%{x}%{red}%{green}%{blue}` in little-endian binary. */ @@ -151,9 +161,13 @@ int convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char g = (*pixel >> 8) & 255; b = (*pixel >> 0) & 255; - SAVE_PNG_PIXEL (pixbuf, x3, r, g, b); + if ((pos < d.start) || (pos >= d.end)) + continue; + + if (x3 < width3) + SAVE_PNG_PIXEL (pixbuf, x3, r, g, b); x3 += 3; - if (x3 == width3) + if (x3 == lineend) { SAVE_PNG_ROW (pngbuf, pixbuf); x3 = 0; @@ -162,6 +176,7 @@ int convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char *adjustment = (off != n ? 4 : 0); *state = x3; + ((struct data *)data)->position = pos; return 0; } @@ -55,14 +55,13 @@ char *get_fbpath (int altpath, int fbno); * Get the dimensions of a framebuffer. * * @param fbno The number of the framebuffer. - * @param fbpath The path to the framebuffer device.. + * @param fbfd File descriptor for framebuffer device. * @param width Output parameter for the width of the image. * @param height Output parameter for the height of the image. * @parma data Additional data to pass to `convert_fb_to_png`. * @return Zero on success, -1 on error. */ -int measure (int fbno, char *restrict fbpath, long *restrict width, - long *restrict height, void **restrict data); +int measure (int fbno, int fbfd, long *restrict width, long *restrict height, void **restrict data); /** * Convert read data from a framebuffer to PNG pixel data. @@ -71,6 +71,7 @@ save_png (int fbfd, long width, long height, int imgfd, void *restrict data) goto fail; /* Initialise PNG write, and write head. */ + errno = 0; if (setjmp (png_jmpbuf(pngbuf))) /* Failing libpng calls jump here. */ goto fail; png_init_io (pngbuf, file); diff --git a/src/scrotty.c b/src/scrotty.c index bce7036..5ab39fe 100644 --- a/src/scrotty.c +++ b/src/scrotty.c @@ -66,7 +66,7 @@ static int try_alt_fbpath = 0; /** * Create an image of a framebuffer. * - * @param fbname The framebuffer device. + * @param fbfd File descriptor for framebuffer device. * @param imgname The pathname of the output image, `NULL` for piping. * @param width The width of the image. * @param height The height of the image. @@ -74,10 +74,10 @@ static int try_alt_fbpath = 0; * @return Zero on success, -1 on error. */ static int -save (const char *fbpath, const char *imgpath, long width, +save (int fbfd, const char *imgpath, long width, long height, void *restrict data) { - int imgfd = STDOUT_FILENO, fbfd = -1, piping = (imgpath == NULL); + int imgfd = STDOUT_FILENO, piping = (imgpath == NULL); int saved_errno; /* Open output file. */ @@ -89,11 +89,6 @@ save (const char *fbpath, const char *imgpath, long width, FILE_FAILURE (imgpath); } - /* Open the framebuffer device for reading. */ - fbfd = open (fbpath, O_RDONLY); - if (fbfd == -1) - FILE_FAILURE (fbpath); - /* Save image. */ if (save_png (fbfd, width, height, imgfd, data) < 0) goto fail; @@ -105,8 +100,6 @@ save (const char *fbpath, const char *imgpath, long width, fail: saved_errno = errno; - if (fbfd >= 0) - close (fbfd); if ((imgfd >= 0) && !piping) close (imgfd); errno = saved_errno; @@ -198,6 +191,7 @@ save_fb (int fbno, const char *filepattern, const char *execpattern) char *execargs = NULL; long width, height; void *data = NULL; + int fbfd = -1; int rc = 0, saved_errno = 0; /* Get pathname for framebuffer, and stop if we have read all existing ones. */ @@ -205,8 +199,13 @@ save_fb (int fbno, const char *filepattern, const char *execpattern) if (access (fbpath, F_OK)) return 1; + /* Open the framebuffer device for reading. */ + fbfd = open (fbpath, O_RDONLY); + if (fbfd == -1) + FILE_FAILURE (fbpath); + /* Get the size of the framebuffer. */ - if (measure (fbno, fbpath, &width, &height, &data) < 0) + if (measure (fbno, fbfd, &width, &height, &data) < 0) goto fail; /* Get output pathname. */ @@ -218,7 +217,7 @@ save_fb (int fbno, const char *filepattern, const char *execpattern) } /* Take a screenshot of the current framebuffer. */ - if (save (fbpath, imgpath, width, height, data) < 0) + if (save (fbfd, imgpath, width, height, data) < 0) goto fail; if (imgpath) fprintf (stderr, _("Saved framebuffer %i to %s.\n"), fbno, imgpath); @@ -242,6 +241,8 @@ save_fb (int fbno, const char *filepattern, const char *execpattern) saved_errno = errno; rc = -1; done: + if (fbfd >= 0) + close (fbfd); free (execargs); free (imgpath); return errno = saved_errno, rc; @@ -407,11 +408,11 @@ main (int argc, char *argv[]) return 0; fail: - if (failure_file == NULL) - perror (execname); - else + if (failure_file != NULL) fprintf (stderr, _("%s: %s: %s\n"), execname, strerror (errno), failure_file); + else if (errno) + perror (execname); return 1; no_fb: |