frontend: improve minimize handling
[pcsx_rearmed.git] / frontend / plat_omap.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2010-2012
3  *
4  * This work is licensed under the terms of the GNU GPLv2 or later.
5  * See the COPYING file in the top-level directory.
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include <unistd.h>
15 #include <linux/omapfb.h>
16
17 #include "common/menu.h"
18 #include "common/input.h"
19 #include "linux/fbdev.h"
20 #include "linux/xenv.h"
21 #include "plugin_lib.h"
22 #include "pl_gun_ts.h"
23 #include "plat.h"
24 #include "plat_omap.h"
25 #include "menu.h"
26
27 static struct vout_fbdev *main_fb, *layer_fb;
28
29 static int omap_setup_layer_(int fd, int enabled, int x, int y, int w, int h)
30 {
31         struct omapfb_plane_info pi = { 0, };
32         struct omapfb_mem_info mi = { 0, };
33         int ret;
34
35         ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
36         if (ret != 0) {
37                 perror("QUERY_PLANE");
38                 return -1;
39         }
40
41         ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
42         if (ret != 0) {
43                 perror("QUERY_MEM");
44                 return -1;
45         }
46
47         /* must disable when changing stuff */
48         if (pi.enabled) {
49                 pi.enabled = 0;
50                 ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
51                 if (ret != 0)
52                         perror("SETUP_PLANE");
53         }
54
55         if (mi.size < 640*512*3*3) {
56                 mi.size = 640*512*3*3;
57                 ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
58                 if (ret != 0) {
59                         perror("SETUP_MEM");
60                         return -1;
61                 }
62         }
63
64         pi.pos_x = x;
65         pi.pos_y = y;
66         pi.out_width = w;
67         pi.out_height = h;
68         pi.enabled = enabled;
69
70         ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
71         if (ret != 0) {
72                 perror("SETUP_PLANE");
73                 return -1;
74         }
75
76         return 0;
77 }
78
79 static int omap_enable_layer(int enabled)
80 {
81         if (enabled)
82                 pl_set_gun_rect(g_layer_x, g_layer_y, g_layer_w, g_layer_h);
83
84         return omap_setup_layer_(vout_fbdev_get_fd(layer_fb), enabled,
85                 g_layer_x, g_layer_y, g_layer_w, g_layer_h);
86 }
87
88 void plat_omap_gvideo_open(void)
89 {
90         omap_enable_layer(1);
91
92         // try to align redraws to vsync
93         vout_fbdev_wait_vsync(layer_fb);
94 }
95
96 void *plat_gvideo_set_mode(int *w, int *h, int *bpp)
97 {
98         void *buf;
99
100         vout_fbdev_clear(layer_fb);
101         buf = vout_fbdev_resize(layer_fb, *w, *h, *bpp, 0, 0, 0, 0, 3);
102
103         omap_enable_layer(1);
104
105         return buf;
106 }
107
108 void *plat_gvideo_flip(void)
109 {
110         return vout_fbdev_flip(layer_fb);
111 }
112
113 void plat_gvideo_close(void)
114 {
115         omap_enable_layer(0);
116 }
117
118 void plat_video_menu_enter(int is_rom_loaded)
119 {
120         g_menuscreen_ptr = vout_fbdev_resize(main_fb,
121                 g_menuscreen_w, g_menuscreen_h, 16, 0, 0, 0, 0, 3);
122         if (g_menuscreen_ptr == NULL)
123                 fprintf(stderr, "warning: vout_fbdev_resize failed\n");
124
125         xenv_update(NULL, NULL, NULL, NULL);
126 }
127
128 void plat_video_menu_begin(void)
129 {
130 }
131
132 void plat_video_menu_end(void)
133 {
134         g_menuscreen_ptr = vout_fbdev_flip(main_fb);
135 }
136
137 void plat_video_menu_leave(void)
138 {
139         /* have to get rid of panning so that plugins that
140          * use fb0 and don't ever pan can work. */
141         vout_fbdev_clear(main_fb);
142         g_menuscreen_ptr = vout_fbdev_resize(main_fb,
143                 g_menuscreen_w, g_menuscreen_h, 16, 0, 0, 0, 0, 1);
144         if (g_menuscreen_ptr == NULL)
145                 fprintf(stderr, "warning: vout_fbdev_resize failed\n");
146 }
147
148 void plat_minimize(void)
149 {
150         int ret;
151
152         ret = vout_fbdev_save(layer_fb);
153         if (ret != 0) {
154                 printf("minimize: layer/fb handling failed\n");
155                 return;
156         }
157
158         xenv_minimize();
159
160         in_set_config_int(0, IN_CFG_BLOCKING, 0); /* flush event queue */
161         omap_enable_layer(0); /* restore layer mem */
162         vout_fbdev_restore(layer_fb);
163 }
164
165 void *plat_prepare_screenshot(int *w, int *h, int *bpp)
166 {
167         return NULL;
168 }
169
170 void plat_omap_init(void)
171 {
172         const char *main_fb_name, *layer_fb_name;
173         int fd, ret, w, h;
174
175         main_fb_name = getenv("FBDEV_MAIN");
176         if (main_fb_name == NULL)
177                 main_fb_name = "/dev/fb0";
178
179         layer_fb_name = getenv("FBDEV_LAYER");
180         if (layer_fb_name == NULL)
181                 layer_fb_name = "/dev/fb1";
182
183         // must set the layer up first to be able to use it
184         fd = open(layer_fb_name, O_RDWR);
185         if (fd == -1) {
186                 fprintf(stderr, "%s: ", layer_fb_name);
187                 perror("open");
188                 exit(1);
189         }
190
191         g_layer_x = 80, g_layer_y = 0;
192         g_layer_w = 640, g_layer_h = 480;
193
194         ret = omap_setup_layer_(fd, 0, g_layer_x, g_layer_y, g_layer_w, g_layer_h);
195         close(fd);
196         if (ret != 0) {
197                 fprintf(stderr, "failed to set up layer, exiting.\n");
198                 exit(1);
199         }
200
201         xenv_init(NULL, "PCSX-ReARMed");
202
203         w = h = 0;
204         main_fb = vout_fbdev_init(main_fb_name, &w, &h, 16, 2);
205         if (main_fb == NULL) {
206                 fprintf(stderr, "couldn't init fb: %s\n", main_fb_name);
207                 exit(1);
208         }
209
210         g_menuscreen_w = w;
211         g_menuscreen_h = h;
212         g_menuscreen_ptr = vout_fbdev_flip(main_fb);
213         pl_rearmed_cbs.screen_w = w;
214         pl_rearmed_cbs.screen_h = h;
215
216         w = 640;
217         h = 512;
218         layer_fb = vout_fbdev_init(layer_fb_name, &w, &h, 16, 3);
219         if (layer_fb == NULL) {
220                 fprintf(stderr, "couldn't init fb: %s\n", layer_fb_name);
221                 goto fail0;
222         }
223
224         return;
225
226 fail0:
227         vout_fbdev_finish(main_fb);
228         exit(1);
229 }
230
231 void plat_omap_finish(void)
232 {
233         omap_enable_layer(0);
234         vout_fbdev_finish(layer_fb);
235         vout_fbdev_finish(main_fb);
236         xenv_finish();
237 }
238