op_runfbapp: more complete layer state save/restore
authorGrazvydas Ignotas <notasas@gmail.com>
Sun, 4 Aug 2013 15:07:29 +0000 (18:07 +0300)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 4 Aug 2013 15:07:29 +0000 (18:07 +0300)
op_runfbapp.c

index 4a5abb3..1c73d59 100644 (file)
@@ -42,6 +42,7 @@
 #include <termios.h>
 #include <signal.h>
 #include <linux/kd.h>
+#include <linux/fb.h>
 
 #define __user
 #include "omapfb.h"
@@ -95,61 +96,159 @@ static void x11h_wait_vmstate(Display *display)
        fprintf(stderr, "timeout waiting for wm_state change\n");
 }
 
-static struct omapfb_plane_info omap_pi;
+static struct omapfb_plane_info desktop_pi, app_pi[2];
+static struct fb_var_screeninfo desktop_si, app_si[2];
+static int desktop_saved;
 
-static int hide_omap_layer(void)
+static int save_fb_state(int index, struct omapfb_plane_info *pi,
+                        struct fb_var_screeninfo *si)
 {
        int retval = -1;
+       char buf[16];
+       int fd = -1;
        int ret;
-       int fd;
 
-       fd = open("/dev/fb1", O_RDWR);
+       snprintf(buf, sizeof(buf), "/dev/fb%d", index);
+       fd = open(buf, O_RDWR);
        if (fd == -1) {
-               perror("open(/dev/fb1)");
-               return -1;
+               fprintf(stderr, PFX);
+               perror(buf);
+               goto out;
+       }
+
+       ret = ioctl(fd, OMAPFB_QUERY_PLANE, pi);
+       if (ret != 0) {
+               perror(PFX "QUERY_PLANE");
+               goto out;
+       }
+
+       ret = ioctl(fd, FBIOGET_VSCREENINFO, si);
+       if (ret == -1) {
+               perror(PFX "FBIOGET_VSCREENINFO");
+               goto out;
+       }
+
+       retval = 0;
+out:
+       if (fd != -1)
+               close(fd);
+       return retval;
+}
+
+static int load_fb_state(int index, struct omapfb_plane_info *pi,
+                        struct fb_var_screeninfo *si)
+{
+       struct omapfb_plane_info tmp_pi;
+       int retval = -1;
+       char buf[16];
+       int fd = -1;
+       int ret;
+
+       snprintf(buf, sizeof(buf), "/dev/fb%d", index);
+       fd = open(buf, O_RDWR);
+       if (fd == -1) {
+               fprintf(stderr, PFX);
+               perror(buf);
+               goto out;
+       }
+
+       // resolution can sometimes only be restored if position is right,
+       // so it's a bit more tricky..
+       ret = ioctl(fd, OMAPFB_QUERY_PLANE, &tmp_pi);
+       if (ret != 0) {
+               perror(PFX "QUERY_PLANE");
+               goto out;
+       }
+
+       tmp_pi.enabled = 0;
+       tmp_pi.pos_x = 0;
+       tmp_pi.pos_y = 0;
+       ret = ioctl(fd, OMAPFB_SETUP_PLANE, &tmp_pi);
+       if (ret != 0) {
+               perror(PFX "SETUP_PLANE");
+               goto out;
+       }
+
+       ret = ioctl(fd, FBIOPUT_VSCREENINFO, si);
+       if (ret == -1) {
+               perror(PFX "FBIOPUT_VSCREENINFO");
+               goto out;
        }
 
-       ret = ioctl(fd, OMAPFB_QUERY_PLANE, &omap_pi);
+       ret = ioctl(fd, OMAPFB_SETUP_PLANE, pi);
        if (ret != 0) {
-               perror("QUERY_PLANE");
+               perror(PFX "SETUP_PLANE(2)");
                goto out;
        }
 
-       if (omap_pi.enabled) {
-               omap_pi.enabled = 0;
-               ret = ioctl(fd, OMAPFB_SETUP_PLANE, &omap_pi);
+       retval = 0;
+out:
+       if (fd != -1)
+               close(fd);
+       return retval;
+}
+
+// prepare OMAP layers for desktop
+static int minimize_omap_layers(void)
+{
+       struct omapfb_plane_info pi_set;
+       int retval = -1;
+       int fd = -1;
+       int i, ret;
+
+       if (!desktop_saved) {
+               fprintf(stderr, PFX "desktop not saved\n");
+               goto out;
+       }
+
+       for (i = 0; i < 2; i++) {
+               ret = save_fb_state(i, &app_pi[i], &app_si[i]);
                if (ret != 0) {
-                       perror("SETUP_PLANE");
+                       fprintf(stderr, PFX "layer %d state save failed\n", i);
                        goto out;
                }
+       }
+
+       retval = 0; // no restoring needed
+
+       if (memcmp(&app_pi[0], &desktop_pi, sizeof(desktop_pi)) != 0) {
+               ret = load_fb_state(0, &desktop_pi, &desktop_si);
+               if (ret != 0) {
+                       fprintf(stderr, PFX "desktop restore failed\n");
+                       // but continue, I guess?
+               }
                retval = 1;
        }
-       else {
-               retval = 0;
+
+       if (app_pi[1].enabled) {
+               pi_set = app_pi[1];
+               pi_set.enabled = 0;
+
+               fd = open("/dev/fb1", O_RDWR);
+               ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi_set);
+               if (ret != 0) {
+                       perror(PFX "SETUP_PLANE");
+               }
+               retval = 1;
        }
 
 out:
-       close(fd);
+       if (fd != -1)
+               close(fd);
        return retval;
 }
 
-static void show_omap_layer(void)
+static void restore_omap_layers(void)
 {
-       int ret;
-       int fd;
+       int i, ret;
 
-       fd = open("/dev/fb1", O_RDWR);
-       if (fd == -1) {
-               perror("open(/dev/fb1)");
-               return;
+       for (i = 0; i < 2; i++) {
+               ret = load_fb_state(i, &app_pi[i], &app_si[i]);
+               if (ret != 0) {
+                       fprintf(stderr, PFX "layer %d state load failed\n", i);
+                       // .. but try to continue ..
+               }
        }
-
-       omap_pi.enabled = 1;
-       ret = ioctl(fd, OMAPFB_SETUP_PLANE, &omap_pi);
-       if (ret != 0)
-               perror("SETUP_PLANE");
-
-       close(fd);
 }
 
 static int x11h_minimize(Display *display, Window window)
@@ -269,10 +368,17 @@ static void *x11_handler(void *arg)
                            && g_child_pid != 0) {
                                kill(g_child_pid, SIGSTOP);
 
-                               ret = hide_omap_layer();
-                               x11h_minimize(display, win);
-                               if (ret > 0)
-                                       show_omap_layer();
+                               ret = minimize_omap_layers();
+                               if (ret >= 0) {
+                                       fflush(stdout);
+                                       fflush(stderr);
+                                       x11h_minimize(display, win);
+                               }
+                               if (ret > 0) {
+                                       restore_omap_layers();
+                                       fflush(stdout);
+                                       fflush(stderr);
+                               }
 
                                kill(g_child_pid, SIGCONT);
                        }
@@ -394,6 +500,13 @@ int main(int argc, char *argv[])
        }
        pthread_detach(tid);
 
+       // assume desktop is in good state..
+       ret = save_fb_state(0, &desktop_pi, &desktop_si);
+       if (ret == 0)
+               desktop_saved = 1;
+       else
+               fprintf(stderr, PFX "initial desktop state save failed\n");
+
        pthread_cond_wait(&g_start_cond, &g_start_mutex);
        pthread_mutex_unlock(&g_start_mutex);