11 #include <linux/matroxfb.h>
15 #define FBDEV_MAX_BUFFERS 3
21 struct fb_var_screeninfo fbvar_old;
22 struct fb_var_screeninfo fbvar_new;
24 void *buffers[FBDEV_MAX_BUFFERS];
28 void *vout_fbdev_flip(struct vout_fbdev *fbdev)
32 if (fbdev->buffer_count < 2)
35 draw_buf = fbdev->buffer_write;
36 fbdev->buffer_write++;
37 if (fbdev->buffer_write >= fbdev->buffer_count)
38 fbdev->buffer_write = 0;
40 fbdev->fbvar_new.yoffset = fbdev->fbvar_old.yres * draw_buf;
42 ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new);
44 return fbdev->buffers[fbdev->buffer_write];
47 void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev)
50 ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &arg);
53 void vout_fbdev_clear(struct vout_fbdev *fbdev)
55 memset(fbdev->mem, 0, fbdev->mem_size);
58 struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int no_dblbuf)
60 struct vout_fbdev *fbdev;
63 fbdev = calloc(1, sizeof(*fbdev));
67 fbdev->fd = open(fbdev_name, O_RDWR);
68 if (fbdev->fd == -1) {
69 fprintf(stderr, "%s: ", fbdev_name);
74 ret = ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->fbvar_old);
76 perror("FBIOGET_VSCREENINFO ioctl");
80 fbdev->fbvar_new = fbdev->fbvar_old;
81 printf("%s: %ix%i@%d\n", fbdev_name, fbdev->fbvar_old.xres, fbdev->fbvar_old.yres,
82 fbdev->fbvar_old.bits_per_pixel);
83 *w = fbdev->fbvar_old.xres;
84 *h = fbdev->fbvar_old.yres;
85 fbdev->buffer_count = FBDEV_MAX_BUFFERS; // be optimistic
87 fbdev->buffer_count = 1;
89 if (fbdev->fbvar_new.bits_per_pixel != 16) {
90 printf(" switching to 16bpp\n");
91 fbdev->fbvar_new.bits_per_pixel = 16;
92 ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
94 perror("FBIOPUT_VSCREENINFO ioctl");
99 if (fbdev->fbvar_new.yres_virtual < fbdev->fbvar_old.yres * fbdev->buffer_count) {
100 fbdev->fbvar_new.yres_virtual = fbdev->fbvar_old.yres * fbdev->buffer_count;
101 ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
103 fbdev->buffer_count = 1;
104 fprintf(stderr, "Warning: failed to increase virtual resolution, "
105 "doublebuffering disabled\n");
109 fbdev->mem_size = *w * *h * 2 * fbdev->buffer_count;
110 fbdev->mem = mmap(0, fbdev->mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
111 if (fbdev->mem == MAP_FAILED && fbdev->buffer_count > 1) {
112 fprintf(stderr, "Warning: can't map %zd bytes, doublebuffering disabled\n", fbdev->mem_size);
113 fbdev->mem_size = *w * *h * 2;
114 fbdev->buffer_count = 1;
115 fbdev->mem = mmap(0, fbdev->mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
117 if (fbdev->mem == MAP_FAILED) {
118 perror("mmap framebuffer");
121 memset(fbdev->mem, 0, fbdev->mem_size);
122 for (i = 0; i < fbdev->buffer_count; i++)
123 fbdev->buffers[i] = (char *)fbdev->mem + i * *w * *h * 2;
127 ret = ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &ret);
129 fprintf(stderr, "Warning: vsync doesn't seem to be supported\n");
131 if (fbdev->buffer_count > 1) {
132 fbdev->buffer_write = 0;
133 fbdev->fbvar_new.yoffset = fbdev->fbvar_old.yres * (fbdev->buffer_count - 1);
134 ret = ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new);
136 fbdev->buffer_count = 1;
137 fprintf(stderr, "Warning: can't pan display, doublebuffering disabled\n");
141 printf("fbdev initialized.\n");
151 void vout_fbdev_finish(struct vout_fbdev *fbdev)
153 ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_old);
154 if (fbdev->mem != MAP_FAILED)
155 munmap(fbdev->mem, fbdev->mem_size);
168 vout_fbdev_init(&w, &h);
171 memset(g_screen_ptr, 0xff, fbdev_mem_size / 2);
172 plat_video_wait_vsync();
174 memset(g_screen_ptr, 0x00, fbdev_mem_size / 2);
176 // plat_video_wait_vsync();