started fbdev port
[retrobench] / src / fbdev / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <signal.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/time.h>
9 #include <sys/mman.h>
10 #include "rbench.h"
11 #include "util.h"
12
13
14 static int init_fbdev(int xsz, int ysz, int bpp);
15 static void close_fbdev(void);
16 static int parse_args(int argc, char **argv);
17
18 static int fbfd = -1;
19 static int fbsz;
20 static void *fbmem;
21
22
23 int main(int argc, char **argv)
24 {
25         int num_frames = 0;
26         struct timeval tv, tv0;
27
28         read_config("rbench.cfg");
29
30         if(parse_args(argc, argv) == -1) {
31                 return 1;
32         }
33
34         if(init_fbdev(opt.width, opt.height, opt.bpp) == -1) {
35                 return 1;
36         }
37
38         fb_width = opt.width;
39         fb_height = opt.height;
40         fb_bpp = opt.bpp;
41         fb_pitch = opt.width * opt.bpp / 8;
42
43         if(!(framebuf = malloc(fb_pitch * fb_height))) {
44                 fprintf(stderr, "failed to allocate %dx%d (%d bpp) framebuffer\n",
45                                 fb_width, fb_height, fb_bpp);
46                 return 1;
47         }
48         /*
49         fb_rmask = ximg->red_mask;
50         fb_gmask = ximg->green_mask;
51         fb_bmask = ximg->blue_mask;
52         fb_rshift = mask_to_shift(fb_rmask);
53         fb_gshift = mask_to_shift(fb_gmask);
54         fb_bshift = mask_to_shift(fb_bmask);
55         */
56
57         if(init() == -1) {
58                 goto end;
59         }
60
61         /* TODO: set terminal raw and disable cursor */
62
63         gettimeofday(&tv0, 0);
64
65         for(;;) {
66                 /* TODO read input */
67
68                 gettimeofday(&tv, 0);
69                 time_msec = (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
70                 num_frames++;
71
72                 redraw();
73
74                 /* TODO copy to fb */
75         }
76
77 end:
78         cleanup();
79         close_fbdev();
80
81         if(num_frames) {
82                 printf("avg framerate: %.1f fps\n", (10000 * num_frames / time_msec) / 10.0f);
83         }
84         return 0;
85 }
86
87 int init_fbdev(int xsz, int ysz, int bpp)
88 {
89         if((fbfd = open("/dev/fb0", O_RDWR)) == -1) {
90                 perror("failed to open framebuffer device");
91                 return -1;
92         }
93
94         /* TODO modeset ioctl */
95
96         fbsz = xsz * ysz * bpp / 8;     /* XXX */
97
98         if((fbmem = mmap(0, fbsz, PROT_WRITE, MAP_SHARED, fbfd, 0)) == (void*)-1) {
99                 perror("failed to map framebuffer");
100                 return -1;
101         }
102
103         return 0;
104 }
105
106 void close_fbdev(void)
107 {
108         if(fbmem) {
109                 munmap(fbmem, fbsz);
110         }
111         if(fbfd >= 0) {
112                 close(fbfd);
113         }
114 }
115
116 static const char *usage_str =
117         "Usage: %s [options]\n"
118         "Options:\n"
119         "  -s <WxH>: resolution\n"
120         "  -b <bpp>: color depth\n"
121         "  -h: print usage and exit\n";
122
123 static int parse_args(int argc, char **argv)
124 {
125         int i;
126
127         for(i=1; i<argc; i++) {
128                 if(argv[i][0] == '-') {
129                         if(argv[i][2]) {
130                                 goto inval_arg;
131                         }
132                         switch(argv[i][1]) {
133                         case 's':
134                                 if(!argv[++i] || sscanf(argv[i], "%dx%d", &opt.width, &opt.height) != 2) {
135                                         fprintf(stderr, "-s must be followed by WxH\n");
136                                         return -1;
137                                 }
138                                 break;
139
140                         case 'b':
141                                 if(!argv[++i] || !(opt.bpp = atoi(argv[i]))) {
142                                         fprintf(stderr, "-b must be followed by the color depth\n");
143                                         return -1;
144                                 }
145                                 break;
146
147                         case 'h':
148                                 printf(usage_str, argv[0]);
149                                 exit(0);
150
151                         default:
152                                 goto inval_arg;
153                         }
154                 } else {
155 inval_arg:      fprintf(stderr, "invalid argument: %s\n", argv[i]);
156                         return -1;
157                 }
158         }
159         return 0;
160 }