frontend: update libpicofe, fix missed callbacks
[pcsx_rearmed.git] / frontend / plat_sdl.c
CommitLineData
7badc935 1/*
418caf43 2 * (C) GraÅžvydas "notaz" Ignotas, 2011-2013
7badc935 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>
81023939 12#include <assert.h>
7badc935 13#include <SDL.h>
cc56203b 14
c9b09029 15#include "../libpcsxcore/plugins.h"
cc56203b 16#include "libpicofe/input.h"
17#include "libpicofe/in_sdl.h"
18#include "libpicofe/menu.h"
c9099d02 19#include "libpicofe/fonts.h"
5b9aa749 20#include "libpicofe/plat_sdl.h"
81023939 21#include "libpicofe/plat.h"
5b9aa749 22#include "libpicofe/gl.h"
c82f907a 23#include "cspace.h"
b07c18e8 24#include "plugin_lib.h"
418caf43 25#include "plugin.h"
81023939 26#include "menu.h"
b07c18e8 27#include "main.h"
7badc935 28#include "plat.h"
29#include "revision.h"
30
81023939 31#include "libpicofe/plat_sdl.c"
32
b07c18e8 33static const struct in_default_bind in_sdl_defbinds[] = {
2e6189bc 34 { SDLK_UP, IN_BINDTYPE_PLAYER12, DKEY_UP },
35 { SDLK_DOWN, IN_BINDTYPE_PLAYER12, DKEY_DOWN },
36 { SDLK_LEFT, IN_BINDTYPE_PLAYER12, DKEY_LEFT },
37 { SDLK_RIGHT, IN_BINDTYPE_PLAYER12, DKEY_RIGHT },
38 { SDLK_d, IN_BINDTYPE_PLAYER12, DKEY_TRIANGLE },
39 { SDLK_z, IN_BINDTYPE_PLAYER12, DKEY_CROSS },
40 { SDLK_x, IN_BINDTYPE_PLAYER12, DKEY_CIRCLE },
41 { SDLK_s, IN_BINDTYPE_PLAYER12, DKEY_SQUARE },
42 { SDLK_v, IN_BINDTYPE_PLAYER12, DKEY_START },
43 { SDLK_c, IN_BINDTYPE_PLAYER12, DKEY_SELECT },
44 { SDLK_w, IN_BINDTYPE_PLAYER12, DKEY_L1 },
45 { SDLK_r, IN_BINDTYPE_PLAYER12, DKEY_R1 },
46 { SDLK_e, IN_BINDTYPE_PLAYER12, DKEY_L2 },
47 { SDLK_t, IN_BINDTYPE_PLAYER12, DKEY_R2 },
48 { SDLK_ESCAPE, IN_BINDTYPE_EMU, SACTION_ENTER_MENU },
456f1b86 49 { SDLK_F1, IN_BINDTYPE_EMU, SACTION_SAVE_STATE },
50 { SDLK_F2, IN_BINDTYPE_EMU, SACTION_LOAD_STATE },
51 { SDLK_F3, IN_BINDTYPE_EMU, SACTION_PREV_SSLOT },
52 { SDLK_F4, IN_BINDTYPE_EMU, SACTION_NEXT_SSLOT },
53 { SDLK_F5, IN_BINDTYPE_EMU, SACTION_TOGGLE_FSKIP },
54 { SDLK_F6, IN_BINDTYPE_EMU, SACTION_SCREENSHOT },
dde7da71 55 { SDLK_F7, IN_BINDTYPE_EMU, SACTION_TOGGLE_FPS },
456f1b86 56 { SDLK_F8, IN_BINDTYPE_EMU, SACTION_SWITCH_DISPMODE },
a8376201 57 { SDLK_F11, IN_BINDTYPE_EMU, SACTION_TOGGLE_FULLSCREEN },
dde7da71 58 { SDLK_BACKSPACE, IN_BINDTYPE_EMU, SACTION_FAST_FORWARD },
2e6189bc 59 { 0, 0, 0 }
7badc935 60};
61
bcfc48e3 62const struct menu_keymap in_sdl_key_map[] =
63{
64 { SDLK_UP, PBTN_UP },
65 { SDLK_DOWN, PBTN_DOWN },
66 { SDLK_LEFT, PBTN_LEFT },
67 { SDLK_RIGHT, PBTN_RIGHT },
68 { SDLK_RETURN, PBTN_MOK },
69 { SDLK_ESCAPE, PBTN_MBACK },
70 { SDLK_SEMICOLON, PBTN_MA2 },
71 { SDLK_QUOTE, PBTN_MA3 },
72 { SDLK_LEFTBRACKET, PBTN_L },
73 { SDLK_RIGHTBRACKET, PBTN_R },
74};
75
76const struct menu_keymap in_sdl_joy_map[] =
77{
78 { SDLK_UP, PBTN_UP },
79 { SDLK_DOWN, PBTN_DOWN },
80 { SDLK_LEFT, PBTN_LEFT },
81 { SDLK_RIGHT, PBTN_RIGHT },
82 /* joystick */
83 { SDLK_WORLD_0, PBTN_MOK },
84 { SDLK_WORLD_1, PBTN_MBACK },
85 { SDLK_WORLD_2, PBTN_MA2 },
86 { SDLK_WORLD_3, PBTN_MA3 },
87};
88
89static const struct in_pdata in_sdl_platform_data = {
90 .defbinds = in_sdl_defbinds,
91 .key_map = in_sdl_key_map,
92 .kmap_size = sizeof(in_sdl_key_map) / sizeof(in_sdl_key_map[0]),
93 .joy_map = in_sdl_joy_map,
94 .jmap_size = sizeof(in_sdl_joy_map) / sizeof(in_sdl_joy_map[0]),
95};
96
3a52f747 97static int psx_w = 256, psx_h = 240;
5b9aa749 98static void *shadow_fb, *menubg_img;
81023939 99static int vout_fullscreen_old;
100static int forced_clears;
101static int forced_flips;
102static int sdl12_compat;
c9b09029 103static int resized;
5b9aa749 104static int in_menu;
7badc935 105
7192adbe 106static int gl_w_prev, gl_h_prev, gl_quirks_prev;
c9b09029 107static float gl_vertices[] = {
108 -1.0f, 1.0f, 0.0f, // 0 0 1
109 1.0f, 1.0f, 0.0f, // 1 ^
110 -1.0f, -1.0f, 0.0f, // 2 | 2 3
111 1.0f, -1.0f, 0.0f, // 3 +-->
112};
113
114static void handle_window_resize(void);
81023939 115static void handle_scaler_resize(int w, int h);
3a52f747 116static void centered_clear(void);
418caf43 117
c9b09029 118static int plugin_owns_display(void)
119{
120 // if true, a plugin is drawing and flipping
121 return (pl_rearmed_cbs.gpu_caps & GPU_CAP_OWNS_DISPLAY);
122}
123
124static void plugin_update(void)
418caf43 125{
81023939 126 // used by some plugins...
c9b09029 127 pl_rearmed_cbs.screen_w = plat_sdl_screen->w;
128 pl_rearmed_cbs.screen_h = plat_sdl_screen->h;
418caf43 129 pl_rearmed_cbs.gles_display = gl_es_display;
130 pl_rearmed_cbs.gles_surface = gl_es_surface;
131 plugin_call_rearmed_cbs();
81023939 132}
133
134static void sdl_event_handler(void *event_)
135{
136 SDL_Event *event = event_;
137
138 switch (event->type) {
139 case SDL_VIDEORESIZE:
140 if (window_w != (event->resize.w & ~3) || window_h != (event->resize.h & ~1)) {
141 window_w = event->resize.w & ~3;
142 window_h = event->resize.h & ~1;
143 resized = 1;
c9b09029 144 if (!in_menu && plat_sdl_gl_active && plugin_owns_display()) {
145 // the plugin flips by itself so resize has to be handled here
146 handle_window_resize();
147 if (GPU_open != NULL) {
148 int ret = GPU_open(&gpuDisp, "PCSX", NULL);
149 if (ret)
150 fprintf(stderr, "GPU_open: %d\n", ret);
151 }
152 }
81023939 153 }
154 return;
155 case SDL_ACTIVEEVENT:
156 // no need to redraw?
157 return;
158 default:
159 break;
160 }
161 plat_sdl_event_handler(event_);
a8376201 162}
163
69e482e3 164static void quit_cb(void)
165{
166 emu_core_ask_exit();
167}
168
418caf43 169static void get_layer_pos(int *x, int *y, int *w, int *h)
170{
171 // always fill entire SDL window
172 *x = *y = 0;
173 *w = pl_rearmed_cbs.screen_w;
174 *h = pl_rearmed_cbs.screen_h;
175}
176
7badc935 177void plat_init(void)
178{
7192adbe 179 static const char *hwfilters[] = { "linear", "nearest", NULL };
81023939 180 const SDL_version *ver;
8e7632dd 181 int shadow_size;
5b9aa749 182 int ret;
7badc935 183
418caf43 184 plat_sdl_quit_cb = quit_cb;
418caf43 185
7192adbe 186 old_fullscreen = -1; // hack
187
5b9aa749 188 ret = plat_sdl_init();
189 if (ret != 0)
7badc935 190 exit(1);
a8376201 191
81023939 192 ver = SDL_Linked_Version();
193 sdl12_compat = ver->patch >= 50;
194 printf("SDL %u.%u.%u compat=%d\n", ver->major, ver->minor, ver->patch, sdl12_compat);
195
a8376201 196 in_menu = 1;
7badc935 197 SDL_WM_SetCaption("PCSX-ReARMed " REV, NULL);
198
8e7632dd 199 shadow_size = g_menuscreen_w * g_menuscreen_h * 2;
af486d6e 200 // alloc enough for double res. rendering
201 if (shadow_size < 1024 * 512 * 2)
202 shadow_size = 1024 * 512 * 2;
8e7632dd 203
204 shadow_fb = malloc(shadow_size);
205 menubg_img = malloc(shadow_size);
5b9aa749 206 if (shadow_fb == NULL || menubg_img == NULL) {
207 fprintf(stderr, "OOM\n");
208 exit(1);
209 }
2e6189bc 210
81023939 211 in_sdl_init(&in_sdl_platform_data, sdl_event_handler);
7badc935 212 in_probe();
4ea7de6a 213 pl_rearmed_cbs.only_16bpp = 1;
418caf43 214 pl_rearmed_cbs.pl_get_layer_pos = get_layer_pos;
c9099d02 215
216 bgr_to_uyvy_init();
81023939 217
c9b09029 218 assert(plat_sdl_screen);
219 plugin_update();
220 if (plat_target.vout_method == vout_mode_gl)
221 gl_w_prev = plat_sdl_screen->w, gl_h_prev = plat_sdl_screen->h;
7192adbe 222 if (vout_mode_gl != -1)
223 plat_target.hwfilters = hwfilters;
7badc935 224}
225
226void plat_finish(void)
227{
5b9aa749 228 free(shadow_fb);
229 shadow_fb = NULL;
2e6189bc 230 free(menubg_img);
231 menubg_img = NULL;
5b9aa749 232 plat_sdl_finish();
7badc935 233}
234
ab423939 235void plat_gvideo_open(int is_pal)
7badc935 236{
237}
238
81023939 239static void uyvy_to_rgb565(void *d, int pixels)
7badc935 240{
81023939 241 const unsigned int *src = (const void *)plat_sdl_overlay->pixels[0];
242 int x2 = plat_sdl_overlay->w >= psx_w * 2;
c9099d02 243 unsigned short *dst = d;
c9099d02 244 int v;
245
246 // no colors, for now
81023939 247 if (x2) {
248 for (; pixels > 0; src++, dst++, pixels--) {
249 v = (*src >> 8) & 0xff;
250 v = (v - 16) * 255 / 219 / 8;
251 *dst = (v << 11) | (v << 6) | v;
252 }
253 }
254 else {
255 for (; pixels > 0; src++, dst += 2, pixels -= 2) {
256 v = (*src >> 8) & 0xff;
257 v = (v - 16) * 255 / 219 / 8;
258 dst[0] = (v << 11) | (v << 6) | v;
259
260 v = (*src >> 24) & 0xff;
261 v = (v - 16) * 255 / 219 / 8;
262 dst[1] = (v << 11) | (v << 6) | v;
263 }
264 }
265}
266
267static void overlay_resize(int force)
268{
269 int x2_mul = !in_menu && plat_target.vout_method > 1 ? 2 : 1; // lame
270 int w = in_menu ? g_menuscreen_w : psx_w;
271 int h = in_menu ? g_menuscreen_h : psx_h;
272
273 if (!force && plat_sdl_overlay && w * x2_mul == plat_sdl_overlay->w
274 && h == plat_sdl_overlay->h)
275 return;
276 if (plat_sdl_overlay)
277 SDL_FreeYUVOverlay(plat_sdl_overlay);
278 plat_sdl_overlay = SDL_CreateYUVOverlay(w * x2_mul, h, SDL_UYVY_OVERLAY,
279 plat_sdl_screen);
280 if (plat_sdl_overlay) {
281 //printf("overlay: %dx%d %08x hw=%d\n", plat_sdl_overlay->w, plat_sdl_overlay->h,
282 // plat_sdl_overlay->format, plat_sdl_overlay->hw_overlay);
283 if (SDL_LockYUVOverlay(plat_sdl_overlay) == 0) {
284 plat_sdl_overlay_clear();
285 SDL_UnlockYUVOverlay(plat_sdl_overlay);
286 }
287 }
c9b09029 288 else {
81023939 289 fprintf(stderr, "overlay resize to %dx%d failed\n", w, h);
c9b09029 290 plat_target.vout_method = 0;
c9099d02 291 }
c9b09029 292 handle_scaler_resize(w, h);
7badc935 293}
294
c9099d02 295static void overlay_blit(int doffs, const void *src_, int w, int h,
296 int sstride, int bgr24)
297{
298 const unsigned short *src = src_;
299 unsigned short *dst;
5b9aa749 300 int dstride = plat_sdl_overlay->w;
81023939 301 int x2 = dstride >= 2 * w;
c9099d02 302
5b9aa749 303 SDL_LockYUVOverlay(plat_sdl_overlay);
304 dst = (void *)plat_sdl_overlay->pixels[0];
c9099d02 305
306 dst += doffs;
307 if (bgr24) {
308 for (; h > 0; dst += dstride, src += sstride, h--)
81023939 309 bgr888_to_uyvy(dst, src, w, x2);
c9099d02 310 }
311 else {
312 for (; h > 0; dst += dstride, src += sstride, h--)
81023939 313 bgr555_to_uyvy(dst, src, w, x2);
c9099d02 314 }
315
5b9aa749 316 SDL_UnlockYUVOverlay(plat_sdl_overlay);
c9099d02 317}
318
319static void overlay_hud_print(int x, int y, const char *str, int bpp)
320{
81023939 321 int x2;
5b9aa749 322 SDL_LockYUVOverlay(plat_sdl_overlay);
81023939 323 x2 = plat_sdl_overlay->w >= psx_w * 2;
324 if (x2)
325 x *= 2;
5b9aa749 326 basic_text_out_uyvy_nf(plat_sdl_overlay->pixels[0], plat_sdl_overlay->w, x, y, str);
327 SDL_UnlockYUVOverlay(plat_sdl_overlay);
c9099d02 328}
329
c9b09029 330static void gl_finish_pl(void)
331{
332 if (plugin_owns_display() && GPU_close != NULL)
333 GPU_close();
86e02a02 334 gl_destroy();
c9b09029 335}
336
337static void gl_resize(void)
338{
339 int w = in_menu ? g_menuscreen_w : psx_w;
340 int h = in_menu ? g_menuscreen_h : psx_h;
341
7192adbe 342 gl_quirks &= ~(GL_QUIRK_SCALING_NEAREST | GL_QUIRK_VSYNC_ON);
343 if (plat_target.hwfilter) // inverted from plat_sdl_gl_scaling()
344 gl_quirks |= GL_QUIRK_SCALING_NEAREST;
345 if (g_opts & OPT_VSYNC)
346 gl_quirks |= GL_QUIRK_VSYNC_ON;
347
c9b09029 348 if (plugin_owns_display())
349 w = plat_sdl_screen->w, h = plat_sdl_screen->h;
350 if (plat_sdl_gl_active) {
7192adbe 351 if (w == gl_w_prev && h == gl_h_prev && gl_quirks == gl_quirks_prev)
c9b09029 352 return;
353 gl_finish_pl();
354 }
86e02a02 355 plat_sdl_gl_active = (gl_create(window, &gl_quirks, w, h) == 0);
c9b09029 356 if (plat_sdl_gl_active)
7192adbe 357 gl_w_prev = w, gl_h_prev = h, gl_quirks_prev = gl_quirks;
c9b09029 358 else {
359 fprintf(stderr, "warning: could not init GL.\n");
360 plat_target.vout_method = 0;
361 }
362 handle_scaler_resize(w, h);
363 plugin_update();
364 forced_flips = 0; // interferes with gl
365}
366
367static void overlay_or_gl_check_enable(void)
368{
369 int ovl_on = plat_target.vout_method == vout_mode_overlay ||
370 plat_target.vout_method == vout_mode_overlay2x;
371 int gl_on = plat_target.vout_method == vout_mode_gl;
372 if (!gl_on && plat_sdl_gl_active) {
373 gl_finish_pl();
374 pl_rearmed_cbs.gles_display = gl_es_display;
375 pl_rearmed_cbs.gles_surface = gl_es_surface;
376 plat_sdl_gl_active = 0;
377 }
378 if (!ovl_on && plat_sdl_overlay) {
379 SDL_FreeYUVOverlay(plat_sdl_overlay);
380 plat_sdl_overlay = NULL;
381 }
382 if (ovl_on)
383 overlay_resize(0);
384 else if (gl_on)
385 gl_resize();
386}
387
3a52f747 388static void centered_clear(void)
c9099d02 389{
3a52f747 390 int dstride = plat_sdl_screen->pitch / 2;
391 int w = plat_sdl_screen->w;
392 int h = plat_sdl_screen->h;
393 unsigned short *dst;
394
c9b09029 395 if (plat_sdl_gl_active) {
396 gl_clear();
397 return;
398 }
399
81023939 400 if (SDL_MUSTLOCK(plat_sdl_screen))
401 SDL_LockSurface(plat_sdl_screen);
3a52f747 402 dst = plat_sdl_screen->pixels;
403
404 for (; h > 0; dst += dstride, h--)
405 memset(dst, 0, w * 2);
406
81023939 407 if (SDL_MUSTLOCK(plat_sdl_screen))
408 SDL_UnlockSurface(plat_sdl_screen);
409
410 if (plat_sdl_overlay != NULL) {
411 // apply the parts not covered by the overlay
412 forced_flips = 3;
413 }
414}
415
416static int adj_src_dst(const SDL_Surface *sfc, int w, int pp, int *h,
417 unsigned short **dst, const unsigned short **src)
418{
419 int line_w = w;
420 if (sfc->w > w)
421 *dst += (sfc->w - w) / 2;
422 else {
423 *src += (w - sfc->w) / 2;
424 line_w = sfc->w;
425 }
426 if (sfc->h > *h)
427 *dst += sfc->pitch * (sfc->h - *h) / 2 / 2;
428 else {
429 *src += pp * (*h - sfc->h) / 2;
430 *h = sfc->h;
431 }
432 return line_w;
3a52f747 433}
434
435static void centered_blit(int doffs, const void *src_, int w, int h,
436 int sstride, int bgr24)
437{
438 const unsigned short *src = src_;
439 unsigned short *dst;
440 int dstride;
441
81023939 442 if (SDL_MUSTLOCK(plat_sdl_screen))
443 SDL_LockSurface(plat_sdl_screen);
3a52f747 444 dst = plat_sdl_screen->pixels;
445 dstride = plat_sdl_screen->pitch / 2;
81023939 446 w = adj_src_dst(plat_sdl_screen, w, sstride, &h, &dst, &src);
3a52f747 447
3a52f747 448 if (bgr24) {
449 for (; h > 0; dst += dstride, src += sstride, h--)
450 bgr888_to_rgb565(dst, src, w * 3);
451 }
452 else {
453 for (; h > 0; dst += dstride, src += sstride, h--)
454 bgr555_to_rgb565(dst, src, w * 2);
455 }
456
81023939 457 if (SDL_MUSTLOCK(plat_sdl_screen))
458 SDL_UnlockSurface(plat_sdl_screen);
3a52f747 459}
460
461static void centered_blit_menu(void)
462{
463 const unsigned short *src = g_menuscreen_ptr;
464 int w = g_menuscreen_w;
465 int h = g_menuscreen_h;
466 unsigned short *dst;
81023939 467 int dstride, len;
468
469 if (SDL_MUSTLOCK(plat_sdl_screen))
470 SDL_LockSurface(plat_sdl_screen);
3a52f747 471
3a52f747 472 dst = plat_sdl_screen->pixels;
473 dstride = plat_sdl_screen->pitch / 2;
81023939 474 len = adj_src_dst(plat_sdl_screen, w, g_menuscreen_pp, &h, &dst, &src);
3a52f747 475
3a52f747 476 for (; h > 0; dst += dstride, src += g_menuscreen_pp, h--)
81023939 477 memcpy(dst, src, len * 2);
3a52f747 478
81023939 479 if (SDL_MUSTLOCK(plat_sdl_screen))
480 SDL_UnlockSurface(plat_sdl_screen);
3a52f747 481}
482
483static void centered_hud_print(int x, int y, const char *str, int bpp)
484{
81023939 485 int w_diff, h_diff;
486 if (SDL_MUSTLOCK(plat_sdl_screen))
487 SDL_LockSurface(plat_sdl_screen);
488 w_diff = plat_sdl_screen->w - psx_w;
489 h_diff = plat_sdl_screen->h - psx_h;
490 if (w_diff > 0) x += w_diff / 2;
491 if (h_diff > 0) y += h_diff / 2;
492 if (h_diff < 0) y += h_diff;
493 if (w_diff < 0 && x > 32) x += w_diff;
3a52f747 494 basic_text_out16_nf(plat_sdl_screen->pixels, plat_sdl_screen->pitch / 2, x, y, str);
81023939 495 if (SDL_MUSTLOCK(plat_sdl_screen))
496 SDL_UnlockSurface(plat_sdl_screen);
3a52f747 497}
498
81023939 499static void *setup_blit_callbacks(int w, int h)
3a52f747 500{
501 pl_plat_clear = NULL;
502 pl_plat_blit = NULL;
503 pl_plat_hud_print = NULL;
5b9aa749 504 if (plat_sdl_overlay != NULL) {
505 pl_plat_clear = plat_sdl_overlay_clear;
c9099d02 506 pl_plat_blit = overlay_blit;
507 pl_plat_hud_print = overlay_hud_print;
3a52f747 508 }
509 else if (plat_sdl_gl_active) {
510 return shadow_fb;
c9099d02 511 }
512 else {
81023939 513 pl_plat_clear = centered_clear;
514
515 if (!SDL_MUSTLOCK(plat_sdl_screen) && w == plat_sdl_screen->w &&
516 h == plat_sdl_screen->h)
5b9aa749 517 return plat_sdl_screen->pixels;
81023939 518
519 pl_plat_blit = centered_blit;
520 pl_plat_hud_print = centered_hud_print;
521 }
522 return NULL;
523}
524
525// not using plat_sdl_change_video_mode() since we need
526// different size overlay vs plat_sdl_screen layer
527static void change_mode(int w, int h)
528{
c9b09029 529 int set_w = w, set_h = h, had_overlay = 0, had_gl = 0;
81023939 530 if (plat_target.vout_fullscreen && (plat_target.vout_method != 0 || !sdl12_compat))
531 set_w = fs_w, set_h = fs_h;
532 if (plat_sdl_screen->w != set_w || plat_sdl_screen->h != set_h ||
533 plat_target.vout_fullscreen != vout_fullscreen_old)
534 {
535 Uint32 flags = plat_sdl_screen->flags;
536 if (plat_target.vout_fullscreen)
537 flags |= SDL_FULLSCREEN;
3a52f747 538 else {
81023939 539 flags &= ~SDL_FULLSCREEN;
540 if (plat_sdl_is_windowed())
541 flags |= SDL_RESIZABLE; // sdl12-compat 1.2.68 loses this flag
542 }
543 if (plat_sdl_overlay) {
544 SDL_FreeYUVOverlay(plat_sdl_overlay);
545 plat_sdl_overlay = NULL;
546 had_overlay = 1;
3a52f747 547 }
c9b09029 548 if (plat_sdl_gl_active) {
549 gl_finish_pl();
550 plat_sdl_gl_active = 0;
551 had_gl = 1;
552 }
81023939 553 SDL_PumpEvents();
554 plat_sdl_screen = SDL_SetVideoMode(set_w, set_h, 16, flags);
555 //printf("mode: %dx%d %x -> %dx%d\n", set_w, set_h, flags,
556 // plat_sdl_screen->w, plat_sdl_screen->h);
557 assert(plat_sdl_screen);
558 if (vout_fullscreen_old && !plat_target.vout_fullscreen)
559 // why is this needed?? (on 1.2.68)
560 SDL_WM_GrabInput(SDL_GRAB_OFF);
c9b09029 561 if (vout_mode_gl != -1)
562 update_wm_display_window();
81023939 563 // overlay needs the latest plat_sdl_screen
564 if (had_overlay)
565 overlay_resize(1);
c9b09029 566 if (had_gl)
567 gl_resize();
81023939 568 centered_clear();
c9b09029 569 plugin_update();
81023939 570 vout_fullscreen_old = plat_target.vout_fullscreen;
571 }
572}
573
574static void handle_scaler_resize(int w, int h)
575{
576 int ww = plat_sdl_screen->w;
577 int wh = plat_sdl_screen->h;
578 int layer_w_old = g_layer_w;
579 int layer_h_old = g_layer_h;
c9b09029 580 float w_mul, h_mul;
581 int x, y;
81023939 582 pl_update_layer_size(w, h, ww, wh);
583 if (layer_w_old != g_layer_w || layer_h_old != g_layer_h)
584 forced_clears = 3;
c9b09029 585
586 w_mul = 2.0f / ww;
587 h_mul = 2.0f / wh;
588 x = (ww - g_layer_w) / 2;
589 y = (wh - g_layer_h) / 2;
590 gl_vertices[3*0+0] = gl_vertices[3*2+0] = -1.0f + x * w_mul;
591 gl_vertices[3*1+0] = gl_vertices[3*3+0] = -1.0f + (x + g_layer_w) * w_mul;
592 gl_vertices[3*2+1] = gl_vertices[3*3+1] = -1.0f + y * h_mul;
593 gl_vertices[3*0+1] = gl_vertices[3*1+1] = -1.0f + (y + g_layer_h) * h_mul;
81023939 594}
595
596static void handle_window_resize(void)
597{
598 // sdl12-compat: a hack to take advantage of sdl2 scaling
599 if (resized && (plat_target.vout_method != 0 || !sdl12_compat)) {
600 change_mode(window_w, window_h);
601 setup_blit_callbacks(psx_w, psx_h);
602 forced_clears = 3;
a8376201 603 }
c9b09029 604 resized = 0;
3a52f747 605}
606
607void *plat_gvideo_set_mode(int *w, int *h, int *bpp)
608{
609 psx_w = *w;
610 psx_h = *h;
81023939 611
c9b09029 612 if (plat_sdl_gl_active && plugin_owns_display())
613 return NULL;
614
81023939 615 if (plat_sdl_overlay != NULL)
616 overlay_resize(0);
c9b09029 617 else if (plat_sdl_gl_active) {
81023939 618 memset(shadow_fb, 0, (*w) * (*h) * 2);
c9b09029 619 gl_resize();
620 }
81023939 621 else if (plat_target.vout_method == 0) // && sdl12_compat
622 change_mode(*w, *h);
623
624 handle_scaler_resize(*w, *h); // override the value from pl_vout_set_mode()
625 return setup_blit_callbacks(*w, *h);
a8376201 626}
627
7badc935 628void *plat_gvideo_flip(void)
629{
81023939 630 void *ret = NULL;
631 int do_flip = 0;
5b9aa749 632 if (plat_sdl_overlay != NULL) {
81023939 633 SDL_Rect dstrect = {
634 (plat_sdl_screen->w - g_layer_w) / 2,
635 (plat_sdl_screen->h - g_layer_h) / 2,
636 g_layer_w, g_layer_h
637 };
5b9aa749 638 SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
a8376201 639 }
5b9aa749 640 else if (plat_sdl_gl_active) {
c9b09029 641 gl_flip_v(shadow_fb, psx_w, psx_h, g_scaler != SCALE_FULLSCREEN ? gl_vertices : NULL);
81023939 642 ret = shadow_fb;
5b9aa749 643 }
81023939 644 else
645 do_flip |= 2;
646
647 if (forced_flips > 0) {
648 forced_flips--;
649 do_flip |= 1;
650 }
651 if (do_flip)
5b9aa749 652 SDL_Flip(plat_sdl_screen);
81023939 653 handle_window_resize();
654 if (do_flip) {
655 if (forced_clears > 0) {
656 forced_clears--;
657 centered_clear();
658 }
659 if (!SDL_MUSTLOCK(plat_sdl_screen) && plat_sdl_screen->w == psx_w &&
660 plat_sdl_screen->h == psx_h && (do_flip & 2)) {
661 ret = plat_sdl_screen->pixels;
662 }
a8376201 663 }
81023939 664 assert(ret || pl_plat_clear != NULL);
665 return ret;
7badc935 666}
667
668void plat_gvideo_close(void)
669{
670}
671
672void plat_video_menu_enter(int is_rom_loaded)
673{
3a998763 674 int d;
675
a8376201 676 in_menu = 1;
677
2e6189bc 678 /* surface will be lost, must adjust pl_vout_buf for menu bg */
5b9aa749 679 if (plat_sdl_overlay != NULL)
81023939 680 uyvy_to_rgb565(menubg_img, psx_w * psx_h);
5b9aa749 681 else if (plat_sdl_gl_active)
682 memcpy(menubg_img, shadow_fb, psx_w * psx_h * 2);
81023939 683 else {
684 unsigned short *dst = menubg_img;
685 const unsigned short *src;
686 int h;
687 if (SDL_MUSTLOCK(plat_sdl_screen))
688 SDL_LockSurface(plat_sdl_screen);
689 src = plat_sdl_screen->pixels;
690 src += (plat_sdl_screen->w - psx_w) / 2;
691 src += plat_sdl_screen->pitch * (plat_sdl_screen->h - psx_h) / 2 / 2;
692 for (h = psx_h; h > 0; dst += psx_w, src += plat_sdl_screen->pitch / 2, h--)
693 memcpy(dst, src, psx_w * 2);
694 if (SDL_MUSTLOCK(plat_sdl_screen))
695 SDL_UnlockSurface(plat_sdl_screen);
696 }
2e6189bc 697 pl_vout_buf = menubg_img;
698
81023939 699 if (plat_target.vout_method == 0)
700 change_mode(g_menuscreen_w, g_menuscreen_h);
701 else
c9b09029 702 overlay_or_gl_check_enable();
81023939 703 centered_clear();
3a998763 704
705 for (d = 0; d < IN_MAX_DEVS; d++)
706 in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 1);
7badc935 707}
708
709void plat_video_menu_begin(void)
710{
81023939 711 void *old_ovl = plat_sdl_overlay;
712 static int g_scaler_old;
713 int scaler_changed = g_scaler_old != g_scaler;
714 g_scaler_old = g_scaler;
715 if (plat_target.vout_fullscreen != vout_fullscreen_old ||
716 (plat_target.vout_fullscreen && scaler_changed)) {
717 change_mode(g_menuscreen_w, g_menuscreen_h);
718 }
7192adbe 719 overlay_or_gl_check_enable();
81023939 720 handle_scaler_resize(g_menuscreen_w, g_menuscreen_h);
721
722 if (old_ovl != plat_sdl_overlay || scaler_changed)
723 centered_clear();
3a52f747 724 g_menuscreen_ptr = shadow_fb;
7badc935 725}
726
727void plat_video_menu_end(void)
728{
81023939 729 int do_flip = 0;
730
5b9aa749 731 if (plat_sdl_overlay != NULL) {
81023939 732 SDL_Rect dstrect = {
733 (plat_sdl_screen->w - g_layer_w) / 2,
734 (plat_sdl_screen->h - g_layer_h) / 2,
735 g_layer_w, g_layer_h
736 };
5b9aa749 737
738 SDL_LockYUVOverlay(plat_sdl_overlay);
739 rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
740 g_menuscreen_w * g_menuscreen_h);
741 SDL_UnlockYUVOverlay(plat_sdl_overlay);
742
743 SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
744 }
745 else if (plat_sdl_gl_active) {
c9b09029 746 gl_flip_v(g_menuscreen_ptr, g_menuscreen_w, g_menuscreen_h,
747 g_scaler != SCALE_FULLSCREEN ? gl_vertices : NULL);
5b9aa749 748 }
749 else {
3a52f747 750 centered_blit_menu();
81023939 751 do_flip |= 2;
5b9aa749 752 }
81023939 753
754 if (forced_flips > 0) {
755 forced_flips--;
756 do_flip |= 1;
757 }
758 if (do_flip)
759 SDL_Flip(plat_sdl_screen);
760
761 handle_window_resize();
7badc935 762 g_menuscreen_ptr = NULL;
763}
764
765void plat_video_menu_leave(void)
766{
3a998763 767 int d;
768
a8376201 769 in_menu = 0;
81023939 770 if (plat_sdl_overlay != NULL || plat_sdl_gl_active)
771 memset(shadow_fb, 0, g_menuscreen_w * g_menuscreen_h * 2);
772
773 if (plat_target.vout_fullscreen)
774 change_mode(fs_w, fs_h);
7192adbe 775 overlay_or_gl_check_enable();
81023939 776 centered_clear();
b2ba218e 777 setup_blit_callbacks(psx_w, psx_h);
3a998763 778
779 for (d = 0; d < IN_MAX_DEVS; d++)
780 in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 0);
7badc935 781}
782
7badc935 783void *plat_prepare_screenshot(int *w, int *h, int *bpp)
784{
1ae743b1 785 if (plat_sdl_screen && !SDL_MUSTLOCK(plat_sdl_screen) &&
786 plat_sdl_overlay == NULL && !plat_sdl_gl_active)
787 {
788 *w = plat_sdl_screen->pitch / 2;
789 *h = plat_sdl_screen->h;
790 *bpp = 16;
791 return plat_sdl_screen->pixels;
792 }
793 fprintf(stderr, "screenshot not implemented in current mode\n");
794 return NULL;
7badc935 795}
796
d71c7095 797void plat_trigger_vibrate(int pad, int low, int high)
7badc935 798{
799}
800
801void plat_minimize(void)
802{
803}
804
805// vim:shiftwidth=2:expandtab