From c5bb70cf1235e4a2cc547c8fff0bff08ca2477d1 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 19 May 2021 06:01:40 +0300 Subject: [PATCH] fbdev backend works --- src/fbdev/fbevents.c | 87 ++++++++++++++++++++++++++++++++ src/fbdev/fbevents.h | 13 +++++ src/fbdev/fbgfx.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/fbdev/fbgfx.h | 21 ++++++++ src/fbdev/main.c | 84 +++++++++++++------------------ 5 files changed, 290 insertions(+), 49 deletions(-) create mode 100644 src/fbdev/fbevents.c create mode 100644 src/fbdev/fbevents.h create mode 100644 src/fbdev/fbgfx.c create mode 100644 src/fbdev/fbgfx.h diff --git a/src/fbdev/fbevents.c b/src/fbdev/fbevents.c new file mode 100644 index 0000000..ec0af45 --- /dev/null +++ b/src/fbdev/fbevents.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include "fbevents.h" + +static struct termios orig_state; +static int term_fd = -1; /* tty file descriptor */ + +static void (*keyb_func)(int, int, void*); +static void *keyb_cls; +static void (*mbutton_func)(int, int, int, int, void*); +static void *mbutton_cls; +static void (*mmotion_func)(int, int, void*); +static void *mmotion_cls; + + +int fbev_init(void) +{ + struct termios tstate; + + if((term_fd = open("/dev/tty", O_RDWR)) == -1) { + perror("failed to open tty"); + return -1; + } + fcntl(term_fd, F_SETFL, fcntl(term_fd, F_GETFL) | O_NONBLOCK); + + if(tcgetattr(term_fd, &tstate) == -1) { + perror("failed to retrieve tty attribs"); + close(term_fd); + return -1; + } + orig_state = tstate; + + cfmakeraw(&tstate); + /* keep output flags as they where, since we'll be drawing directly to fbdev */ + tstate.c_oflag = orig_state.c_oflag; + if(tcsetattr(term_fd, TCSANOW, &tstate) == -1) { + perror("failed put terminal into raw mode"); + close(term_fd); + return -1; + } + return 0; +} + +void fbev_shutdown(void) +{ + if(term_fd >= 0) { + tcsetattr(term_fd, TCSANOW, &orig_state); + close(term_fd); + term_fd = -1; + } +} + +void fbev_update(void) +{ + char buf[64]; + int i, sz; + assert(term_fd >= 0); + + while((sz = read(term_fd, buf, 64)) > 0) { + if(keyb_func) { + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include "fbgfx.h" + +static void cleanup(void); + +static int fd = -1; +static void *vmem; +static int vmem_size; +static struct fb_fix_screeninfo finfo; +static struct fb_var_screeninfo vinfo; +static struct fb_var_screeninfo saved_vinfo; +static int saved_vinfo_valid; +static struct fbgfx_vmode curvm; + +static int init(void) +{ + if(fd >= 0) return 0; + + if((fd = open("/dev/fb0", O_RDWR)) == -1) { + fprintf(stderr, "failed to open framebuffer device\n"); + return -1; + } + + ioctl(fd, FBIOGET_FSCREENINFO, &finfo); + + curvm.pitch = finfo.line_length; + + atexit(cleanup); + return 0; +} + +static void cleanup(void) +{ + if(vmem) { + munmap(vmem, vmem_size); + } + if(fd != -1) { + close(fd); + } +} + +void *fbgfx_set_video_mode(int x, int y, int depth) +{ + struct fb_var_screeninfo new_vinfo; + + if(init() == -1) { + return 0; + } + + ioctl(fd, FBIOGET_VSCREENINFO, &new_vinfo); + new_vinfo.xres = x; + new_vinfo.yres = y; + new_vinfo.bits_per_pixel = depth; + + if(ioctl(fd, FBIOPUT_VSCREENINFO, &new_vinfo) == -1) { + fprintf(stderr, "failed to set video mode %dx%d %dbpp: %s\n", x, y, depth, strerror(errno)); + return 0; + } + + if(vmem) { + munmap(vmem, vmem_size); + vmem = 0; + vmem_size = 0; + } + + return fbgfx_get_video_mode(0, 0, 0); +} + +void *fbgfx_get_video_mode(int *xptr, int *yptr, int *depthptr) +{ + if(init() == -1) { + return 0; + } + + ioctl(fd, FBIOGET_VSCREENINFO, &vinfo); + /*vmem_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;*/ + vmem_size = finfo.smem_len; + + curvm.width = vinfo.xres; + curvm.height = vinfo.yres; + curvm.bpp = vinfo.bits_per_pixel; + curvm.fbsize = vmem_size; + curvm.rshift = vinfo.red.offset; + curvm.gshift = vinfo.green.offset; + curvm.bshift = vinfo.blue.offset; + curvm.rmask = (0xffffffff >> (32 - vinfo.red.length)) << curvm.rshift; + curvm.gmask = (0xffffffff >> (32 - vinfo.green.length)) << curvm.gshift; + curvm.bmask = (0xffffffff >> (32 - vinfo.blue.length)) << curvm.bshift; + + if(!vmem) { + if((vmem = mmap(0, vmem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == (void*)-1) { + fprintf(stderr, "failed to map video memory\n"); + vmem = 0; + return 0; + } + } + if(xptr) *xptr = vinfo.xres; + if(yptr) *yptr = vinfo.yres; + if(depthptr) *depthptr = vinfo.bits_per_pixel; + return vmem; +} + +void fbgfx_save_video_mode(void) +{ + if(init() == -1) { + return; + } + + if(ioctl(fd, FBIOGET_VSCREENINFO, &saved_vinfo) == -1) { + return; + } + saved_vinfo_valid = 1; +} + +void fbgfx_restore_video_mode(void) +{ + if(init() == -1 || !saved_vinfo_valid) { + return; + } + ioctl(fd, FBIOPUT_VSCREENINFO, &saved_vinfo); +} + +struct fbgfx_vmode *fbgfx_video_mode_info(void) +{ + return &curvm; +} diff --git a/src/fbdev/fbgfx.h b/src/fbdev/fbgfx.h new file mode 100644 index 0000000..882d883 --- /dev/null +++ b/src/fbdev/fbgfx.h @@ -0,0 +1,21 @@ +#ifndef FBGFX_H_ +#define FBGFX_H_ + +struct fbgfx_vmode { + int width, height, bpp; + int pitch; + unsigned int rmask, gmask, bmask; + int rshift, gshift, bshift; + int fbsize; +}; + +void *fbgfx_set_video_mode(int x, int y, int depth); +void *fbgfx_get_video_mode(int *xptr, int *yptr, int *depthptr); + +void fbgfx_save_video_mode(void); +void fbgfx_restore_video_mode(void); + +struct fbgfx_vmode *fbgfx_video_mode_info(void); + + +#endif /* FBGFX_H_ */ diff --git a/src/fbdev/main.c b/src/fbdev/main.c index 3c5def6..88c4638 100644 --- a/src/fbdev/main.c +++ b/src/fbdev/main.c @@ -7,23 +7,22 @@ #include #include #include +#include "fbgfx.h" +#include "fbevents.h" #include "rbench.h" #include "util.h" - -static int init_fbdev(int xsz, int ysz, int bpp); -static void close_fbdev(void); +static void keyb(int key, int pressed, void *cls); static int parse_args(int argc, char **argv); -static int fbfd = -1; -static int fbsz; +static int quit; static void *fbmem; - int main(int argc, char **argv) { int num_frames = 0; struct timeval tv, tv0; + struct fbgfx_vmode *vm; read_config("rbench.cfg"); @@ -31,52 +30,58 @@ int main(int argc, char **argv) return 1; } - if(init_fbdev(opt.width, opt.height, opt.bpp) == -1) { + fbgfx_save_video_mode(); + if(!(fbmem = fbgfx_set_video_mode(opt.width, opt.height, opt.bpp))) { + fprintf(stderr, "failed to set video mode: %dx%d %dbpp\n", opt.width, + opt.height, opt.bpp); return 1; } - - fb_width = opt.width; - fb_height = opt.height; - fb_bpp = opt.bpp; - fb_pitch = opt.width * opt.bpp / 8; + vm = fbgfx_video_mode_info(); + + fb_width = vm->width; + fb_height = vm->height; + fb_bpp = vm->bpp; + fb_pitch = vm->pitch; + fb_rmask = vm->rmask; + fb_gmask = vm->gmask; + fb_bmask = vm->bmask; + fb_rshift = vm->rshift; + fb_gshift = vm->gshift; + fb_bshift = vm->bshift; if(!(framebuf = malloc(fb_pitch * fb_height))) { fprintf(stderr, "failed to allocate %dx%d (%d bpp) framebuffer\n", fb_width, fb_height, fb_bpp); return 1; } - /* - fb_rmask = ximg->red_mask; - fb_gmask = ximg->green_mask; - fb_bmask = ximg->blue_mask; - fb_rshift = mask_to_shift(fb_rmask); - fb_gshift = mask_to_shift(fb_gmask); - fb_bshift = mask_to_shift(fb_bmask); - */ - if(init() == -1) { + if(fbev_init() == -1) { goto end; } + fbev_keyboard(keyb, 0); - /* TODO: set terminal raw and disable cursor */ + if(init() == -1) { + goto end; + } gettimeofday(&tv0, 0); for(;;) { - /* TODO read input */ + fbev_update(); + if(quit) break; gettimeofday(&tv, 0); time_msec = (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000; num_frames++; redraw(); - - /* TODO copy to fb */ + memcpy(fbmem, framebuf, fb_pitch * fb_height); } end: cleanup(); - close_fbdev(); + fbev_shutdown(); + fbgfx_restore_video_mode(); if(num_frames) { printf("avg framerate: %.1f fps\n", (10000 * num_frames / time_msec) / 10.0f); @@ -84,34 +89,15 @@ end: return 0; } -int init_fbdev(int xsz, int ysz, int bpp) +static void keyb(int key, int pressed, void *cls) { - if((fbfd = open("/dev/fb0", O_RDWR)) == -1) { - perror("failed to open framebuffer device"); - return -1; - } + if(!pressed) return; - /* TODO modeset ioctl */ - - fbsz = xsz * ysz * bpp / 8; /* XXX */ - - if((fbmem = mmap(0, fbsz, PROT_WRITE, MAP_SHARED, fbfd, 0)) == (void*)-1) { - perror("failed to map framebuffer"); - return -1; + if(key == 27 || key == 'q' || key == 'Q') { + quit = 1; } - - return 0; } -void close_fbdev(void) -{ - if(fbmem) { - munmap(fbmem, fbsz); - } - if(fbfd >= 0) { - close(fbfd); - } -} static const char *usage_str = "Usage: %s [options]\n" -- 1.7.10.4