blob: 1123b053b3ee1086a26c95b1f7633c7bada04a24 [file] [log] [blame]
Talustus3019a912013-04-06 11:50:07 +02001/**
2 * fb2png Save screenshot into .png.
3 *
4 * Copyright (C) 2012 Kyan <kyan.ql.he@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
Matt Mower908a2772017-01-11 15:31:00 -060020#include <errno.h>
21#include <fcntl.h>
22#include <linux/fb.h>
Talustus3019a912013-04-06 11:50:07 +020023#include <stdio.h>
24#include <stdlib.h>
Talustus3019a912013-04-06 11:50:07 +020025#include <sys/ioctl.h>
26#include <sys/mman.h>
Matt Mower908a2772017-01-11 15:31:00 -060027#include <sys/types.h>
28#include <unistd.h>
Talustus3019a912013-04-06 11:50:07 +020029
30#include "log.h"
31#include "fb2png.h"
32#include "fb.h"
33
34/**
35 * Get the {@code struct fb} from device's framebuffer.
36 * Return
37 * 0 for success.
38 */
39int get_device_fb(const char* path, struct fb *fb)
40{
41 int fd;
42 int bytespp;
43 int offset;
44 char *x;
45 struct fb_var_screeninfo vinfo;
46
47 fd = open(path, O_RDONLY);
48 if (fd < 0) return -1;
49
50 if(ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
51 D("ioctl failed, %s\n", strerror(errno));
52 return -1;
53 }
54
55 bytespp = vinfo.bits_per_pixel / 8;
56
57 fb->bpp = vinfo.bits_per_pixel;
58 fb->size = vinfo.xres * vinfo.yres * bytespp;
59 fb->width = vinfo.xres;
60 fb->height = vinfo.yres;
61 fb->red_offset = vinfo.red.offset;
62 fb->red_length = vinfo.red.length;
63 fb->green_offset = vinfo.green.offset;
64 fb->green_length = vinfo.green.length;
65 fb->blue_offset = vinfo.blue.offset;
66 fb->blue_length = vinfo.blue.length;
67 fb->alpha_offset = vinfo.transp.offset;
68 fb->alpha_length = vinfo.transp.length;
69
70#ifdef ANDROID
71 /* HACK: for several of 3d cores a specific alignment
72 * is required so the start of the fb may not be an integer number of lines
73 * from the base. As a result we are storing the additional offset in
74 * xoffset. This is not the correct usage for xoffset, it should be added
75 * to each line, not just once at the beginning */
76
77 offset = vinfo.xoffset * bytespp;
78
79 /* Android use double-buffer, capture 2nd */
80 offset += vinfo.xres * vinfo.yoffset * bytespp;
81#else
82 offset = 0;
83#endif
84
85 x = malloc(fb->size);
86 if (!x) return -1;
87
88 lseek(fd, offset, SEEK_SET);
89
90 if (read(fd, x ,fb->size) != fb->size) goto oops;
91
92 fb->data = x;
93 close(fd);
94
95 return 0;
96
97oops:
98 close(fd);
99 free(x);
100 return -1;
101}
102
103int fb2png(const char *path)
104{
105 struct fb fb;
106 int ret;
107
108#ifdef ANDROID
109 ret = get_device_fb("/dev/graphics/fb0", &fb);
110#else
111 ret = get_device_fb("/dev/fb0", &fb);
112#endif
113
114 if (ret) {
115 D("Failed to read framebuffer.");
116 return -1;
117 }
118
119 fb_dump(&fb);
120
121 return fb_save_png(&fb, path);
122}
123