From b9fe67c67c292b51545a2486620fef95b5f722ee Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 18 Aug 2010 13:17:19 +0000 Subject: [PATCH] allow multiple fbdevs git-svn-id: file:///home/notaz/opt/svn/PicoDrive@881 be3aeb3a-fb24-0410-a615-afba39da0efa --- platform/linux/fbdev.c | 156 +++++++++++++++++++++++------------------ platform/linux/fbdev.h | 10 +-- 2 files changed, 92 insertions(+), 74 deletions(-) diff --git a/platform/linux/fbdev.c b/platform/linux/fbdev.c index adf7a3d4..afcd5290 100644 --- a/platform/linux/fbdev.c +++ b/platform/linux/fbdev.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -9,139 +10,154 @@ #include #include -#include "../common/emu.h" #include "fbdev.h" #define FBDEV_MAX_BUFFERS 3 -static int fbdev = -1; -static void *fbdev_mem = MAP_FAILED; -static int fbdev_mem_size; -static struct fb_var_screeninfo fbvar_old; -static struct fb_var_screeninfo fbvar_new; -static int fbdev_buffer_write; - -void *fbdev_buffers[FBDEV_MAX_BUFFERS]; -int fbdev_buffer_count; - -void plat_video_flip(void) +struct vout_fbdev { + int fd; + void *mem; + size_t mem_size; + struct fb_var_screeninfo fbvar_old; + struct fb_var_screeninfo fbvar_new; + int buffer_write; + void *buffers[FBDEV_MAX_BUFFERS]; + int buffer_count; +}; + +void *vout_fbdev_flip(struct vout_fbdev *fbdev) { int draw_buf; - if (fbdev_buffer_count < 2) - return; + if (fbdev->buffer_count < 2) + return fbdev->mem; - draw_buf = fbdev_buffer_write; - fbdev_buffer_write++; - if (fbdev_buffer_write >= fbdev_buffer_count) - fbdev_buffer_write = 0; + draw_buf = fbdev->buffer_write; + fbdev->buffer_write++; + if (fbdev->buffer_write >= fbdev->buffer_count) + fbdev->buffer_write = 0; - fbvar_new.yoffset = fbvar_old.yres * draw_buf; - g_screen_ptr = fbdev_buffers[fbdev_buffer_write]; + fbdev->fbvar_new.yoffset = fbdev->fbvar_old.yres * draw_buf; - ioctl(fbdev, FBIOPAN_DISPLAY, &fbvar_new); + ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new); + + return fbdev->buffers[fbdev->buffer_write]; } -void plat_video_wait_vsync(void) +void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev) { int arg = 0; - ioctl(fbdev, FBIO_WAITFORVSYNC, &arg); + ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &arg); } -int vout_fbdev_init(int *w, int *h) +void vout_fbdev_clear(struct vout_fbdev *fbdev) { - static const char *fbdev_name = "/dev/fb0"; + memset(fbdev->mem, 0, fbdev->mem_size); +} + +struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int no_dblbuf) +{ + struct vout_fbdev *fbdev; int i, ret; - fbdev = open(fbdev_name, O_RDWR); - if (fbdev == -1) { + fbdev = calloc(1, sizeof(*fbdev)); + if (fbdev == NULL) + return NULL; + + fbdev->fd = open(fbdev_name, O_RDWR); + if (fbdev->fd == -1) { fprintf(stderr, "%s: ", fbdev_name); perror("open"); - return -1; + goto fail_open; } - ret = ioctl(fbdev, FBIOGET_VSCREENINFO, &fbvar_old); + ret = ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->fbvar_old); if (ret == -1) { perror("FBIOGET_VSCREENINFO ioctl"); goto fail; } - fbvar_new = fbvar_old; - printf("%s: %ix%i@%d\n", fbdev_name, fbvar_old.xres, fbvar_old.yres, fbvar_old.bits_per_pixel); - *w = fbvar_old.xres; - *h = fbvar_old.yres; - fbdev_buffer_count = FBDEV_MAX_BUFFERS; // be optimistic + fbdev->fbvar_new = fbdev->fbvar_old; + printf("%s: %ix%i@%d\n", fbdev_name, fbdev->fbvar_old.xres, fbdev->fbvar_old.yres, + fbdev->fbvar_old.bits_per_pixel); + *w = fbdev->fbvar_old.xres; + *h = fbdev->fbvar_old.yres; + fbdev->buffer_count = FBDEV_MAX_BUFFERS; // be optimistic + if (no_dblbuf) + fbdev->buffer_count = 1; - if (fbvar_new.bits_per_pixel != 16) { + if (fbdev->fbvar_new.bits_per_pixel != 16) { printf(" switching to 16bpp\n"); - fbvar_new.bits_per_pixel = 16; - ret = ioctl(fbdev, FBIOPUT_VSCREENINFO, &fbvar_new); + fbdev->fbvar_new.bits_per_pixel = 16; + ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); if (ret == -1) { perror("FBIOPUT_VSCREENINFO ioctl"); goto fail; } } - if (fbvar_new.yres_virtual < fbvar_old.yres * fbdev_buffer_count) { - fbvar_new.yres_virtual = fbvar_old.yres * fbdev_buffer_count; - ret = ioctl(fbdev, FBIOPUT_VSCREENINFO, &fbvar_new); + if (fbdev->fbvar_new.yres_virtual < fbdev->fbvar_old.yres * fbdev->buffer_count) { + fbdev->fbvar_new.yres_virtual = fbdev->fbvar_old.yres * fbdev->buffer_count; + ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); if (ret == -1) { - fbdev_buffer_count = 1; + fbdev->buffer_count = 1; fprintf(stderr, "Warning: failed to increase virtual resolution, " "doublebuffering disabled\n"); } } - fbdev_mem_size = *w * *h * 2 * fbdev_buffer_count; - fbdev_mem = mmap(0, fbdev_mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev, 0); - if (fbdev_mem == MAP_FAILED && fbdev_buffer_count > 1) { - fprintf(stderr, "Warning: can't map %d bytes, doublebuffering disabled\n", fbdev_mem_size); - fbdev_mem_size = *w * *h * 2; - fbdev_buffer_count = 1; - fbdev_mem = mmap(0, fbdev_mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev, 0); + fbdev->mem_size = *w * *h * 2 * fbdev->buffer_count; + fbdev->mem = mmap(0, fbdev->mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); + if (fbdev->mem == MAP_FAILED && fbdev->buffer_count > 1) { + fprintf(stderr, "Warning: can't map %zd bytes, doublebuffering disabled\n", fbdev->mem_size); + fbdev->mem_size = *w * *h * 2; + fbdev->buffer_count = 1; + fbdev->mem = mmap(0, fbdev->mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); } - if (fbdev_mem == MAP_FAILED) { + if (fbdev->mem == MAP_FAILED) { perror("mmap framebuffer"); goto fail; } - memset(fbdev_mem, 0, fbdev_mem_size); - for (i = 0; i < fbdev_buffer_count; i++) - fbdev_buffers[i] = (char *)fbdev_mem + i * *w * *h * 2; - g_screen_ptr = fbdev_buffers[0]; + memset(fbdev->mem, 0, fbdev->mem_size); + for (i = 0; i < fbdev->buffer_count; i++) + fbdev->buffers[i] = (char *)fbdev->mem + i * *w * *h * 2; // some checks ret = 0; - ret = ioctl(fbdev, FBIO_WAITFORVSYNC, &ret); + ret = ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &ret); if (ret != 0) fprintf(stderr, "Warning: vsync doesn't seem to be supported\n"); - if (fbdev_buffer_count > 1) { - fbdev_buffer_write = 0; - fbvar_new.yoffset = fbvar_old.yres * (fbdev_buffer_count - 1); - ret = ioctl(fbdev, FBIOPAN_DISPLAY, &fbvar_new); + if (fbdev->buffer_count > 1) { + fbdev->buffer_write = 0; + fbdev->fbvar_new.yoffset = fbdev->fbvar_old.yres * (fbdev->buffer_count - 1); + ret = ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new); if (ret != 0) { - fbdev_buffer_count = 1; + fbdev->buffer_count = 1; fprintf(stderr, "Warning: can't pan display, doublebuffering disabled\n"); } } printf("fbdev initialized.\n"); - return 0; + return fbdev; fail: - close(fbdev); - return -1; + close(fbdev->fd); +fail_open: + free(fbdev); + return NULL; } -void vout_fbdev_finish(void) +void vout_fbdev_finish(struct vout_fbdev *fbdev) { - ioctl(fbdev, FBIOPUT_VSCREENINFO, &fbvar_old); - if (fbdev_mem != MAP_FAILED) - munmap(fbdev_mem, fbdev_mem_size); - if (fbdev >= 0) - close(fbdev); - fbdev_mem = NULL; - fbdev = -1; + ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_old); + if (fbdev->mem != MAP_FAILED) + munmap(fbdev->mem, fbdev->mem_size); + if (fbdev->fd >= 0) + close(fbdev->fd); + fbdev->mem = NULL; + fbdev->fd = -1; + free(fbdev); } #if 0 diff --git a/platform/linux/fbdev.h b/platform/linux/fbdev.h index 1e5d28bb..9e5d4335 100644 --- a/platform/linux/fbdev.h +++ b/platform/linux/fbdev.h @@ -1,5 +1,7 @@ -int vout_fbdev_init(int *w, int *h); -void vout_fbdev_finish(void); +struct vout_fbdev; -extern void *fbdev_buffers[]; -extern int fbdev_buffer_count; +struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int no_dblbuf); +void *vout_fbdev_flip(struct vout_fbdev *fbdev); +void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev); +void vout_fbdev_clear(struct vout_fbdev *fbdev); +void vout_fbdev_finish(struct vout_fbdev *fbdev); -- 2.39.5