attempt to make gles plugin work under RPi
[pcsx_rearmed.git] / frontend / plat_sdl.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2011-2013
3  *
4  * This work is licensed under the terms of any of these licenses
5  * (at your option):
6  *  - GNU GPL, version 2 or later.
7  *  - GNU LGPL, version 2.1 or later.
8  * See the COPYING file in the top-level directory.
9  */
10
11 #include <stdio.h>
12 #include <SDL.h>
13
14 #include "libpicofe/input.h"
15 #include "libpicofe/in_sdl.h"
16 #include "libpicofe/menu.h"
17 #include "libpicofe/fonts.h"
18 #include "libpicofe/plat_sdl.h"
19 #include "libpicofe/gl.h"
20 #include "../plugins/gpulib/cspace.h"
21 #include "plugin_lib.h"
22 #include "plugin.h"
23 #include "main.h"
24 #include "plat.h"
25 #include "revision.h"
26
27 static const struct in_default_bind in_sdl_defbinds[] = {
28   { SDLK_UP,     IN_BINDTYPE_PLAYER12, DKEY_UP },
29   { SDLK_DOWN,   IN_BINDTYPE_PLAYER12, DKEY_DOWN },
30   { SDLK_LEFT,   IN_BINDTYPE_PLAYER12, DKEY_LEFT },
31   { SDLK_RIGHT,  IN_BINDTYPE_PLAYER12, DKEY_RIGHT },
32   { SDLK_d,      IN_BINDTYPE_PLAYER12, DKEY_TRIANGLE },
33   { SDLK_z,      IN_BINDTYPE_PLAYER12, DKEY_CROSS },
34   { SDLK_x,      IN_BINDTYPE_PLAYER12, DKEY_CIRCLE },
35   { SDLK_s,      IN_BINDTYPE_PLAYER12, DKEY_SQUARE },
36   { SDLK_v,      IN_BINDTYPE_PLAYER12, DKEY_START },
37   { SDLK_c,      IN_BINDTYPE_PLAYER12, DKEY_SELECT },
38   { SDLK_w,      IN_BINDTYPE_PLAYER12, DKEY_L1 },
39   { SDLK_r,      IN_BINDTYPE_PLAYER12, DKEY_R1 },
40   { SDLK_e,      IN_BINDTYPE_PLAYER12, DKEY_L2 },
41   { SDLK_t,      IN_BINDTYPE_PLAYER12, DKEY_R2 },
42   { SDLK_ESCAPE, IN_BINDTYPE_EMU, SACTION_ENTER_MENU },
43   { SDLK_F1,     IN_BINDTYPE_EMU, SACTION_SAVE_STATE },
44   { SDLK_F2,     IN_BINDTYPE_EMU, SACTION_LOAD_STATE },
45   { SDLK_F3,     IN_BINDTYPE_EMU, SACTION_PREV_SSLOT },
46   { SDLK_F4,     IN_BINDTYPE_EMU, SACTION_NEXT_SSLOT },
47   { SDLK_F5,     IN_BINDTYPE_EMU, SACTION_TOGGLE_FSKIP },
48   { SDLK_F6,     IN_BINDTYPE_EMU, SACTION_SCREENSHOT },
49   { SDLK_F7,     IN_BINDTYPE_EMU, SACTION_TOGGLE_FPS },
50   { SDLK_F8,     IN_BINDTYPE_EMU, SACTION_SWITCH_DISPMODE },
51   { SDLK_F11,    IN_BINDTYPE_EMU, SACTION_TOGGLE_FULLSCREEN },
52   { SDLK_BACKSPACE, IN_BINDTYPE_EMU, SACTION_FAST_FORWARD },
53   { 0, 0, 0 }
54 };
55
56 static int psx_w, psx_h;
57 static void *shadow_fb, *menubg_img;
58 static int in_menu;
59
60 static int change_video_mode(int force)
61 {
62   int w, h;
63
64   if (in_menu) {
65     w = g_menuscreen_w;
66     h = g_menuscreen_h;
67   }
68   else {
69     w = psx_w;
70     h = psx_h;
71   }
72
73   return plat_sdl_change_video_mode(w, h, force);
74 }
75
76 static void resize_cb(int w, int h)
77 {
78   // used by some plugins..
79   pl_rearmed_cbs.screen_w = w;
80   pl_rearmed_cbs.screen_h = h;
81   pl_rearmed_cbs.gles_display = gl_es_display;
82   pl_rearmed_cbs.gles_surface = gl_es_surface;
83   plugin_call_rearmed_cbs();
84 }
85
86 static void quit_cb(void)
87 {
88   emu_core_ask_exit();
89 }
90
91 static void get_layer_pos(int *x, int *y, int *w, int *h)
92 {
93   // always fill entire SDL window
94   *x = *y = 0;
95   *w = pl_rearmed_cbs.screen_w;
96   *h = pl_rearmed_cbs.screen_h;
97 }
98
99 void plat_init(void)
100 {
101   int ret;
102
103   plat_sdl_quit_cb = quit_cb;
104   plat_sdl_resize_cb = resize_cb;
105
106   ret = plat_sdl_init();
107   if (ret != 0)
108     exit(1);
109
110   in_menu = 1;
111   SDL_WM_SetCaption("PCSX-ReARMed " REV, NULL);
112
113   shadow_fb = malloc(640 * 512 * 2);
114   menubg_img = malloc(640 * 512 * 2);
115   if (shadow_fb == NULL || menubg_img == NULL) {
116     fprintf(stderr, "OOM\n");
117     exit(1);
118   }
119
120   in_sdl_init(in_sdl_defbinds, plat_sdl_event_handler);
121   in_probe();
122   pl_rearmed_cbs.only_16bpp = 1;
123   pl_rearmed_cbs.pl_get_layer_pos = get_layer_pos;
124
125   bgr_to_uyvy_init();
126 }
127
128 void plat_finish(void)
129 {
130   free(shadow_fb);
131   shadow_fb = NULL;
132   free(menubg_img);
133   menubg_img = NULL;
134   plat_sdl_finish();
135 }
136
137 void plat_gvideo_open(int is_pal)
138 {
139 }
140
141 static void uyvy_to_rgb565(void *d, const void *s, int pixels)
142 {
143   unsigned short *dst = d;
144   const unsigned int *src = s;
145   int v;
146
147   // no colors, for now
148   for (; pixels > 0; src++, dst += 2, pixels -= 2) {
149     v = (*src >> 8) & 0xff;
150     v = (v - 16) * 255 / 219 / 8;
151     dst[0] = (v << 11) | (v << 6) | v;
152
153     v = (*src >> 24) & 0xff;
154     v = (v - 16) * 255 / 219 / 8;
155     dst[1] = (v << 11) | (v << 6) | v;
156   }
157 }
158
159 static void overlay_blit(int doffs, const void *src_, int w, int h,
160                          int sstride, int bgr24)
161 {
162   const unsigned short *src = src_;
163   unsigned short *dst;
164   int dstride = plat_sdl_overlay->w;
165
166   SDL_LockYUVOverlay(plat_sdl_overlay);
167   dst = (void *)plat_sdl_overlay->pixels[0];
168
169   dst += doffs;
170   if (bgr24) {
171     for (; h > 0; dst += dstride, src += sstride, h--)
172       bgr888_to_uyvy(dst, src, w);
173   }
174   else {
175     for (; h > 0; dst += dstride, src += sstride, h--)
176       bgr555_to_uyvy(dst, src, w);
177   }
178
179   SDL_UnlockYUVOverlay(plat_sdl_overlay);
180 }
181
182 static void overlay_hud_print(int x, int y, const char *str, int bpp)
183 {
184   SDL_LockYUVOverlay(plat_sdl_overlay);
185   basic_text_out_uyvy_nf(plat_sdl_overlay->pixels[0], plat_sdl_overlay->w, x, y, str);
186   SDL_UnlockYUVOverlay(plat_sdl_overlay);
187 }
188
189 void *plat_gvideo_set_mode(int *w, int *h, int *bpp)
190 {
191   psx_w = *w;
192   psx_h = *h;
193   change_video_mode(0);
194   if (plat_sdl_overlay != NULL) {
195     pl_plat_clear = plat_sdl_overlay_clear;
196     pl_plat_blit = overlay_blit;
197     pl_plat_hud_print = overlay_hud_print;
198     return NULL;
199   }
200   else {
201     pl_plat_clear = NULL;
202     pl_plat_blit = NULL;
203     pl_plat_hud_print = NULL;
204     if (plat_sdl_gl_active)
205       return shadow_fb;
206     else
207       return plat_sdl_screen->pixels;
208   }
209 }
210
211 void *plat_gvideo_flip(void)
212 {
213   if (plat_sdl_overlay != NULL) {
214     SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
215     SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
216     return NULL;
217   }
218   else if (plat_sdl_gl_active) {
219     gl_flip(shadow_fb, psx_w, psx_h);
220     return shadow_fb;
221   }
222   else {
223     // XXX: no locking, but should be fine with SDL_SWSURFACE?
224     SDL_Flip(plat_sdl_screen);
225     return plat_sdl_screen->pixels;
226   }
227 }
228
229 void plat_gvideo_close(void)
230 {
231 }
232
233 void plat_video_menu_enter(int is_rom_loaded)
234 {
235   int force_mode_change = 0;
236
237   in_menu = 1;
238
239   /* surface will be lost, must adjust pl_vout_buf for menu bg */
240   if (plat_sdl_overlay != NULL)
241     uyvy_to_rgb565(menubg_img, plat_sdl_overlay->pixels[0], psx_w * psx_h);
242   else if (plat_sdl_gl_active)
243     memcpy(menubg_img, shadow_fb, psx_w * psx_h * 2);
244   else
245     memcpy(menubg_img, plat_sdl_screen->pixels, psx_w * psx_h * 2);
246   pl_vout_buf = menubg_img;
247
248   /* gles plugin messes stuff up.. */
249   if (pl_rearmed_cbs.gpu_caps & GPU_CAP_OWNS_DISPLAY)
250     force_mode_change = 1;
251
252   change_video_mode(force_mode_change);
253 }
254
255 void plat_video_menu_begin(void)
256 {
257   if (plat_sdl_overlay != NULL || plat_sdl_gl_active) {
258     g_menuscreen_ptr = shadow_fb;
259   }
260   else {
261     SDL_LockSurface(plat_sdl_screen);
262     g_menuscreen_ptr = plat_sdl_screen->pixels;
263   }
264 }
265
266 void plat_video_menu_end(void)
267 {
268   if (plat_sdl_overlay != NULL) {
269     SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
270
271     SDL_LockYUVOverlay(plat_sdl_overlay);
272     rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
273       g_menuscreen_w * g_menuscreen_h);
274     SDL_UnlockYUVOverlay(plat_sdl_overlay);
275
276     SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
277   }
278   else if (plat_sdl_gl_active) {
279     gl_flip(g_menuscreen_ptr, g_menuscreen_w, g_menuscreen_h);
280   }
281   else {
282     SDL_UnlockSurface(plat_sdl_screen);
283     SDL_Flip(plat_sdl_screen);
284   }
285   g_menuscreen_ptr = NULL;
286 }
287
288 void plat_video_menu_leave(void)
289 {
290   in_menu = 0;
291 }
292
293 /* unused stuff */
294 void *plat_prepare_screenshot(int *w, int *h, int *bpp)
295 {
296   return 0;
297 }
298
299 void plat_trigger_vibrate(int is_strong)
300 {
301 }
302
303 void plat_minimize(void)
304 {
305 }
306
307 // vim:shiftwidth=2:expandtab