*/
#include <stdio.h>
+#include <assert.h>
#include <SDL.h>
+#include "../libpcsxcore/plugins.h"
#include "libpicofe/input.h"
#include "libpicofe/in_sdl.h"
#include "libpicofe/menu.h"
#include "libpicofe/fonts.h"
#include "libpicofe/plat_sdl.h"
+#include "libpicofe/plat.h"
#include "libpicofe/gl.h"
-#include "../plugins/gpulib/cspace.h"
+#include "cspace.h"
#include "plugin_lib.h"
#include "plugin.h"
+#include "menu.h"
#include "main.h"
#include "plat.h"
#include "revision.h"
+#include "libpicofe/plat_sdl.c"
+
static const struct in_default_bind in_sdl_defbinds[] = {
{ SDLK_UP, IN_BINDTYPE_PLAYER12, DKEY_UP },
{ SDLK_DOWN, IN_BINDTYPE_PLAYER12, DKEY_DOWN },
{ 0, 0, 0 }
};
-static int psx_w, psx_h;
+const struct menu_keymap in_sdl_key_map[] =
+{
+ { SDLK_UP, PBTN_UP },
+ { SDLK_DOWN, PBTN_DOWN },
+ { SDLK_LEFT, PBTN_LEFT },
+ { SDLK_RIGHT, PBTN_RIGHT },
+ { SDLK_RETURN, PBTN_MOK },
+ { SDLK_ESCAPE, PBTN_MBACK },
+ { SDLK_SEMICOLON, PBTN_MA2 },
+ { SDLK_QUOTE, PBTN_MA3 },
+ { SDLK_LEFTBRACKET, PBTN_L },
+ { SDLK_RIGHTBRACKET, PBTN_R },
+};
+
+const struct menu_keymap in_sdl_joy_map[] =
+{
+ { SDLK_UP, PBTN_UP },
+ { SDLK_DOWN, PBTN_DOWN },
+ { SDLK_LEFT, PBTN_LEFT },
+ { SDLK_RIGHT, PBTN_RIGHT },
+ /* joystick */
+ { SDLK_WORLD_0, PBTN_MOK },
+ { SDLK_WORLD_1, PBTN_MBACK },
+ { SDLK_WORLD_2, PBTN_MA2 },
+ { SDLK_WORLD_3, PBTN_MA3 },
+};
+
+static const struct in_pdata in_sdl_platform_data = {
+ .defbinds = in_sdl_defbinds,
+ .key_map = in_sdl_key_map,
+ .kmap_size = sizeof(in_sdl_key_map) / sizeof(in_sdl_key_map[0]),
+ .joy_map = in_sdl_joy_map,
+ .jmap_size = sizeof(in_sdl_joy_map) / sizeof(in_sdl_joy_map[0]),
+};
+
+static int psx_w = 256, psx_h = 240;
static void *shadow_fb, *menubg_img;
+static int vout_fullscreen_old;
+static int forced_clears;
+static int forced_flips;
+static int sdl12_compat;
+static int resized;
static int in_menu;
-static int change_video_mode(int force)
-{
- int w, h;
+static int gl_w_prev, gl_h_prev, gl_quirks_prev;
+static float gl_vertices[] = {
+ -1.0f, 1.0f, 0.0f, // 0 0 1
+ 1.0f, 1.0f, 0.0f, // 1 ^
+ -1.0f, -1.0f, 0.0f, // 2 | 2 3
+ 1.0f, -1.0f, 0.0f, // 3 +-->
+};
- if (in_menu) {
- w = g_menuscreen_w;
- h = g_menuscreen_h;
- }
- else {
- w = psx_w;
- h = psx_h;
- }
+static void handle_window_resize(void);
+static void handle_scaler_resize(int w, int h);
+static void centered_clear(void);
- return plat_sdl_change_video_mode(w, h, force);
+static int plugin_owns_display(void)
+{
+ // if true, a plugin is drawing and flipping
+ return (pl_rearmed_cbs.gpu_caps & GPU_CAP_OWNS_DISPLAY);
}
-static void resize_cb(int w, int h)
+static void plugin_update(void)
{
- // used by some plugins..
- pl_rearmed_cbs.screen_w = w;
- pl_rearmed_cbs.screen_h = h;
+ // used by some plugins...
+ pl_rearmed_cbs.screen_w = plat_sdl_screen->w;
+ pl_rearmed_cbs.screen_h = plat_sdl_screen->h;
pl_rearmed_cbs.gles_display = gl_es_display;
pl_rearmed_cbs.gles_surface = gl_es_surface;
plugin_call_rearmed_cbs();
}
+static void sdl_event_handler(void *event_)
+{
+ SDL_Event *event = event_;
+
+ switch (event->type) {
+ case SDL_VIDEORESIZE:
+ if (window_w != (event->resize.w & ~3) || window_h != (event->resize.h & ~1)) {
+ window_w = event->resize.w & ~3;
+ window_h = event->resize.h & ~1;
+ resized = 1;
+ if (!in_menu && plat_sdl_gl_active && plugin_owns_display()) {
+ // the plugin flips by itself so resize has to be handled here
+ handle_window_resize();
+ if (GPU_open != NULL) {
+ int ret = GPU_open(&gpuDisp, "PCSX", NULL);
+ if (ret)
+ fprintf(stderr, "GPU_open: %d\n", ret);
+ }
+ }
+ }
+ return;
+ case SDL_ACTIVEEVENT:
+ // no need to redraw?
+ return;
+ default:
+ break;
+ }
+ plat_sdl_event_handler(event_);
+}
+
static void quit_cb(void)
{
emu_core_ask_exit();
void plat_init(void)
{
+ static const char *hwfilters[] = { "linear", "nearest", NULL };
+ const SDL_version *ver;
+ int shadow_size;
int ret;
plat_sdl_quit_cb = quit_cb;
- plat_sdl_resize_cb = resize_cb;
+
+ old_fullscreen = -1; // hack
ret = plat_sdl_init();
if (ret != 0)
exit(1);
+ ver = SDL_Linked_Version();
+ sdl12_compat = ver->patch >= 50;
+ printf("SDL %u.%u.%u compat=%d\n", ver->major, ver->minor, ver->patch, sdl12_compat);
+
in_menu = 1;
SDL_WM_SetCaption("PCSX-ReARMed " REV, NULL);
- shadow_fb = malloc(640 * 512 * 2);
- menubg_img = malloc(640 * 512 * 2);
+ shadow_size = g_menuscreen_w * g_menuscreen_h * 2;
+ // alloc enough for double res. rendering
+ if (shadow_size < 1024 * 512 * 2)
+ shadow_size = 1024 * 512 * 2;
+
+ shadow_fb = malloc(shadow_size);
+ menubg_img = malloc(shadow_size);
if (shadow_fb == NULL || menubg_img == NULL) {
fprintf(stderr, "OOM\n");
exit(1);
}
- in_sdl_init(in_sdl_defbinds, plat_sdl_event_handler);
+ in_sdl_init(&in_sdl_platform_data, sdl_event_handler);
in_probe();
pl_rearmed_cbs.only_16bpp = 1;
pl_rearmed_cbs.pl_get_layer_pos = get_layer_pos;
bgr_to_uyvy_init();
+
+ assert(plat_sdl_screen);
+ plugin_update();
+ if (plat_target.vout_method == vout_mode_gl)
+ gl_w_prev = plat_sdl_screen->w, gl_h_prev = plat_sdl_screen->h;
+ if (vout_mode_gl != -1)
+ plat_target.hwfilters = hwfilters;
}
void plat_finish(void)
{
}
-static void uyvy_to_rgb565(void *d, const void *s, int pixels)
+static void uyvy_to_rgb565(void *d, int pixels)
{
+ const unsigned int *src = (const void *)plat_sdl_overlay->pixels[0];
+ int x2 = plat_sdl_overlay->w >= psx_w * 2;
unsigned short *dst = d;
- const unsigned int *src = s;
int v;
// no colors, for now
- for (; pixels > 0; src++, dst += 2, pixels -= 2) {
- v = (*src >> 8) & 0xff;
- v = (v - 16) * 255 / 219 / 8;
- dst[0] = (v << 11) | (v << 6) | v;
+ if (x2) {
+ for (; pixels > 0; src++, dst++, pixels--) {
+ v = (*src >> 8) & 0xff;
+ v = (v - 16) * 255 / 219 / 8;
+ *dst = (v << 11) | (v << 6) | v;
+ }
+ }
+ else {
+ for (; pixels > 0; src++, dst += 2, pixels -= 2) {
+ v = (*src >> 8) & 0xff;
+ v = (v - 16) * 255 / 219 / 8;
+ dst[0] = (v << 11) | (v << 6) | v;
+
+ v = (*src >> 24) & 0xff;
+ v = (v - 16) * 255 / 219 / 8;
+ dst[1] = (v << 11) | (v << 6) | v;
+ }
+ }
+}
- v = (*src >> 24) & 0xff;
- v = (v - 16) * 255 / 219 / 8;
- dst[1] = (v << 11) | (v << 6) | v;
+static void overlay_resize(int force)
+{
+ int x2_mul = !in_menu && plat_target.vout_method > 1 ? 2 : 1; // lame
+ int w = in_menu ? g_menuscreen_w : psx_w;
+ int h = in_menu ? g_menuscreen_h : psx_h;
+
+ if (!force && plat_sdl_overlay && w * x2_mul == plat_sdl_overlay->w
+ && h == plat_sdl_overlay->h)
+ return;
+ if (plat_sdl_overlay)
+ SDL_FreeYUVOverlay(plat_sdl_overlay);
+ plat_sdl_overlay = SDL_CreateYUVOverlay(w * x2_mul, h, SDL_UYVY_OVERLAY,
+ plat_sdl_screen);
+ if (plat_sdl_overlay) {
+ //printf("overlay: %dx%d %08x hw=%d\n", plat_sdl_overlay->w, plat_sdl_overlay->h,
+ // plat_sdl_overlay->format, plat_sdl_overlay->hw_overlay);
+ if (SDL_LockYUVOverlay(plat_sdl_overlay) == 0) {
+ plat_sdl_overlay_clear();
+ SDL_UnlockYUVOverlay(plat_sdl_overlay);
+ }
+ }
+ else {
+ fprintf(stderr, "overlay resize to %dx%d failed\n", w, h);
+ plat_target.vout_method = 0;
}
+ handle_scaler_resize(w, h);
}
static void overlay_blit(int doffs, const void *src_, int w, int h,
const unsigned short *src = src_;
unsigned short *dst;
int dstride = plat_sdl_overlay->w;
+ int x2 = dstride >= 2 * w;
SDL_LockYUVOverlay(plat_sdl_overlay);
dst = (void *)plat_sdl_overlay->pixels[0];
dst += doffs;
if (bgr24) {
for (; h > 0; dst += dstride, src += sstride, h--)
- bgr888_to_uyvy(dst, src, w);
+ bgr888_to_uyvy(dst, src, w, x2);
}
else {
for (; h > 0; dst += dstride, src += sstride, h--)
- bgr555_to_uyvy(dst, src, w);
+ bgr555_to_uyvy(dst, src, w, x2);
}
SDL_UnlockYUVOverlay(plat_sdl_overlay);
static void overlay_hud_print(int x, int y, const char *str, int bpp)
{
+ int x2;
SDL_LockYUVOverlay(plat_sdl_overlay);
+ x2 = plat_sdl_overlay->w >= psx_w * 2;
+ if (x2)
+ x *= 2;
basic_text_out_uyvy_nf(plat_sdl_overlay->pixels[0], plat_sdl_overlay->w, x, y, str);
SDL_UnlockYUVOverlay(plat_sdl_overlay);
}
-void *plat_gvideo_set_mode(int *w, int *h, int *bpp)
+static void gl_finish_pl(void)
{
- psx_w = *w;
- psx_h = *h;
- change_video_mode(0);
+ if (plugin_owns_display() && GPU_close != NULL)
+ GPU_close();
+ gl_destroy();
+}
+
+static void gl_resize(void)
+{
+ int w = in_menu ? g_menuscreen_w : psx_w;
+ int h = in_menu ? g_menuscreen_h : psx_h;
+
+ gl_quirks &= ~(GL_QUIRK_SCALING_NEAREST | GL_QUIRK_VSYNC_ON);
+ if (plat_target.hwfilter) // inverted from plat_sdl_gl_scaling()
+ gl_quirks |= GL_QUIRK_SCALING_NEAREST;
+ if (g_opts & OPT_VSYNC)
+ gl_quirks |= GL_QUIRK_VSYNC_ON;
+
+ if (plugin_owns_display())
+ w = plat_sdl_screen->w, h = plat_sdl_screen->h;
+ if (plat_sdl_gl_active) {
+ if (w == gl_w_prev && h == gl_h_prev && gl_quirks == gl_quirks_prev)
+ return;
+ gl_finish_pl();
+ }
+ plat_sdl_gl_active = (gl_create(window, &gl_quirks, w, h) == 0);
+ if (plat_sdl_gl_active)
+ gl_w_prev = w, gl_h_prev = h, gl_quirks_prev = gl_quirks;
+ else {
+ fprintf(stderr, "warning: could not init GL.\n");
+ plat_target.vout_method = 0;
+ }
+ handle_scaler_resize(w, h);
+ plugin_update();
+ forced_flips = 0; // interferes with gl
+}
+
+static void overlay_or_gl_check_enable(void)
+{
+ int ovl_on = plat_target.vout_method == vout_mode_overlay ||
+ plat_target.vout_method == vout_mode_overlay2x;
+ int gl_on = plat_target.vout_method == vout_mode_gl;
+ if (!gl_on && plat_sdl_gl_active) {
+ gl_finish_pl();
+ pl_rearmed_cbs.gles_display = gl_es_display;
+ pl_rearmed_cbs.gles_surface = gl_es_surface;
+ plat_sdl_gl_active = 0;
+ }
+ if (!ovl_on && plat_sdl_overlay) {
+ SDL_FreeYUVOverlay(plat_sdl_overlay);
+ plat_sdl_overlay = NULL;
+ }
+ if (ovl_on)
+ overlay_resize(0);
+ else if (gl_on)
+ gl_resize();
+}
+
+static void centered_clear(void)
+{
+ int dstride = plat_sdl_screen->pitch / 2;
+ int w = plat_sdl_screen->w;
+ int h = plat_sdl_screen->h;
+ unsigned short *dst;
+
+ if (plat_sdl_gl_active) {
+ gl_clear();
+ return;
+ }
+
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_LockSurface(plat_sdl_screen);
+ dst = plat_sdl_screen->pixels;
+
+ for (; h > 0; dst += dstride, h--)
+ memset(dst, 0, w * 2);
+
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_UnlockSurface(plat_sdl_screen);
+
+ if (plat_sdl_overlay != NULL) {
+ // apply the parts not covered by the overlay
+ forced_flips = 3;
+ }
+}
+
+static int adj_src_dst(const SDL_Surface *sfc, int w, int pp, int *h,
+ unsigned short **dst, const unsigned short **src)
+{
+ int line_w = w;
+ if (sfc->w > w)
+ *dst += (sfc->w - w) / 2;
+ else {
+ *src += (w - sfc->w) / 2;
+ line_w = sfc->w;
+ }
+ if (sfc->h > *h)
+ *dst += sfc->pitch * (sfc->h - *h) / 2 / 2;
+ else {
+ *src += pp * (*h - sfc->h) / 2;
+ *h = sfc->h;
+ }
+ return line_w;
+}
+
+static void centered_blit(int doffs, const void *src_, int w, int h,
+ int sstride, int bgr24)
+{
+ const unsigned short *src = src_;
+ unsigned short *dst;
+ int dstride;
+
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_LockSurface(plat_sdl_screen);
+ dst = plat_sdl_screen->pixels;
+ dstride = plat_sdl_screen->pitch / 2;
+ w = adj_src_dst(plat_sdl_screen, w, sstride, &h, &dst, &src);
+
+ if (bgr24) {
+ for (; h > 0; dst += dstride, src += sstride, h--)
+ bgr888_to_rgb565(dst, src, w * 3);
+ }
+ else {
+ for (; h > 0; dst += dstride, src += sstride, h--)
+ bgr555_to_rgb565(dst, src, w * 2);
+ }
+
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_UnlockSurface(plat_sdl_screen);
+}
+
+static void centered_blit_menu(void)
+{
+ const unsigned short *src = g_menuscreen_ptr;
+ int w = g_menuscreen_w;
+ int h = g_menuscreen_h;
+ unsigned short *dst;
+ int dstride, len;
+
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_LockSurface(plat_sdl_screen);
+
+ dst = plat_sdl_screen->pixels;
+ dstride = plat_sdl_screen->pitch / 2;
+ len = adj_src_dst(plat_sdl_screen, w, g_menuscreen_pp, &h, &dst, &src);
+
+ for (; h > 0; dst += dstride, src += g_menuscreen_pp, h--)
+ memcpy(dst, src, len * 2);
+
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_UnlockSurface(plat_sdl_screen);
+}
+
+static void centered_hud_print(int x, int y, const char *str, int bpp)
+{
+ int w_diff, h_diff;
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_LockSurface(plat_sdl_screen);
+ w_diff = plat_sdl_screen->w - psx_w;
+ h_diff = plat_sdl_screen->h - psx_h;
+ if (w_diff > 0) x += w_diff / 2;
+ if (h_diff > 0) y += h_diff / 2;
+ if (h_diff < 0) y += h_diff;
+ if (w_diff < 0 && x > 32) x += w_diff;
+ basic_text_out16_nf(plat_sdl_screen->pixels, plat_sdl_screen->pitch / 2, x, y, str);
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_UnlockSurface(plat_sdl_screen);
+}
+
+static void *setup_blit_callbacks(int w, int h)
+{
+ pl_plat_clear = NULL;
+ pl_plat_blit = NULL;
+ pl_plat_hud_print = NULL;
if (plat_sdl_overlay != NULL) {
pl_plat_clear = plat_sdl_overlay_clear;
pl_plat_blit = overlay_blit;
pl_plat_hud_print = overlay_hud_print;
- return NULL;
+ }
+ else if (plat_sdl_gl_active) {
+ return shadow_fb;
}
else {
- pl_plat_clear = NULL;
- pl_plat_blit = NULL;
- pl_plat_hud_print = NULL;
- if (plat_sdl_gl_active)
- return shadow_fb;
- else
+ pl_plat_clear = centered_clear;
+
+ if (!SDL_MUSTLOCK(plat_sdl_screen) && w == plat_sdl_screen->w &&
+ h == plat_sdl_screen->h)
return plat_sdl_screen->pixels;
+
+ pl_plat_blit = centered_blit;
+ pl_plat_hud_print = centered_hud_print;
+ }
+ return NULL;
+}
+
+// not using plat_sdl_change_video_mode() since we need
+// different size overlay vs plat_sdl_screen layer
+static void change_mode(int w, int h)
+{
+ int set_w = w, set_h = h, had_overlay = 0, had_gl = 0;
+ if (plat_target.vout_fullscreen && (plat_target.vout_method != 0 || !sdl12_compat))
+ set_w = fs_w, set_h = fs_h;
+ if (plat_sdl_screen->w != set_w || plat_sdl_screen->h != set_h ||
+ plat_target.vout_fullscreen != vout_fullscreen_old)
+ {
+ Uint32 flags = plat_sdl_screen->flags;
+ if (plat_target.vout_fullscreen)
+ flags |= SDL_FULLSCREEN;
+ else {
+ flags &= ~SDL_FULLSCREEN;
+ if (plat_sdl_is_windowed())
+ flags |= SDL_RESIZABLE; // sdl12-compat 1.2.68 loses this flag
+ }
+ if (plat_sdl_overlay) {
+ SDL_FreeYUVOverlay(plat_sdl_overlay);
+ plat_sdl_overlay = NULL;
+ had_overlay = 1;
+ }
+ if (plat_sdl_gl_active) {
+ gl_finish_pl();
+ plat_sdl_gl_active = 0;
+ had_gl = 1;
+ }
+ SDL_PumpEvents();
+ plat_sdl_screen = SDL_SetVideoMode(set_w, set_h, 16, flags);
+ //printf("mode: %dx%d %x -> %dx%d\n", set_w, set_h, flags,
+ // plat_sdl_screen->w, plat_sdl_screen->h);
+ assert(plat_sdl_screen);
+ if (vout_fullscreen_old && !plat_target.vout_fullscreen)
+ // why is this needed?? (on 1.2.68)
+ SDL_WM_GrabInput(SDL_GRAB_OFF);
+ if (vout_mode_gl != -1)
+ update_wm_display_window();
+ // overlay needs the latest plat_sdl_screen
+ if (had_overlay)
+ overlay_resize(1);
+ if (had_gl)
+ gl_resize();
+ centered_clear();
+ plugin_update();
+ vout_fullscreen_old = plat_target.vout_fullscreen;
+ }
+}
+
+static void handle_scaler_resize(int w, int h)
+{
+ int ww = plat_sdl_screen->w;
+ int wh = plat_sdl_screen->h;
+ int layer_w_old = g_layer_w;
+ int layer_h_old = g_layer_h;
+ float w_mul, h_mul;
+ int x, y;
+ pl_update_layer_size(w, h, ww, wh);
+ if (layer_w_old != g_layer_w || layer_h_old != g_layer_h)
+ forced_clears = 3;
+
+ w_mul = 2.0f / ww;
+ h_mul = 2.0f / wh;
+ x = (ww - g_layer_w) / 2;
+ y = (wh - g_layer_h) / 2;
+ gl_vertices[3*0+0] = gl_vertices[3*2+0] = -1.0f + x * w_mul;
+ gl_vertices[3*1+0] = gl_vertices[3*3+0] = -1.0f + (x + g_layer_w) * w_mul;
+ gl_vertices[3*2+1] = gl_vertices[3*3+1] = -1.0f + y * h_mul;
+ gl_vertices[3*0+1] = gl_vertices[3*1+1] = -1.0f + (y + g_layer_h) * h_mul;
+}
+
+static void handle_window_resize(void)
+{
+ // sdl12-compat: a hack to take advantage of sdl2 scaling
+ if (resized && (plat_target.vout_method != 0 || !sdl12_compat)) {
+ change_mode(window_w, window_h);
+ setup_blit_callbacks(psx_w, psx_h);
+ forced_clears = 3;
+ }
+ resized = 0;
+}
+
+void *plat_gvideo_set_mode(int *w, int *h, int *bpp)
+{
+ psx_w = *w;
+ psx_h = *h;
+
+ if (plat_sdl_gl_active && plugin_owns_display())
+ return NULL;
+
+ if (plat_sdl_overlay != NULL)
+ overlay_resize(0);
+ else if (plat_sdl_gl_active) {
+ memset(shadow_fb, 0, (*w) * (*h) * 2);
+ gl_resize();
}
+ else if (plat_target.vout_method == 0) // && sdl12_compat
+ change_mode(*w, *h);
+
+ handle_scaler_resize(*w, *h); // override the value from pl_vout_set_mode()
+ return setup_blit_callbacks(*w, *h);
}
void *plat_gvideo_flip(void)
{
+ void *ret = NULL;
+ int do_flip = 0;
if (plat_sdl_overlay != NULL) {
- SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
+ SDL_Rect dstrect = {
+ (plat_sdl_screen->w - g_layer_w) / 2,
+ (plat_sdl_screen->h - g_layer_h) / 2,
+ g_layer_w, g_layer_h
+ };
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
- return NULL;
}
else if (plat_sdl_gl_active) {
- gl_flip(shadow_fb, psx_w, psx_h);
- return shadow_fb;
+ gl_flip_v(shadow_fb, psx_w, psx_h, g_scaler != SCALE_FULLSCREEN ? gl_vertices : NULL);
+ ret = shadow_fb;
}
- else {
- // XXX: no locking, but should be fine with SDL_SWSURFACE?
+ else
+ do_flip |= 2;
+
+ if (forced_flips > 0) {
+ forced_flips--;
+ do_flip |= 1;
+ }
+ if (do_flip)
SDL_Flip(plat_sdl_screen);
- return plat_sdl_screen->pixels;
+ handle_window_resize();
+ if (do_flip) {
+ if (forced_clears > 0) {
+ forced_clears--;
+ centered_clear();
+ }
+ if (!SDL_MUSTLOCK(plat_sdl_screen) && plat_sdl_screen->w == psx_w &&
+ plat_sdl_screen->h == psx_h && (do_flip & 2)) {
+ ret = plat_sdl_screen->pixels;
+ }
}
+ assert(ret || pl_plat_clear != NULL);
+ return ret;
}
void plat_gvideo_close(void)
void plat_video_menu_enter(int is_rom_loaded)
{
- int force_mode_change = 0;
+ int d;
in_menu = 1;
/* surface will be lost, must adjust pl_vout_buf for menu bg */
if (plat_sdl_overlay != NULL)
- uyvy_to_rgb565(menubg_img, plat_sdl_overlay->pixels[0], psx_w * psx_h);
+ uyvy_to_rgb565(menubg_img, psx_w * psx_h);
else if (plat_sdl_gl_active)
memcpy(menubg_img, shadow_fb, psx_w * psx_h * 2);
- else
- memcpy(menubg_img, plat_sdl_screen->pixels, psx_w * psx_h * 2);
+ else {
+ unsigned short *dst = menubg_img;
+ const unsigned short *src;
+ int h;
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_LockSurface(plat_sdl_screen);
+ src = plat_sdl_screen->pixels;
+ src += (plat_sdl_screen->w - psx_w) / 2;
+ src += plat_sdl_screen->pitch * (plat_sdl_screen->h - psx_h) / 2 / 2;
+ for (h = psx_h; h > 0; dst += psx_w, src += plat_sdl_screen->pitch / 2, h--)
+ memcpy(dst, src, psx_w * 2);
+ if (SDL_MUSTLOCK(plat_sdl_screen))
+ SDL_UnlockSurface(plat_sdl_screen);
+ }
pl_vout_buf = menubg_img;
- /* gles plugin messes stuff up.. */
- if (pl_rearmed_cbs.gpu_caps & GPU_CAP_OWNS_DISPLAY)
- force_mode_change = 1;
+ if (plat_target.vout_method == 0)
+ change_mode(g_menuscreen_w, g_menuscreen_h);
+ else
+ overlay_or_gl_check_enable();
+ centered_clear();
- change_video_mode(force_mode_change);
+ for (d = 0; d < IN_MAX_DEVS; d++)
+ in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 1);
}
void plat_video_menu_begin(void)
{
- if (plat_sdl_overlay != NULL || plat_sdl_gl_active) {
- g_menuscreen_ptr = shadow_fb;
- }
- else {
- SDL_LockSurface(plat_sdl_screen);
- g_menuscreen_ptr = plat_sdl_screen->pixels;
+ void *old_ovl = plat_sdl_overlay;
+ static int g_scaler_old;
+ int scaler_changed = g_scaler_old != g_scaler;
+ g_scaler_old = g_scaler;
+ if (plat_target.vout_fullscreen != vout_fullscreen_old ||
+ (plat_target.vout_fullscreen && scaler_changed)) {
+ change_mode(g_menuscreen_w, g_menuscreen_h);
}
+ overlay_or_gl_check_enable();
+ handle_scaler_resize(g_menuscreen_w, g_menuscreen_h);
+
+ if (old_ovl != plat_sdl_overlay || scaler_changed)
+ centered_clear();
+ g_menuscreen_ptr = shadow_fb;
}
void plat_video_menu_end(void)
{
+ int do_flip = 0;
+
if (plat_sdl_overlay != NULL) {
- SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
+ SDL_Rect dstrect = {
+ (plat_sdl_screen->w - g_layer_w) / 2,
+ (plat_sdl_screen->h - g_layer_h) / 2,
+ g_layer_w, g_layer_h
+ };
SDL_LockYUVOverlay(plat_sdl_overlay);
rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
}
else if (plat_sdl_gl_active) {
- gl_flip(g_menuscreen_ptr, g_menuscreen_w, g_menuscreen_h);
+ gl_flip_v(g_menuscreen_ptr, g_menuscreen_w, g_menuscreen_h,
+ g_scaler != SCALE_FULLSCREEN ? gl_vertices : NULL);
}
else {
- SDL_UnlockSurface(plat_sdl_screen);
- SDL_Flip(plat_sdl_screen);
+ centered_blit_menu();
+ do_flip |= 2;
}
+
+ if (forced_flips > 0) {
+ forced_flips--;
+ do_flip |= 1;
+ }
+ if (do_flip)
+ SDL_Flip(plat_sdl_screen);
+
+ handle_window_resize();
g_menuscreen_ptr = NULL;
}
void plat_video_menu_leave(void)
{
+ int d;
+
in_menu = 0;
+ if (plat_sdl_overlay != NULL || plat_sdl_gl_active)
+ memset(shadow_fb, 0, g_menuscreen_w * g_menuscreen_h * 2);
+
+ if (plat_target.vout_fullscreen)
+ change_mode(fs_w, fs_h);
+ overlay_or_gl_check_enable();
+ centered_clear();
+ setup_blit_callbacks(psx_w, psx_h);
+
+ for (d = 0; d < IN_MAX_DEVS; d++)
+ in_set_config_int(d, IN_CFG_ANALOG_MAP_ULDR, 0);
}
-/* unused stuff */
void *plat_prepare_screenshot(int *w, int *h, int *bpp)
{
- return 0;
+ if (plat_sdl_screen && !SDL_MUSTLOCK(plat_sdl_screen) &&
+ plat_sdl_overlay == NULL && !plat_sdl_gl_active)
+ {
+ *w = plat_sdl_screen->pitch / 2;
+ *h = plat_sdl_screen->h;
+ *bpp = 16;
+ return plat_sdl_screen->pixels;
+ }
+ fprintf(stderr, "screenshot not implemented in current mode\n");
+ return NULL;
}
-void plat_trigger_vibrate(int is_strong)
+void plat_trigger_vibrate(int pad, int low, int high)
{
}