almost
[fbgfx] / src / fbgfx.c
index 4b96eeb..d7fe862 100644 (file)
@@ -1,5 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
@@ -14,6 +16,8 @@ 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 int init(void)
 {
@@ -42,10 +46,29 @@ static void cleanup(void)
 
 void *fbgfx_set_video_mode(int x, int y, int depth)
 {
+       struct fb_var_screeninfo new_vinfo;
+
        if(init() == -1) {
                return 0;
        }
-       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)
@@ -53,18 +76,39 @@ void *fbgfx_get_video_mode(int *xptr, int *yptr, int *depthptr)
        if(init() == -1) {
                return 0;
        }
-       if(vmem) return vmem;
 
        ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
        vmem_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
 
-       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(!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;
+               }
        }
-       *xptr = vinfo.xres;
-       *yptr = vinfo.yres;
-       *depthptr = vinfo.bits_per_pixel;
+       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);
+}