summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/sdl
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/sdl')
-rw-r--r--src/osd/sdl/android_main.cpp11
-rw-r--r--src/osd/sdl/osdsdl.cpp851
-rw-r--r--src/osd/sdl/osdsdl.h204
-rw-r--r--src/osd/sdl/sdlmain.cpp423
-rw-r--r--src/osd/sdl/sdlopts.cpp126
-rw-r--r--src/osd/sdl/sdlopts.h98
-rw-r--r--src/osd/sdl/video.cpp205
-rw-r--r--src/osd/sdl/window.cpp575
-rw-r--r--src/osd/sdl/window.h103
9 files changed, 1699 insertions, 897 deletions
diff --git a/src/osd/sdl/android_main.cpp b/src/osd/sdl/android_main.cpp
new file mode 100644
index 00000000000..00879ecbe27
--- /dev/null
+++ b/src/osd/sdl/android_main.cpp
@@ -0,0 +1,11 @@
+#ifdef __ANDROID__
+
+extern "C" int SDL_main(int argc, char *argv[]);
+
+// Using this in main library to prevent linker removing SDL_main
+int dummy_main(int argc, char** argv)
+{
+ return SDL_main(argc, argv);
+}
+
+#endif /* __ANDROID__ */
diff --git a/src/osd/sdl/osdsdl.cpp b/src/osd/sdl/osdsdl.cpp
new file mode 100644
index 00000000000..87af652733e
--- /dev/null
+++ b/src/osd/sdl/osdsdl.cpp
@@ -0,0 +1,851 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont
+
+#include "osdsdl.h"
+
+#include "modules/input/input_common.h"
+#include "modules/lib/osdlib.h"
+#include "window.h"
+
+#include "util/language.h"
+#include "util/unicode.h"
+
+// TODO: reduce dependence on concrete emu classes
+#include "emu.h"
+#include "main.h"
+#include "uiinput.h"
+
+#include "ui/uimain.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <cstring>
+
+
+namespace {
+
+//============================================================
+// defines_verbose
+//============================================================
+
+#define MAC_EXPAND_STR(_m) #_m
+#define MACRO_VERBOSE(_mac) \
+ do { \
+ if (strcmp(MAC_EXPAND_STR(_mac), #_mac) != 0) \
+ osd_printf_verbose("%s=%s ", #_mac, MAC_EXPAND_STR(_mac)); \
+ } while (0)
+
+void defines_verbose()
+{
+ osd_printf_verbose("Build version: %s\n", emulator_info::get_build_version());
+ osd_printf_verbose("Build architecure: ");
+ MACRO_VERBOSE(SDLMAME_ARCH);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Build defines 1: ");
+ MACRO_VERBOSE(SDLMAME_UNIX);
+ MACRO_VERBOSE(SDLMAME_X11);
+ MACRO_VERBOSE(SDLMAME_WIN32);
+ MACRO_VERBOSE(SDLMAME_MACOSX);
+ MACRO_VERBOSE(SDLMAME_DARWIN);
+ MACRO_VERBOSE(SDLMAME_LINUX);
+ MACRO_VERBOSE(SDLMAME_SOLARIS);
+ MACRO_VERBOSE(SDLMAME_IRIX);
+ MACRO_VERBOSE(SDLMAME_BSD);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Build defines 1: ");
+ MACRO_VERBOSE(LSB_FIRST);
+ MACRO_VERBOSE(PTR64);
+ MACRO_VERBOSE(MAME_NOASM);
+ MACRO_VERBOSE(MAME_DEBUG);
+ MACRO_VERBOSE(BIGENDIAN);
+ MACRO_VERBOSE(CPP_COMPILE);
+ MACRO_VERBOSE(SYNC_IMPLEMENTATION);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("SDL/OpenGL defines: ");
+ osd_printf_verbose("SDL_COMPILEDVERSION=%d ", SDL_COMPILEDVERSION);
+ MACRO_VERBOSE(USE_OPENGL);
+ MACRO_VERBOSE(USE_DISPATCH_GL);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Compiler defines A: ");
+ MACRO_VERBOSE(__GNUC__);
+ MACRO_VERBOSE(__GNUC_MINOR__);
+ MACRO_VERBOSE(__GNUC_PATCHLEVEL__);
+ MACRO_VERBOSE(__VERSION__);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Compiler defines B: ");
+ MACRO_VERBOSE(__amd64__);
+ MACRO_VERBOSE(__x86_64__);
+ MACRO_VERBOSE(__unix__);
+ MACRO_VERBOSE(__i386__);
+ MACRO_VERBOSE(__ppc__);
+ MACRO_VERBOSE(__ppc64__);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Compiler defines C: ");
+ MACRO_VERBOSE(_FORTIFY_SOURCE);
+ MACRO_VERBOSE(__USE_FORTIFY_LEVEL);
+ osd_printf_verbose("\n");
+}
+
+
+//============================================================
+// osd_sdl_info
+//============================================================
+
+void osd_sdl_info()
+{
+ int num = SDL_GetNumVideoDrivers();
+
+ osd_printf_verbose("Available videodrivers: ");
+ for (int i = 0; i < num; i++)
+ {
+ const char *name = SDL_GetVideoDriver(i);
+ osd_printf_verbose("%s ", name);
+ }
+ osd_printf_verbose("\n");
+
+ osd_printf_verbose("Current Videodriver: %s\n", SDL_GetCurrentVideoDriver());
+ num = SDL_GetNumVideoDisplays();
+ for (int i = 0; i < num; i++)
+ {
+ SDL_DisplayMode mode;
+
+ osd_printf_verbose("\tDisplay #%d\n", i);
+ if (SDL_GetDesktopDisplayMode(i, &mode) == 0)
+ osd_printf_verbose("\t\tDesktop Mode: %dx%d-%d@%d\n", mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate);
+ if (SDL_GetCurrentDisplayMode(i, &mode) == 0)
+ osd_printf_verbose("\t\tCurrent Display Mode: %dx%d-%d@%d\n", mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate);
+
+ osd_printf_verbose("\t\tRenderdrivers:\n");
+ for (int j = 0; j < SDL_GetNumRenderDrivers(); j++)
+ {
+ SDL_RendererInfo info;
+ SDL_GetRenderDriverInfo(j, &info);
+ osd_printf_verbose("\t\t\t%10s (%dx%d)\n", info.name, info.max_texture_width, info.max_texture_height);
+ }
+ }
+
+ osd_printf_verbose("Available audio drivers: \n");
+ num = SDL_GetNumAudioDrivers();
+ for (int i = 0; i < num; i++)
+ {
+ osd_printf_verbose("\t%-20s\n", SDL_GetAudioDriver(i));
+ }
+}
+
+
+sdl_window_info *window_from_id(Uint32 id)
+{
+ SDL_Window const *const sdl_window = SDL_GetWindowFromID(id);
+
+ auto const window = std::find_if(
+ osd_common_t::window_list().begin(),
+ osd_common_t::window_list().end(),
+ [sdl_window] (std::unique_ptr<osd_window> const &w)
+ {
+ return dynamic_cast<sdl_window_info &>(*w).platform_window() == sdl_window;
+ });
+
+ if (window == osd_common_t::window_list().end())
+ return nullptr;
+
+ return &static_cast<sdl_window_info &>(**window);
+}
+
+} // anonymous namespace
+
+
+
+//============================================================
+// SDL OSD interface
+//============================================================
+
+sdl_osd_interface::sdl_osd_interface(sdl_options &options) :
+ osd_common_t(options),
+ m_options(options),
+ m_focus_window(nullptr),
+ m_mouse_over_window(0),
+ m_modifier_keys(0),
+ m_last_click_time(std::chrono::steady_clock::time_point::min()),
+ m_last_click_x(0),
+ m_last_click_y(0),
+ m_enable_touch(false),
+ m_next_ptrdev(0)
+{
+}
+
+
+sdl_osd_interface::~sdl_osd_interface()
+{
+}
+
+
+void sdl_osd_interface::init(running_machine &machine)
+{
+ // call our parent
+ osd_common_t::init(machine);
+
+ const char *stemp;
+
+ // determine if we are benchmarking, and adjust options appropriately
+ int bench = options().bench();
+ if (bench > 0)
+ {
+ options().set_value(OPTION_SLEEP, false, OPTION_PRIORITY_MAXIMUM);
+ options().set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM);
+ options().set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM);
+ options().set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM);
+ options().set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM);
+ }
+
+ // Some driver options - must be before audio init!
+ stemp = options().audio_driver();
+ if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0)
+ {
+ osd_printf_verbose("Setting SDL audiodriver '%s' ...\n", stemp);
+ osd_setenv(SDLENV_AUDIODRIVER, stemp, 1);
+ }
+
+ stemp = options().video_driver();
+ if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0)
+ {
+ osd_printf_verbose("Setting SDL videodriver '%s' ...\n", stemp);
+ osd_setenv(SDLENV_VIDEODRIVER, stemp, 1);
+ }
+
+ stemp = options().render_driver();
+ if (stemp != nullptr)
+ {
+ if (strcmp(stemp, OSDOPTVAL_AUTO) != 0)
+ {
+ osd_printf_verbose("Setting SDL renderdriver '%s' ...\n", stemp);
+ //osd_setenv(SDLENV_RENDERDRIVER, stemp, 1);
+ SDL_SetHint(SDL_HINT_RENDER_DRIVER, stemp);
+ }
+ else
+ {
+#if defined(SDLMAME_WIN32)
+ // OpenGL renderer has less issues with mode switching on windows
+ osd_printf_verbose("Setting SDL renderdriver '%s' ...\n", "opengl");
+ //osd_setenv(SDLENV_RENDERDRIVER, stemp, 1);
+ SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
+#endif
+ }
+ }
+
+ /* Set the SDL environment variable for drivers wanting to load the
+ * lib at startup.
+ */
+#if USE_OPENGL
+ /* FIXME: move lib loading code from drawogl.c here */
+
+ stemp = options().gl_lib();
+ if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0)
+ {
+ osd_setenv("SDL_VIDEO_GL_DRIVER", stemp, 1);
+ osd_printf_verbose("Setting SDL_VIDEO_GL_DRIVER = '%s' ...\n", stemp);
+ }
+#endif
+
+ /* get number of processors */
+ stemp = options().numprocessors();
+
+ osd_num_processors = 0;
+
+ if (strcmp(stemp, "auto") != 0)
+ {
+ osd_num_processors = atoi(stemp);
+ if (osd_num_processors < 1)
+ {
+ osd_printf_warning("numprocessors < 1 doesn't make much sense. Assuming auto ...\n");
+ osd_num_processors = 0;
+ }
+ }
+
+ /* do we want touch support or will we use mouse emulation? */
+ m_enable_touch = options().enable_touch();
+ try
+ {
+ if (m_enable_touch)
+ {
+ int const count(SDL_GetNumTouchDevices());
+ m_ptrdev_map.reserve(std::max<int>(count + 1, 8));
+ map_pointer_device(SDL_MOUSE_TOUCHID);
+ for (int i = 0; count > i; ++i)
+ {
+ SDL_TouchID const device(SDL_GetTouchDevice(i));
+ if (device)
+ map_pointer_device(device);
+ }
+ }
+ else
+ {
+ m_ptrdev_map.reserve(1);
+ map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ // survivable - it will still attempt to allocate mappings when it first sees devices
+ }
+
+#if defined(SDLMAME_ANDROID)
+ SDL_SetHint(SDL_HINT_VIDEO_EXTERNAL_CONTEXT, "1");
+#endif
+ /* Initialize SDL */
+
+ if (SDL_InitSubSystem(SDL_INIT_VIDEO))
+ {
+ osd_printf_error("Could not initialize SDL %s\n", SDL_GetError());
+ exit(-1);
+ }
+
+ osd_sdl_info();
+
+ defines_verbose();
+
+ osd_common_t::init_subsystems();
+
+ if (options().oslog())
+ {
+ using namespace std::placeholders;
+ machine.add_logerror_callback(std::bind(&sdl_osd_interface::output_oslog, this, _1));
+ }
+
+
+
+#ifdef SDLMAME_EMSCRIPTEN
+ SDL_EventState(SDL_TEXTINPUT, SDL_FALSE);
+#else
+ SDL_EventState(SDL_TEXTINPUT, SDL_TRUE);
+#endif
+}
+
+
+void sdl_osd_interface::input_update(bool relative_reset)
+{
+ process_events_buf();
+ poll_input_modules(relative_reset);
+}
+
+
+void sdl_osd_interface::customize_input_type_list(std::vector<input_type_entry> &typelist)
+{
+ // loop over the defaults
+ for (input_type_entry &entry : typelist)
+ {
+ switch (entry.type())
+ {
+ // configurable UI mode switch
+ case IPT_UI_TOGGLE_UI:
+ {
+ char const *const uimode = options().ui_mode_key();
+ input_item_id mameid_code = ITEM_ID_INVALID;
+ if (!uimode || !*uimode || !strcmp(uimode, "auto"))
+ {
+#if defined(__APPLE__) && defined(__MACH__)
+ mameid_code = keyboard_trans_table::instance().lookup_mame_code("ITEM_ID_INSERT");
+#endif
+ }
+ else
+ {
+ std::string fullmode("ITEM_ID_");
+ fullmode.append(uimode);
+ mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode.c_str());
+ }
+ if (ITEM_ID_INVALID != mameid_code)
+ {
+ input_code const ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code));
+ entry.defseq(SEQ_TYPE_STANDARD).set(ui_code);
+ }
+ }
+ break;
+
+ // alt-enter for fullscreen
+ case IPT_OSD_1:
+ entry.configure_osd("TOGGLE_FULLSCREEN", N_p("input-name", "Toggle Fullscreen"));
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_ENTER, KEYCODE_LALT);
+ break;
+
+ // page down for fastforward (must be OSD_3 as per src/emu/ui.c)
+ case IPT_UI_FAST_FORWARD:
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_PGDN);
+ break;
+
+ // OSD hotkeys use LALT/LCTRL and start at F3, they start
+ // at F3 because F1-F2 are hardcoded into many drivers to
+ // various dipswitches, and pressing them together with
+ // LALT/LCTRL will still press/toggle these dipswitches.
+
+ // LALT-F10 to toggle OpenGL filtering
+ case IPT_OSD_5:
+ entry.configure_osd("TOGGLE_FILTER", N_p("input-name", "Toggle Filter"));
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F10, KEYCODE_LALT);
+ break;
+
+ // add a Not LALT condition to the throttle key
+ case IPT_UI_THROTTLE:
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F10, input_seq::not_code, KEYCODE_LALT);
+ break;
+
+ // LALT-F8 to decrease OpenGL prescaling
+ case IPT_OSD_6:
+ entry.configure_osd("DECREASE_PRESCALE", N_p("input-name", "Decrease Prescaling"));
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F8, KEYCODE_LALT);
+ break;
+
+ // add a Not LALT condition to the frameskip dec key
+ case IPT_UI_FRAMESKIP_DEC:
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F8, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT);
+ break;
+
+ // LALT-F9 to increase OpenGL prescaling
+ case IPT_OSD_7:
+ entry.configure_osd("INCREASE_PRESCALE", N_p("input-name", "Increase Prescaling"));
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F9, KEYCODE_LALT);
+ break;
+
+ // add a Not LALT condition to the load state key
+ case IPT_UI_FRAMESKIP_INC:
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F9, input_seq::not_code, KEYCODE_LALT);
+ break;
+
+ // LSHIFT-LALT-F12 for fullscreen video (BGFX)
+ case IPT_OSD_8:
+ entry.configure_osd("RENDER_AVI", N_p("input-name", "Record Rendered Video"));
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LALT);
+ break;
+
+ // disable the config menu if the ALT key is down
+ // (allows ALT-TAB to switch between apps)
+ case IPT_UI_MENU:
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_TAB, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_RALT);
+ break;
+
+#if defined(__APPLE__) && defined(__MACH__)
+ // 78-key Apple MacBook & Bluetooth keyboards have no right control key
+ case IPT_MAHJONG_SCORE:
+ if (entry.player() == 0)
+ entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_SLASH);
+ break;
+#endif
+
+ // leave everything else alone
+ default:
+ break;
+ }
+ }
+}
+
+
+void sdl_osd_interface::release_keys()
+{
+ auto const keybd = dynamic_cast<input_module_base *>(m_keyboard_input);
+ if (keybd)
+ keybd->reset_devices();
+}
+
+
+bool sdl_osd_interface::should_hide_mouse()
+{
+ // if we are paused, no
+ if (machine().paused())
+ return false;
+
+ // if neither mice nor lightguns are enabled in the core, then no
+ if (!options().mouse() && !options().lightgun())
+ return false;
+
+ if (!mouse_over_window())
+ return false;
+
+ // otherwise, yes
+ return true;
+}
+
+
+void sdl_osd_interface::process_events_buf()
+{
+ SDL_PumpEvents();
+}
+
+
+void sdl_osd_interface::process_events()
+{
+ std::lock_guard<std::mutex> lock(subscription_mutex());
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ // handle UI events
+ switch (event.type)
+ {
+ case SDL_WINDOWEVENT:
+ process_window_event(event);
+ break;
+
+ case SDL_KEYDOWN:
+ if (event.key.keysym.scancode == SDL_SCANCODE_LCTRL)
+ m_modifier_keys |= MODIFIER_KEY_LCTRL;
+ else if (event.key.keysym.scancode == SDL_SCANCODE_RCTRL)
+ m_modifier_keys |= MODIFIER_KEY_RCTRL;
+ else if (event.key.keysym.scancode == SDL_SCANCODE_LSHIFT)
+ m_modifier_keys |= MODIFIER_KEY_LSHIFT;
+ else if (event.key.keysym.scancode == SDL_SCANCODE_RSHIFT)
+ m_modifier_keys |= MODIFIER_KEY_RSHIFT;
+
+ if (event.key.keysym.sym < 0x20)
+ {
+ // push control characters - they don't arrive as text input events
+ machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), event.key.keysym.sym);
+ }
+ else if (m_modifier_keys & MODIFIER_KEY_CTRL)
+ {
+ // SDL filters out control characters for text input, so they are decoded here
+ if (event.key.keysym.sym >= 0x40 && event.key.keysym.sym < 0x7f)
+ {
+ machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), event.key.keysym.sym & 0x1f);
+ }
+ else if (m_modifier_keys & MODIFIER_KEY_SHIFT)
+ {
+ if (event.key.keysym.sym == SDLK_6) // Ctrl-^ (RS)
+ machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), 0x1e);
+ else if (event.key.keysym.sym == SDLK_MINUS) // Ctrl-_ (US)
+ machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), 0x1f);
+ }
+ }
+ break;
+
+ case SDL_KEYUP:
+ if (event.key.keysym.scancode == SDL_SCANCODE_LCTRL)
+ m_modifier_keys &= ~MODIFIER_KEY_LCTRL;
+ else if (event.key.keysym.scancode == SDL_SCANCODE_RCTRL)
+ m_modifier_keys &= ~MODIFIER_KEY_RCTRL;
+ else if (event.key.keysym.scancode == SDL_SCANCODE_LSHIFT)
+ m_modifier_keys &= ~MODIFIER_KEY_LSHIFT;
+ else if (event.key.keysym.scancode == SDL_SCANCODE_RSHIFT)
+ m_modifier_keys &= ~MODIFIER_KEY_RSHIFT;
+ break;
+
+ case SDL_TEXTINPUT:
+ process_textinput_event(event);
+ break;
+
+ case SDL_MOUSEMOTION:
+ if (!m_enable_touch || (SDL_TOUCH_MOUSEID != event.motion.which))
+ {
+ auto const window = window_from_id(event.motion.windowID);
+ if (!window)
+ break;
+
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+
+ int x, y;
+ window->xy_to_render_target(event.motion.x, event.motion.y, &x, &y);
+ window->mouse_moved(device, x, y);
+ }
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ if (!m_enable_touch || (SDL_TOUCH_MOUSEID != event.button.which))
+ {
+ auto const window = window_from_id(event.button.windowID);
+ if (!window)
+ break;
+
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+
+ int x, y;
+ window->xy_to_render_target(event.button.x, event.button.y, &x, &y);
+ unsigned button(event.button.button - 1);
+ if ((1 == button) || (2 == button))
+ button ^= 3;
+ if (SDL_PRESSED == event.button.state)
+ window->mouse_down(device, x, y, button);
+ else
+ window->mouse_up(device, x, y, button);
+ }
+ break;
+
+ case SDL_MOUSEWHEEL:
+ {
+ auto const window = window_from_id(event.wheel.windowID);
+ if (window)
+ {
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+#if SDL_VERSION_ATLEAST(2, 0, 18)
+ window->mouse_wheel(device, std::lround(event.wheel.preciseY * 120));
+#else
+ window->mouse_wheel(device, event.wheel.y);
+#endif
+ }
+ }
+ break;
+
+ case SDL_FINGERMOTION:
+ case SDL_FINGERDOWN:
+ case SDL_FINGERUP:
+ if (m_enable_touch && (SDL_MOUSE_TOUCHID != event.tfinger.touchId))
+ {
+ // ignore if it doesn't map to a window we own
+ auto const window = window_from_id(event.tfinger.windowID);
+ if (!window)
+ break;
+
+ // map SDL touch device ID to a zero-based device number
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(event.tfinger.touchId);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+
+ // convert normalised coordinates to what MAME wants
+ auto const size = window->get_size();
+ int const winx = std::lround(event.tfinger.x * size.width());
+ int const winy = std::lround(event.tfinger.y * size.height());
+ int x, y;
+ window->xy_to_render_target(winx, winy, &x, &y);
+
+ // call appropriate window method
+ switch (event.type)
+ {
+ case SDL_FINGERMOTION:
+ window->finger_moved(event.tfinger.fingerId, device, x, y);
+ break;
+ case SDL_FINGERDOWN:
+ window->finger_down(event.tfinger.fingerId, device, x, y);
+ break;
+ case SDL_FINGERUP:
+ window->finger_up(event.tfinger.fingerId, device, x, y);
+ break;
+ }
+ }
+ break;
+ }
+
+ // let input modules do their thing
+ dispatch_event(event.type, event);
+ }
+}
+
+
+void sdl_osd_interface::osd_exit()
+{
+ osd_common_t::osd_exit();
+
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+}
+
+
+void sdl_osd_interface::output_oslog(const char *buffer)
+{
+ fputs(buffer, stderr);
+}
+
+
+void sdl_osd_interface::process_window_event(SDL_Event const &event)
+{
+ auto const window = window_from_id(event.window.windowID);
+
+ if (!window)
+ {
+ // This condition may occur when the fullscreen toggle is used
+ osd_printf_verbose("Skipped window event due to missing window param from SDL\n");
+ return;
+ }
+
+ switch (event.window.event)
+ {
+ case SDL_WINDOWEVENT_MOVED:
+ window->notify_changed();
+ m_focus_window = window;
+ break;
+
+ case SDL_WINDOWEVENT_RESIZED:
+#ifdef SDLMAME_LINUX
+ /* FIXME: SDL2 sends some spurious resize events on Ubuntu
+ * while in fullscreen mode. Ignore them for now.
+ */
+ if (!window->fullscreen())
+#endif
+ {
+ //printf("event data1,data2 %d x %d %ld\n", event.window.data1, event.window.data2, sizeof(SDL_Event));
+ window->resize(event.window.data1, event.window.data2);
+ }
+ break;
+
+ case SDL_WINDOWEVENT_ENTER:
+ {
+ m_mouse_over_window = 1;
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+ window->mouse_entered(device);
+ }
+ break;
+
+ case SDL_WINDOWEVENT_LEAVE:
+ {
+ m_mouse_over_window = 0;
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+ window->mouse_left(device);
+ }
+ break;
+
+ case SDL_WINDOWEVENT_FOCUS_GAINED:
+ m_focus_window = window;
+ machine().ui_input().push_window_focus_event(window->target());
+ break;
+
+ case SDL_WINDOWEVENT_FOCUS_LOST:
+ if (window == m_focus_window)
+ m_focus_window = nullptr;
+ machine().ui_input().push_window_defocus_event(window->target());
+ break;
+
+ case SDL_WINDOWEVENT_CLOSE:
+ machine().schedule_exit();
+ break;
+ }
+}
+
+void sdl_osd_interface::process_textinput_event(SDL_Event const &event)
+{
+ if (*event.text.text)
+ {
+ auto const window = focus_window(event.text);
+ //printf("Focus window is %p - wl %p\n", window, osd_common_t::window_list().front().get());
+ if (window != nullptr)
+ {
+ auto ptr = event.text.text;
+ auto len = std::strlen(event.text.text);
+ while (len)
+ {
+ char32_t ch;
+ auto chlen = uchar_from_utf8(&ch, ptr, len);
+ if (0 > chlen)
+ {
+ ch = 0x0fffd;
+ chlen = 1;
+ }
+ ptr += chlen;
+ len -= chlen;
+ machine().ui_input().push_char_event(window->target(), ch);
+ }
+ }
+ }
+}
+
+
+void sdl_osd_interface::check_osd_inputs()
+{
+ // check for toggling fullscreen mode (don't do this in debug mode)
+ if (machine().ui_input().pressed(IPT_OSD_1) && !(machine().debug_flags & DEBUG_FLAG_OSD_ENABLED))
+ {
+ // destroy the renderers first so that the render module can bounce if it depends on having a window handle
+ for (auto it = osd_common_t::window_list().rbegin(); osd_common_t::window_list().rend() != it; ++it)
+ (*it)->renderer_reset();
+ for (auto const &curwin : osd_common_t::window_list())
+ dynamic_cast<sdl_window_info &>(*curwin).toggle_full_screen();
+ }
+
+ auto const &window = osd_common_t::window_list().front();
+
+ if (USE_OPENGL)
+ {
+ // FIXME: on a per window basis
+ if (machine().ui_input().pressed(IPT_OSD_5))
+ {
+ video_config.filter = !video_config.filter;
+ machine().ui().popup_time(1, "Filter %s", video_config.filter? "enabled" : "disabled");
+ }
+ }
+
+ if (machine().ui_input().pressed(IPT_OSD_6))
+ dynamic_cast<sdl_window_info &>(*window).modify_prescale(-1);
+
+ if (machine().ui_input().pressed(IPT_OSD_7))
+ dynamic_cast<sdl_window_info &>(*window).modify_prescale(1);
+
+ if (machine().ui_input().pressed(IPT_OSD_8))
+ window->renderer().record();
+}
+
+
+template <typename T>
+sdl_window_info *sdl_osd_interface::focus_window(T const &event) const
+{
+ // FIXME: SDL does not properly report the window for certain versions of Ubuntu - is this still relevant?
+ if (m_enable_touch)
+ return window_from_id(event.windowID);
+ else
+ return m_focus_window;
+}
+
+
+unsigned sdl_osd_interface::map_pointer_device(SDL_TouchID device)
+{
+ auto devpos(std::lower_bound(
+ m_ptrdev_map.begin(),
+ m_ptrdev_map.end(),
+ device,
+ [] (std::pair<SDL_TouchID, unsigned> const &mapping, SDL_TouchID id)
+ {
+ return mapping.first < id;
+ }));
+ if ((m_ptrdev_map.end() == devpos) || (device != devpos->first))
+ {
+ devpos = m_ptrdev_map.emplace(devpos, device, m_next_ptrdev);
+ ++m_next_ptrdev;
+ }
+ return devpos->second;
+}
diff --git a/src/osd/sdl/osdsdl.h b/src/osd/sdl/osdsdl.h
index 155897f6d67..e1d472d9e45 100644
--- a/src/osd/sdl/osdsdl.h
+++ b/src/osd/sdl/osdsdl.h
@@ -5,42 +5,26 @@
#pragma once
+#include "sdlopts.h"
+
#include "modules/lib/osdobj_common.h"
#include "modules/osdmodule.h"
-#include "modules/font/font_module.h"
-
-//============================================================
-// Defines
-//============================================================
-
-#define SDLOPTION_INIPATH "inipath"
-#define SDLOPTION_SDLVIDEOFPS "sdlvideofps"
-#define SDLOPTION_USEALLHEADS "useallheads"
-#define SDLOPTION_ATTACH_WINDOW "attach_window"
-#define SDLOPTION_CENTERH "centerh"
-#define SDLOPTION_CENTERV "centerv"
-#define SDLOPTION_SCALEMODE "scalemode"
+#include <SDL2/SDL.h>
-#define SDLOPTION_WAITVSYNC "waitvsync"
-#define SDLOPTION_SYNCREFRESH "syncrefresh"
-#define SDLOPTION_KEYMAP "keymap"
-#define SDLOPTION_KEYMAP_FILE "keymap_file"
+#include <cassert>
+#include <chrono>
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <utility>
+#include <string>
+#include <vector>
-#define SDLOPTION_SIXAXIS "sixaxis"
-#if (USE_XINPUT)
-#define SDLOPTION_LIGHTGUNINDEX "lightgun_index"
-#endif
-#define SDLOPTION_AUDIODRIVER "audiodriver"
-#define SDLOPTION_VIDEODRIVER "videodriver"
-#define SDLOPTION_RENDERDRIVER "renderdriver"
-#define SDLOPTION_GL_LIB "gl_lib"
-
-#define SDLOPTVAL_OPENGL "opengl"
-#define SDLOPTVAL_SOFT "soft"
-#define SDLOPTVAL_SDL2ACCEL "accel"
-#define SDLOPTVAL_BGFX "bgfx"
+//============================================================
+// Defines
+//============================================================
#define SDLMAME_LED(x) "led" #x
@@ -56,60 +40,103 @@
#define SDLENV_AUDIODRIVER "SDL_AUDIODRIVER"
#define SDLENV_RENDERDRIVER "SDL_VIDEO_RENDERER"
-#define SDLMAME_SOUND_LOG "sound.log"
-
-#ifdef SDLMAME_MACOSX
-/* Vas Crabb: Default GL-lib for MACOSX */
-#define SDLOPTVAL_GLLIB "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
-#else
-#define SDLOPTVAL_GLLIB OSDOPTVAL_AUTO
-#endif
-
//============================================================
// TYPE DEFINITIONS
//============================================================
-class sdl_options : public osd_options
+template <typename EventRecord, typename EventType>
+class event_subscription_manager
{
-public:
- // construction/destruction
- sdl_options();
+public: // need extra public section for forward declaration
+ class subscriber;
- // performance options
- bool video_fps() const { return bool_value(SDLOPTION_SDLVIDEOFPS); }
+private:
+ class impl
+ {
+ public:
+ std::mutex m_mutex;
+ std::unordered_multimap<EventType, subscriber *> m_subs;
+ };
- // video options
- bool centerh() const { return bool_value(SDLOPTION_CENTERH); }
- bool centerv() const { return bool_value(SDLOPTION_CENTERV); }
- const char *scale_mode() const { return value(SDLOPTION_SCALEMODE); }
+ std::shared_ptr<impl> m_impl;
- // full screen options
-#ifdef SDLMAME_X11
- bool use_all_heads() const { return bool_value(SDLOPTION_USEALLHEADS); }
- const char *attach_window() const { return value(SDLOPTION_ATTACH_WINDOW); }
-#endif // SDLMAME_X11
+protected:
+ event_subscription_manager() : m_impl(new impl)
+ {
+ }
- // keyboard mapping
- bool keymap() const { return bool_value(SDLOPTION_KEYMAP); }
- const char *keymap_file() const { return value(SDLOPTION_KEYMAP_FILE); }
+ ~event_subscription_manager() = default;
- // joystick mapping
- bool sixaxis() const { return bool_value(SDLOPTION_SIXAXIS); }
+ std::mutex &subscription_mutex()
+ {
+ return m_impl->m_mutex;
+ }
- const char *video_driver() const { return value(SDLOPTION_VIDEODRIVER); }
- const char *render_driver() const { return value(SDLOPTION_RENDERDRIVER); }
- const char *audio_driver() const { return value(SDLOPTION_AUDIODRIVER); }
-#if USE_OPENGL
- const char *gl_lib() const { return value(SDLOPTION_GL_LIB); }
-#endif
+ void dispatch_event(EventType const &type, EventRecord const &event)
+ {
+ auto const matches = m_impl->m_subs.equal_range(type);
+ for (auto it = matches.first; matches.second != it; ++it)
+ it->second->handle_event(event);
+ }
-private:
- static const options_entry s_option_entries[];
+public:
+ class subscriber
+ {
+ public:
+ virtual void handle_event(EventRecord const &event) = 0;
+
+ protected:
+ subscriber() = default;
+
+ virtual ~subscriber()
+ {
+ unsubscribe();
+ }
+
+ template <typename T>
+ void subscribe(event_subscription_manager &host, T &&types)
+ {
+ assert(!m_host.lock());
+ assert(host.m_impl);
+
+ m_host = host.m_impl;
+
+ std::lock_guard<std::mutex> lock(host.m_impl->m_mutex);
+ for (auto const &t : types)
+ host.m_impl->m_subs.emplace(t, this);
+ }
+
+ void unsubscribe()
+ {
+ auto const host(m_host.lock());
+ m_host.reset();
+ if (host)
+ {
+ std::lock_guard<std::mutex> lock(host->m_mutex);
+ auto it = host->m_subs.begin();
+ while (host->m_subs.end() != it)
+ {
+ if (it->second == this)
+ it = host->m_subs.erase(it);
+ else
+ ++it;
+ }
+ }
+ }
+
+ private:
+ std::weak_ptr<impl> m_host;
+ };
};
-class sdl_osd_interface : public osd_common_t
+using sdl_event_manager = event_subscription_manager<SDL_Event, uint32_t>;
+
+
+class sdl_window_info;
+
+class sdl_osd_interface : public osd_common_t, public sdl_event_manager
{
public:
// construction/destruction
@@ -119,38 +146,69 @@ public:
// general overridables
virtual void init(running_machine &machine) override;
virtual void update(bool skip_redraw) override;
- virtual void input_update() override;
+ virtual void input_update(bool relative_reset) override;
+ virtual void check_osd_inputs() override;
// input overridables
virtual void customize_input_type_list(std::vector<input_type_entry> &typelist) override;
- virtual void video_register() override;
-
virtual bool video_init() override;
virtual bool window_init() override;
virtual void video_exit() override;
virtual void window_exit() override;
- // sdl specific
- void poll_inputs(running_machine &machine);
+ // SDL-specific
+ virtual bool has_focus() const override { return bool(m_focus_window); }
void release_keys();
bool should_hide_mouse();
void process_events_buf();
virtual sdl_options &options() override { return m_options; }
+ virtual void process_events() override;
+
protected:
virtual void build_slider_list() override;
virtual void update_slider_list() override;
private:
+ enum
+ {
+ MODIFIER_KEY_LCTRL = 0x01,
+ MODIFIER_KEY_RCTRL = 0x02,
+ MODIFIER_KEY_LSHIFT = 0x04,
+ MODIFIER_KEY_RSHIFT = 0x08,
+
+ MODIFIER_KEY_CTRL = MODIFIER_KEY_LCTRL | MODIFIER_KEY_RCTRL,
+ MODIFIER_KEY_SHIFT = MODIFIER_KEY_LSHIFT | MODIFIER_KEY_RSHIFT
+ };
+
virtual void osd_exit() override;
void extract_video_config();
void output_oslog(const char *buffer);
+ void process_window_event(SDL_Event const &event);
+ void process_textinput_event(SDL_Event const &event);
+
+ bool mouse_over_window() const { return m_mouse_over_window > 0; }
+ template <typename T> sdl_window_info *focus_window(T const &event) const;
+
+ unsigned map_pointer_device(SDL_TouchID device);
+
sdl_options &m_options;
+ sdl_window_info *m_focus_window;
+ int m_mouse_over_window;
+ uint8_t m_modifier_keys;
+
+ std::chrono::steady_clock::time_point m_last_click_time;
+ int m_last_click_x;
+ int m_last_click_y;
+
+ bool m_enable_touch;
+ unsigned m_next_ptrdev;
+ std::vector<std::pair<SDL_TouchID, unsigned> > m_ptrdev_map;
};
//============================================================
diff --git a/src/osd/sdl/sdlmain.cpp b/src/osd/sdl/sdlmain.cpp
index f238c7bd2cd..1933bde1de6 100644
--- a/src/osd/sdl/sdlmain.cpp
+++ b/src/osd/sdl/sdlmain.cpp
@@ -2,12 +2,30 @@
// copyright-holders:Olivier Galibert, R. Belmont
//============================================================
//
-// sdlmain.c - main file for SDLMAME.
+// sdlmain.cpp - main file for SDLMAME.
//
// SDLMAME by Olivier Galibert and R. Belmont
//
//============================================================
+// OSD headers
+#include "osdsdl.h"
+#include "modules/lib/osdlib.h"
+#include "modules/diagnostics/diagnostics_module.h"
+
+// MAME headers
+#include "emu.h"
+#include "emuopts.h"
+#include "main.h"
+#include "video.h"
+
+#include "corestr.h"
+
+#include "osdepend.h"
+#include "strconv.h"
+
+#include <SDL2/SDL.h>
+
// only for oslog callback
#include <functional>
@@ -28,40 +46,6 @@
#include <unistd.h>
#endif
-// only for strconv.h
-#if defined(SDLMAME_WIN32)
-#include <windows.h>
-#endif
-
-#include <SDL2/SDL.h>
-
-// MAME headers
-#include "corestr.h"
-#include "osdepend.h"
-#include "emu.h"
-#include "emuopts.h"
-#include "strconv.h"
-
-// OSD headers
-#include "video.h"
-#include "osdsdl.h"
-#include "modules/lib/osdlib.h"
-#include "modules/diagnostics/diagnostics_module.h"
-
-//============================================================
-// OPTIONS
-//============================================================
-
-#ifndef INI_PATH
-#if defined(SDLMAME_WIN32)
- #define INI_PATH ".;ini;ini/presets"
-#elif defined(SDLMAME_MACOSX)
- #define INI_PATH "$HOME/Library/Application Support/APP_NAME;$HOME/.APP_NAME;.;ini"
-#else
- #define INI_PATH "$HOME/.APP_NAME;.;ini"
-#endif // MACOSX
-#endif // INI_PATH
-
//============================================================
// Global variables
@@ -71,81 +55,6 @@
int sdl_entered_debugger;
#endif
-//============================================================
-// Local variables
-//============================================================
-
-const options_entry sdl_options::s_option_entries[] =
-{
- { SDLOPTION_INIPATH, INI_PATH, core_options::option_type::STRING, "path to ini files" },
-
- // performance options
- { nullptr, nullptr, core_options::option_type::HEADER, "SDL PERFORMANCE OPTIONS" },
- { SDLOPTION_SDLVIDEOFPS, "0", core_options::option_type::BOOLEAN, "show sdl video performance" },
- // video options
- { nullptr, nullptr, core_options::option_type::HEADER, "SDL VIDEO OPTIONS" },
-// OS X can be trusted to have working hardware OpenGL, so default to it on for the best user experience
- { SDLOPTION_CENTERH, "1", core_options::option_type::BOOLEAN, "center horizontally within the view area" },
- { SDLOPTION_CENTERV, "1", core_options::option_type::BOOLEAN, "center vertically within the view area" },
- { SDLOPTION_SCALEMODE ";sm", OSDOPTVAL_NONE, core_options::option_type::STRING, "Scale mode: none, hwblit, hwbest, yv12, yuy2, yv12x2, yuy2x2 (-video soft only)" },
-
- // full screen options
-#ifdef SDLMAME_X11
- { nullptr, nullptr, core_options::option_type::HEADER, "SDL FULL SCREEN OPTIONS" },
- { SDLOPTION_USEALLHEADS, "0", core_options::option_type::BOOLEAN, "split full screen image across monitors" },
- { SDLOPTION_ATTACH_WINDOW, "", core_options::option_type::STRING, "attach to arbitrary window" },
-#endif // SDLMAME_X11
-
- // keyboard mapping
- { nullptr, nullptr, core_options::option_type::HEADER, "SDL KEYBOARD MAPPING" },
- { SDLOPTION_KEYMAP, "0", core_options::option_type::BOOLEAN, "enable keymap" },
- { SDLOPTION_KEYMAP_FILE, "keymap.dat", core_options::option_type::STRING, "keymap filename" },
-
- // joystick mapping
- { nullptr, nullptr, core_options::option_type::HEADER, "SDL JOYSTICK MAPPING" },
- { SDLOPTION_SIXAXIS, "0", core_options::option_type::BOOLEAN, "use special handling for PS3 Sixaxis controllers" },
-
-#if (USE_XINPUT)
- // lightgun mapping
- { nullptr, nullptr, core_options::option_type::HEADER, "SDL LIGHTGUN MAPPING" },
- { SDLOPTION_LIGHTGUNINDEX "1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #1" },
- { SDLOPTION_LIGHTGUNINDEX "2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #2" },
- { SDLOPTION_LIGHTGUNINDEX "3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #3" },
- { SDLOPTION_LIGHTGUNINDEX "4", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #4" },
- { SDLOPTION_LIGHTGUNINDEX "5", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #5" },
- { SDLOPTION_LIGHTGUNINDEX "6", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #6" },
- { SDLOPTION_LIGHTGUNINDEX "7", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #7" },
- { SDLOPTION_LIGHTGUNINDEX "8", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #8" },
-#endif
-
- // SDL low level driver options
- { nullptr, nullptr, core_options::option_type::HEADER, "SDL LOW-LEVEL DRIVER OPTIONS" },
- { SDLOPTION_VIDEODRIVER ";vd", OSDOPTVAL_AUTO, core_options::option_type::STRING, "SDL video driver to use ('x11', 'directfb', ... or 'auto' for SDL default" },
- { SDLOPTION_RENDERDRIVER ";rd", OSDOPTVAL_AUTO, core_options::option_type::STRING, "SDL render driver to use ('software', 'opengl', 'directfb' ... or 'auto' for SDL default" },
- { SDLOPTION_AUDIODRIVER ";ad", OSDOPTVAL_AUTO, core_options::option_type::STRING, "SDL audio driver to use ('alsa', 'arts', ... or 'auto' for SDL default" },
-#if USE_OPENGL
- { SDLOPTION_GL_LIB, SDLOPTVAL_GLLIB, core_options::option_type::STRING, "alternative libGL.so to use; 'auto' for system default" },
-#endif
-
- // End of list
- { nullptr }
-};
-
-//============================================================
-// sdl_options
-//============================================================
-
-sdl_options::sdl_options()
-: osd_options()
-{
-#if defined (SDLMAME_ANDROID)
- chdir (SDL_AndroidGetExternalStoragePath());
-#endif
- std::string ini_path(INI_PATH);
- add_entries(sdl_options::s_option_entries);
- strreplace(ini_path,"APP_NAME", emulator_info::get_appname_lower());
- set_default_value(SDLOPTION_INIPATH, std::move(ini_path));
-}
//============================================================
// main
@@ -202,297 +111,3 @@ int main(int argc, char** argv)
exit(res);
}
-
-//============================================================
-// constructor
-//============================================================
-
-sdl_osd_interface::sdl_osd_interface(sdl_options &options)
-: osd_common_t(options), m_options(options)
-{
-}
-
-
-//============================================================
-// destructor
-//============================================================
-
-sdl_osd_interface::~sdl_osd_interface()
-{
-}
-
-
-//============================================================
-// osd_exit
-//============================================================
-
-void sdl_osd_interface::osd_exit()
-{
- osd_common_t::osd_exit();
-
- SDL_QuitSubSystem(SDL_INIT_VIDEO);
-}
-
-//============================================================
-// defines_verbose
-//============================================================
-
-#define MAC_EXPAND_STR(_m) #_m
-#define MACRO_VERBOSE(_mac) \
- do { \
- if (strcmp(MAC_EXPAND_STR(_mac), #_mac) != 0) \
- osd_printf_verbose("%s=%s ", #_mac, MAC_EXPAND_STR(_mac)); \
- } while (0)
-
-#define _SDL_VER #SDL_MAJOR_VERSION "." #SDL_MINOR_VERSION "." #SDL_PATCHLEVEL
-
-static void defines_verbose(void)
-{
- osd_printf_verbose("Build version: %s\n", emulator_info::get_build_version());
- osd_printf_verbose("Build architecure: ");
- MACRO_VERBOSE(SDLMAME_ARCH);
- osd_printf_verbose("\n");
- osd_printf_verbose("Build defines 1: ");
- MACRO_VERBOSE(SDLMAME_UNIX);
- MACRO_VERBOSE(SDLMAME_X11);
- MACRO_VERBOSE(SDLMAME_WIN32);
- MACRO_VERBOSE(SDLMAME_MACOSX);
- MACRO_VERBOSE(SDLMAME_DARWIN);
- MACRO_VERBOSE(SDLMAME_LINUX);
- MACRO_VERBOSE(SDLMAME_SOLARIS);
- MACRO_VERBOSE(SDLMAME_IRIX);
- MACRO_VERBOSE(SDLMAME_BSD);
- osd_printf_verbose("\n");
- osd_printf_verbose("Build defines 1: ");
- MACRO_VERBOSE(LSB_FIRST);
- MACRO_VERBOSE(PTR64);
- MACRO_VERBOSE(MAME_NOASM);
- MACRO_VERBOSE(MAME_DEBUG);
- MACRO_VERBOSE(BIGENDIAN);
- MACRO_VERBOSE(CPP_COMPILE);
- MACRO_VERBOSE(SYNC_IMPLEMENTATION);
- osd_printf_verbose("\n");
- osd_printf_verbose("SDL/OpenGL defines: ");
- osd_printf_verbose("SDL_COMPILEDVERSION=%d ", SDL_COMPILEDVERSION);
- MACRO_VERBOSE(USE_OPENGL);
- MACRO_VERBOSE(USE_DISPATCH_GL);
- osd_printf_verbose("\n");
- osd_printf_verbose("Compiler defines A: ");
- MACRO_VERBOSE(__GNUC__);
- MACRO_VERBOSE(__GNUC_MINOR__);
- MACRO_VERBOSE(__GNUC_PATCHLEVEL__);
- MACRO_VERBOSE(__VERSION__);
- osd_printf_verbose("\n");
- osd_printf_verbose("Compiler defines B: ");
- MACRO_VERBOSE(__amd64__);
- MACRO_VERBOSE(__x86_64__);
- MACRO_VERBOSE(__unix__);
- MACRO_VERBOSE(__i386__);
- MACRO_VERBOSE(__ppc__);
- MACRO_VERBOSE(__ppc64__);
- osd_printf_verbose("\n");
- osd_printf_verbose("Compiler defines C: ");
- MACRO_VERBOSE(_FORTIFY_SOURCE);
- MACRO_VERBOSE(__USE_FORTIFY_LEVEL);
- osd_printf_verbose("\n");
-}
-
-//============================================================
-// osd_sdl_info
-//============================================================
-
-static void osd_sdl_info(void)
-{
- int i, num = SDL_GetNumVideoDrivers();
-
- osd_printf_verbose("Available videodrivers: ");
- for (i=0;i<num;i++)
- {
- const char *name = SDL_GetVideoDriver(i);
- osd_printf_verbose("%s ", name);
- }
- osd_printf_verbose("\n");
- osd_printf_verbose("Current Videodriver: %s\n", SDL_GetCurrentVideoDriver());
- num = SDL_GetNumVideoDisplays();
- for (i=0;i<num;i++)
- {
- SDL_DisplayMode mode;
- int j;
-
- osd_printf_verbose("\tDisplay #%d\n", i);
- if (SDL_GetDesktopDisplayMode(i, &mode))
- osd_printf_verbose("\t\tDesktop Mode: %dx%d-%d@%d\n", mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate);
- if (SDL_GetCurrentDisplayMode(i, &mode))
- osd_printf_verbose("\t\tCurrent Display Mode: %dx%d-%d@%d\n", mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate);
- osd_printf_verbose("\t\tRenderdrivers:\n");
- for (j=0; j<SDL_GetNumRenderDrivers(); j++)
- {
- SDL_RendererInfo info;
- SDL_GetRenderDriverInfo(j, &info);
- osd_printf_verbose("\t\t\t%10s (%dx%d)\n", info.name, info.max_texture_width, info.max_texture_height);
- }
- }
-
- osd_printf_verbose("Available audio drivers: \n");
- num = SDL_GetNumAudioDrivers();
- for (i=0;i<num;i++)
- {
- osd_printf_verbose("\t%-20s\n", SDL_GetAudioDriver(i));
- }
-}
-
-
-//============================================================
-// video_register
-//============================================================
-
-void sdl_osd_interface::video_register()
-{
- video_options_add("soft", nullptr);
- video_options_add("accel", nullptr);
-#if USE_OPENGL
- video_options_add("opengl", nullptr);
-#endif
- video_options_add("bgfx", nullptr);
- //video_options_add("auto", nullptr); // making d3d video default one
-}
-
-
-//============================================================
-// output_oslog
-//============================================================
-
-void sdl_osd_interface::output_oslog(const char *buffer)
-{
- fputs(buffer, stderr);
-}
-
-
-//============================================================
-// osd_setup_osd_specific_emu_options
-//============================================================
-
-void osd_setup_osd_specific_emu_options(emu_options &opts)
-{
- opts.add_entries(osd_options::s_option_entries);
-}
-
-
-//============================================================
-// init
-//============================================================
-
-void sdl_osd_interface::init(running_machine &machine)
-{
- // call our parent
- osd_common_t::init(machine);
-
- const char *stemp;
-
- // determine if we are benchmarking, and adjust options appropriately
- int bench = options().bench();
- if (bench > 0)
- {
- options().set_value(OPTION_SLEEP, false, OPTION_PRIORITY_MAXIMUM);
- options().set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM);
- options().set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM);
- options().set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM);
- options().set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM);
- }
-
- // Some driver options - must be before audio init!
- stemp = options().audio_driver();
- if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0)
- {
- osd_printf_verbose("Setting SDL audiodriver '%s' ...\n", stemp);
- osd_setenv(SDLENV_AUDIODRIVER, stemp, 1);
- }
-
- stemp = options().video_driver();
- if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0)
- {
- osd_printf_verbose("Setting SDL videodriver '%s' ...\n", stemp);
- osd_setenv(SDLENV_VIDEODRIVER, stemp, 1);
- }
-
- stemp = options().render_driver();
- if (stemp != nullptr)
- {
- if (strcmp(stemp, OSDOPTVAL_AUTO) != 0)
- {
- osd_printf_verbose("Setting SDL renderdriver '%s' ...\n", stemp);
- //osd_setenv(SDLENV_RENDERDRIVER, stemp, 1);
- SDL_SetHint(SDL_HINT_RENDER_DRIVER, stemp);
- }
- else
- {
-#if defined(SDLMAME_WIN32)
- // OpenGL renderer has less issues with mode switching on windows
- osd_printf_verbose("Setting SDL renderdriver '%s' ...\n", "opengl");
- //osd_setenv(SDLENV_RENDERDRIVER, stemp, 1);
- SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
-#endif
- }
- }
-
- /* Set the SDL environment variable for drivers wanting to load the
- * lib at startup.
- */
-#if USE_OPENGL
- /* FIXME: move lib loading code from drawogl.c here */
-
- stemp = options().gl_lib();
- if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0)
- {
- osd_setenv("SDL_VIDEO_GL_DRIVER", stemp, 1);
- osd_printf_verbose("Setting SDL_VIDEO_GL_DRIVER = '%s' ...\n", stemp);
- }
-#endif
-
- /* get number of processors */
- stemp = options().numprocessors();
-
- osd_num_processors = 0;
-
- if (strcmp(stemp, "auto") != 0)
- {
- osd_num_processors = atoi(stemp);
- if (osd_num_processors < 1)
- {
- osd_printf_warning("numprocessors < 1 doesn't make much sense. Assuming auto ...\n");
- osd_num_processors = 0;
- }
- }
-
- /* Initialize SDL */
-
- if (SDL_InitSubSystem(SDL_INIT_VIDEO))
- {
- osd_printf_error("Could not initialize SDL %s\n", SDL_GetError());
- exit(-1);
- }
-
- // bgfx does not work with wayland
- if ((strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) && ((strcmp(options().video(), "auto") == 0) || (strcmp(options().video(), "bgfx") == 0)))
- fatalerror("Error: BGFX video does not work with wayland videodriver. Please change either of the options.");
-
- osd_sdl_info();
-
- defines_verbose();
-
- osd_common_t::init_subsystems();
-
- if (options().oslog())
- {
- using namespace std::placeholders;
- machine.add_logerror_callback(std::bind(&sdl_osd_interface::output_oslog, this, _1));
- }
-
-
-
-#ifdef SDLMAME_EMSCRIPTEN
- SDL_EventState(SDL_TEXTINPUT, SDL_FALSE);
-#else
- SDL_EventState(SDL_TEXTINPUT, SDL_TRUE);
-#endif
-}
diff --git a/src/osd/sdl/sdlopts.cpp b/src/osd/sdl/sdlopts.cpp
new file mode 100644
index 00000000000..f08dc41f963
--- /dev/null
+++ b/src/osd/sdl/sdlopts.cpp
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont
+
+#include "sdlopts.h"
+
+// emu
+#include "main.h"
+
+// lib/util
+#include "util/corestr.h"
+
+#include <SDL2/SDL.h>
+
+#include <string>
+
+#if defined(SDLMAME_ANDROID)
+#include "unistd.h"
+#endif
+
+
+namespace {
+
+//============================================================
+// OPTIONS
+//============================================================
+
+#ifndef INI_PATH
+#if defined(SDLMAME_WIN32)
+ #define INI_PATH ".;ini;ini/presets"
+#elif defined(SDLMAME_MACOSX)
+ #define INI_PATH "$HOME/Library/Application Support/APP_NAME;$HOME/.APP_NAME;.;ini"
+#else
+ #define INI_PATH "$HOME/.APP_NAME;.;ini"
+#endif // MACOSX
+#endif // INI_PATH
+
+
+//============================================================
+// Local variables
+//============================================================
+
+const options_entry f_sdl_option_entries[] =
+{
+ { SDLOPTION_INIPATH, INI_PATH, core_options::option_type::MULTIPATH, "path to ini files" },
+
+ // performance options
+ { nullptr, nullptr, core_options::option_type::HEADER, "SDL PERFORMANCE OPTIONS" },
+ { SDLOPTION_SDLVIDEOFPS, "0", core_options::option_type::BOOLEAN, "show sdl video performance" },
+ // video options
+ { nullptr, nullptr, core_options::option_type::HEADER, "SDL VIDEO OPTIONS" },
+// OS X can be trusted to have working hardware OpenGL, so default to it on for the best user experience
+ { SDLOPTION_CENTERH, "1", core_options::option_type::BOOLEAN, "center horizontally within the view area" },
+ { SDLOPTION_CENTERV, "1", core_options::option_type::BOOLEAN, "center vertically within the view area" },
+ { SDLOPTION_SCALEMODE ";sm", OSDOPTVAL_NONE, core_options::option_type::STRING, "Scale mode: none, hwblit, hwbest, yv12, yuy2, yv12x2, yuy2x2 (-video soft only)" },
+
+ // full screen options
+#ifdef SDLMAME_X11
+ { nullptr, nullptr, core_options::option_type::HEADER, "SDL FULL SCREEN OPTIONS" },
+ { SDLOPTION_USEALLHEADS, "0", core_options::option_type::BOOLEAN, "split full screen image across monitors" },
+ { SDLOPTION_ATTACH_WINDOW, "", core_options::option_type::STRING, "attach to arbitrary window" },
+#endif // SDLMAME_X11
+
+ // keyboard mapping
+ { nullptr, nullptr, core_options::option_type::HEADER, "SDL KEYBOARD MAPPING" },
+ { SDLOPTION_KEYMAP, "0", core_options::option_type::BOOLEAN, "enable keymap" },
+ { SDLOPTION_KEYMAP_FILE, "keymap.dat", core_options::option_type::PATH, "keymap filename" },
+
+ // joystick mapping
+ { nullptr, nullptr, core_options::option_type::HEADER, "SDL INPUT OPTIONS" },
+ { SDLOPTION_ENABLE_TOUCH, "0", core_options::option_type::BOOLEAN, "enable touch input support" },
+ { SDLOPTION_SIXAXIS, "0", core_options::option_type::BOOLEAN, "use special handling for PS3 Sixaxis controllers" },
+
+#if (USE_XINPUT)
+ // lightgun mapping
+ { nullptr, nullptr, core_options::option_type::HEADER, "SDL LIGHTGUN MAPPING" },
+ { SDLOPTION_LIGHTGUNINDEX "1", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #1" },
+ { SDLOPTION_LIGHTGUNINDEX "2", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #2" },
+ { SDLOPTION_LIGHTGUNINDEX "3", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #3" },
+ { SDLOPTION_LIGHTGUNINDEX "4", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #4" },
+ { SDLOPTION_LIGHTGUNINDEX "5", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #5" },
+ { SDLOPTION_LIGHTGUNINDEX "6", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #6" },
+ { SDLOPTION_LIGHTGUNINDEX "7", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #7" },
+ { SDLOPTION_LIGHTGUNINDEX "8", OSDOPTVAL_AUTO, core_options::option_type::STRING, "name of lightgun mapped to lightgun #8" },
+#endif
+
+ // SDL low level driver options
+ { nullptr, nullptr, core_options::option_type::HEADER, "SDL LOW-LEVEL DRIVER OPTIONS" },
+ { SDLOPTION_VIDEODRIVER ";vd", OSDOPTVAL_AUTO, core_options::option_type::STRING, "SDL video driver to use ('x11', 'directfb', ... or 'auto' for SDL default" },
+ { SDLOPTION_RENDERDRIVER ";rd", OSDOPTVAL_AUTO, core_options::option_type::STRING, "SDL render driver to use ('software', 'opengl', 'directfb' ... or 'auto' for SDL default" },
+ { SDLOPTION_AUDIODRIVER ";ad", OSDOPTVAL_AUTO, core_options::option_type::STRING, "SDL audio driver to use ('alsa', 'arts', ... or 'auto' for SDL default" },
+#if USE_OPENGL
+ { SDLOPTION_GL_LIB, SDLOPTVAL_GLLIB, core_options::option_type::STRING, "alternative libGL.so to use; 'auto' for system default" },
+#endif
+
+ // End of list
+ { nullptr }
+};
+
+} // anonymous namespace
+
+
+//============================================================
+// sdl_options
+//============================================================
+
+sdl_options::sdl_options() : osd_options()
+{
+#if defined(SDLMAME_ANDROID)
+ chdir(SDL_AndroidGetExternalStoragePath()); // FIXME: why is this here of all places?
+#endif
+ std::string ini_path(INI_PATH);
+ add_entries(f_sdl_option_entries);
+ strreplace(ini_path, "APP_NAME", emulator_info::get_appname_lower());
+ set_default_value(SDLOPTION_INIPATH, std::move(ini_path));
+}
+
+
+//============================================================
+// osd_setup_osd_specific_emu_options
+//============================================================
+
+void osd_setup_osd_specific_emu_options(emu_options &opts)
+{
+ opts.add_entries(osd_options::s_option_entries);
+ opts.add_entries(f_sdl_option_entries);
+}
diff --git a/src/osd/sdl/sdlopts.h b/src/osd/sdl/sdlopts.h
new file mode 100644
index 00000000000..fe75e097407
--- /dev/null
+++ b/src/osd/sdl/sdlopts.h
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont
+#ifndef MAME_OSD_SDL_SDLOPTS_H
+#define MAME_OSD_SDL_SDLOPTS_H
+
+#pragma once
+
+#include "modules/lib/osdobj_common.h"
+
+
+//============================================================
+// Option identifiers
+//============================================================
+
+#define SDLOPTION_INIPATH "inipath"
+#define SDLOPTION_SDLVIDEOFPS "sdlvideofps"
+#define SDLOPTION_USEALLHEADS "useallheads"
+#define SDLOPTION_ATTACH_WINDOW "attach_window"
+#define SDLOPTION_CENTERH "centerh"
+#define SDLOPTION_CENTERV "centerv"
+
+#define SDLOPTION_SCALEMODE "scalemode"
+
+#define SDLOPTION_WAITVSYNC "waitvsync"
+#define SDLOPTION_SYNCREFRESH "syncrefresh"
+#define SDLOPTION_KEYMAP "keymap"
+#define SDLOPTION_KEYMAP_FILE "keymap_file"
+
+#define SDLOPTION_ENABLE_TOUCH "enable_touch"
+#define SDLOPTION_SIXAXIS "sixaxis"
+#if defined(USE_XINPUT) && USE_XINPUT
+#define SDLOPTION_LIGHTGUNINDEX "lightgun_index"
+#endif
+
+#define SDLOPTION_AUDIODRIVER "audiodriver"
+#define SDLOPTION_VIDEODRIVER "videodriver"
+#define SDLOPTION_RENDERDRIVER "renderdriver"
+#define SDLOPTION_GL_LIB "gl_lib"
+
+
+//============================================================
+// Option values
+//============================================================
+
+#define SDLOPTVAL_OPENGL "opengl"
+#define SDLOPTVAL_SOFT "soft"
+#define SDLOPTVAL_SDL2ACCEL "accel"
+#define SDLOPTVAL_BGFX "bgfx"
+
+#ifdef SDLMAME_MACOSX
+/* Vas Crabb: Default GL-lib for MACOSX */
+#define SDLOPTVAL_GLLIB "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
+#else
+#define SDLOPTVAL_GLLIB OSDOPTVAL_AUTO
+#endif
+
+
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+class sdl_options : public osd_options
+{
+public:
+ // construction/destruction
+ sdl_options();
+
+ // performance options
+ bool video_fps() const { return bool_value(SDLOPTION_SDLVIDEOFPS); }
+
+ // video options
+ bool centerh() const { return bool_value(SDLOPTION_CENTERH); }
+ bool centerv() const { return bool_value(SDLOPTION_CENTERV); }
+ const char *scale_mode() const { return value(SDLOPTION_SCALEMODE); }
+
+ // full screen options
+#if defined(SDLMAME_X11)
+ bool use_all_heads() const { return bool_value(SDLOPTION_USEALLHEADS); }
+ const char *attach_window() const { return value(SDLOPTION_ATTACH_WINDOW); }
+#endif // SDLMAME_X11
+
+ // keyboard mapping
+ bool keymap() const { return bool_value(SDLOPTION_KEYMAP); }
+ const char *keymap_file() const { return value(SDLOPTION_KEYMAP_FILE); }
+
+ // input options
+ bool enable_touch() const { return bool_value(SDLOPTION_ENABLE_TOUCH); }
+ bool sixaxis() const { return bool_value(SDLOPTION_SIXAXIS); }
+
+ const char *video_driver() const { return value(SDLOPTION_VIDEODRIVER); }
+ const char *render_driver() const { return value(SDLOPTION_RENDERDRIVER); }
+ const char *audio_driver() const { return value(SDLOPTION_AUDIODRIVER); }
+#if USE_OPENGL
+ const char *gl_lib() const { return value(SDLOPTION_GL_LIB); }
+#endif
+};
+
+#endif // MAME_OSD_SDL_SDLOPTS_H
diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp
index 9d73767cc6e..8fe836aabf2 100644
--- a/src/osd/sdl/video.cpp
+++ b/src/osd/sdl/video.cpp
@@ -2,30 +2,28 @@
// copyright-holders:Olivier Galibert, R. Belmont
//============================================================
//
-// video.c - SDL video handling
+// video.cpp - SDL video handling
//
// SDLMAME by Olivier Galibert and R. Belmont
//
//============================================================
-#include <SDL2/SDL.h>
-
-// MAME headers
-#include "emu.h"
-#include "rendutil.h"
-#include "ui/uimain.h"
-#include "emuopts.h"
-#include "uiinput.h"
+#include "window.h"
// MAMEOS headers
-#include "window.h"
#include "osdsdl.h"
#include "modules/lib/osdlib.h"
#include "modules/monitor/monitor_module.h"
+#include "modules/render/render_module.h"
-//============================================================
-// CONSTANTS
-//============================================================
+// MAME headers
+#include "emu.h"
+#include "emuopts.h"
+#include "main.h"
+#include "rendutil.h"
+#include "uiinput.h"
+
+#include <SDL2/SDL.h>
//============================================================
@@ -34,17 +32,11 @@
osd_video_config video_config;
-//============================================================
-// LOCAL VARIABLES
-//============================================================
-
//============================================================
// PROTOTYPES
//============================================================
-static void check_osd_inputs(running_machine &machine);
-
static void get_resolution(const char *defdata, const char *data, osd_window_config *config, int report_error);
@@ -70,16 +62,19 @@ bool sdl_osd_interface::video_init()
for (index = 0; index < video_config.numscreens; index++)
{
osd_window_config conf;
- memset(&conf, 0, sizeof(conf));
get_resolution(options().resolution(), options().resolution(index), &conf, true);
// create window ...
- std::shared_ptr<sdl_window_info> win = std::make_shared<sdl_window_info>(machine(), index, m_monitor_module->pick_monitor(reinterpret_cast<osd_options &>(options()), index), &conf);
-
+ auto win = std::make_unique<sdl_window_info>(machine(), *m_render, index, m_monitor_module->pick_monitor(reinterpret_cast<osd_options &>(options()), index), &conf);
if (win->window_init())
return false;
+
+ s_window_list.emplace_back(std::move(win));
}
+ if (m_render->is_interactive())
+ SDL_RaiseWindow(dynamic_cast<sdl_window_info &>(*osd_common_t::s_window_list.front()).platform_window());
+
return true;
}
@@ -104,7 +99,7 @@ void sdl_osd_interface::update(bool skip_redraw)
if (!skip_redraw)
{
// profiler_mark(PROFILER_BLIT);
- for (auto window : osd_common_t::s_window_list)
+ for (auto const &window : osd_common_t::window_list())
window->update();
// profiler_mark(PROFILER_END);
}
@@ -115,60 +110,11 @@ void sdl_osd_interface::update(bool skip_redraw)
}
//============================================================
-// input_update
-//============================================================
-
-void sdl_osd_interface::input_update()
-{
- // poll the joystick values here
- process_events_buf();
- poll_inputs(machine());
- check_osd_inputs(machine());
-}
-
-//============================================================
-// check_osd_inputs
-//============================================================
-
-static void check_osd_inputs(running_machine &machine)
-{
- // check for toggling fullscreen mode
- if (machine.ui_input().pressed(IPT_OSD_1))
- {
- for (auto curwin : osd_common_t::s_window_list)
- std::static_pointer_cast<sdl_window_info>(curwin)->toggle_full_screen();
- }
-
- auto window = osd_common_t::s_window_list.front();
-
- if (USE_OPENGL)
- {
- //FIXME: on a per window basis
- if (machine.ui_input().pressed(IPT_OSD_5))
- {
- video_config.filter = !video_config.filter;
- machine.ui().popup_time(1, "Filter %s", video_config.filter? "enabled":"disabled");
- }
- }
-
- if (machine.ui_input().pressed(IPT_OSD_6))
- std::static_pointer_cast<sdl_window_info>(window)->modify_prescale(-1);
-
- if (machine.ui_input().pressed(IPT_OSD_7))
- std::static_pointer_cast<sdl_window_info>(window)->modify_prescale(1);
-
- if (machine.ui_input().pressed(IPT_OSD_8))
- window->renderer().record();
-}
-
-//============================================================
// extract_video_config
//============================================================
void sdl_osd_interface::extract_video_config()
{
- const char *stemp;
-
video_config.perftest = options().video_fps();
// global options: extract the data
@@ -184,47 +130,6 @@ void sdl_osd_interface::extract_video_config()
if (machine().debug_flags & DEBUG_FLAG_OSD_ENABLED)
video_config.windowed = true;
- // default to working video please
- video_config.novideo = 0;
-
- // video options: extract the data
- stemp = options().video();
- if (strcmp(stemp, "auto") == 0)
- {
-#if (defined SDLMAME_EMSCRIPTEN)
- stemp = "soft";
-#else
- stemp = "bgfx";
-#endif
- }
- if (strcmp(stemp, SDLOPTVAL_SOFT) == 0)
- video_config.mode = VIDEO_MODE_SOFT;
- else if (strcmp(stemp, OSDOPTVAL_NONE) == 0)
- {
- video_config.mode = VIDEO_MODE_SOFT;
- video_config.novideo = 1;
-
- if (!emulator_info::standalone() && options().seconds_to_run() == 0)
- osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n");
- }
-#if (USE_OPENGL)
- else if (strcmp(stemp, SDLOPTVAL_OPENGL) == 0)
- video_config.mode = VIDEO_MODE_OPENGL;
-#endif
- else if ((strcmp(stemp, SDLOPTVAL_SDL2ACCEL) == 0))
- {
- video_config.mode = VIDEO_MODE_SDL2ACCEL;
- }
- else if (strcmp(stemp, SDLOPTVAL_BGFX) == 0)
- {
- video_config.mode = VIDEO_MODE_BGFX;
- }
- else
- {
- osd_printf_warning("Invalid video value %s; reverting to software\n", stemp);
- video_config.mode = VIDEO_MODE_SOFT;
- }
-
video_config.switchres = options().switch_res();
video_config.centerh = options().centerh();
video_config.centerv = options().centerv();
@@ -236,69 +141,12 @@ void sdl_osd_interface::extract_video_config()
video_config.syncrefresh = 0;
}
- if (video_config.prescale < 1 || video_config.prescale > 8)
+ if (video_config.prescale < 1 || video_config.prescale > 20)
{
osd_printf_warning("Invalid prescale option, reverting to '1'\n");
video_config.prescale = 1;
}
- #if (USE_OPENGL)
- // default to working video please
- video_config.forcepow2texture = options().gl_force_pow2_texture();
- video_config.allowtexturerect = !(options().gl_no_texture_rect());
- video_config.vbo = options().gl_vbo();
- video_config.pbo = options().gl_pbo();
- video_config.glsl = options().gl_glsl();
- if ( video_config.glsl )
- {
- int i;
-
- video_config.glsl_filter = options().glsl_filter();
-
- video_config.glsl_shader_mamebm_num=0;
-
- for(i=0; i<GLSL_SHADER_MAX; i++)
- {
- stemp = options().shader_mame(i);
- if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0)
- {
- video_config.glsl_shader_mamebm[i] = (char *) malloc(strlen(stemp)+1);
- strcpy(video_config.glsl_shader_mamebm[i], stemp);
- video_config.glsl_shader_mamebm_num++;
- } else {
- video_config.glsl_shader_mamebm[i] = nullptr;
- }
- }
-
- video_config.glsl_shader_scrn_num=0;
-
- for(i=0; i<GLSL_SHADER_MAX; i++)
- {
- stemp = options().shader_screen(i);
- if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0)
- {
- video_config.glsl_shader_scrn[i] = (char *) malloc(strlen(stemp)+1);
- strcpy(video_config.glsl_shader_scrn[i], stemp);
- video_config.glsl_shader_scrn_num++;
- } else {
- video_config.glsl_shader_scrn[i] = nullptr;
- }
- }
- } else {
- int i;
- video_config.glsl_filter = 0;
- video_config.glsl_shader_mamebm_num=0;
- for(i=0; i<GLSL_SHADER_MAX; i++)
- {
- video_config.glsl_shader_mamebm[i] = nullptr;
- }
- video_config.glsl_shader_scrn_num=0;
- for(i=0; i<GLSL_SHADER_MAX; i++)
- {
- video_config.glsl_shader_scrn[i] = nullptr;
- }
- }
-
- #endif /* USE_OPENGL */
+
// misc options: sanity check values
// global options: sanity check values
@@ -307,19 +155,6 @@ void sdl_osd_interface::extract_video_config()
osd_printf_warning("Invalid numscreens value %d; reverting to 1\n", video_config.numscreens);
video_config.numscreens = 1;
}
- // yuv settings ...
- stemp = options().scale_mode();
- video_config.scale_mode = drawsdl_scale_mode(stemp);
- if (video_config.scale_mode < 0)
- {
- osd_printf_warning("Invalid yuvmode value %s; reverting to none\n", stemp);
- video_config.scale_mode = VIDEO_SCALE_MODE_NONE;
- }
- if ( (video_config.mode != VIDEO_MODE_SOFT) && (video_config.scale_mode != VIDEO_SCALE_MODE_NONE) )
- {
- osd_printf_warning("scalemode is only for -video soft, overriding\n");
- video_config.scale_mode = VIDEO_SCALE_MODE_NONE;
- }
}
diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp
index 0bf11ddfa9a..1e6318f57a9 100644
--- a/src/osd/sdl/window.cpp
+++ b/src/osd/sdl/window.cpp
@@ -8,42 +8,38 @@
//
//============================================================
-#ifdef SDLMAME_WIN32
-#include <windows.h>
-#endif
+// MAME headers
+#include "emu.h"
+#include "emuopts.h"
+#include "render.h"
+#include "screen.h"
+#include "uiinput.h"
+#include "ui/uimain.h"
+
+// OSD headers
+#include "modules/monitor/monitor_common.h"
+#include "osdsdl.h"
+#include "window.h"
// standard SDL headers
-#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
// standard C headers
+#include <algorithm>
+#include <cassert>
#include <cmath>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
#include <list>
#include <memory>
-// MAME headers
-
-#include "emu.h"
-#include "emuopts.h"
-#include "render.h"
-#include "screen.h"
-#include "ui/uimain.h"
-
-// OSD headers
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
-#include "window.h"
-#include "osdsdl.h"
-#include "modules/render/drawbgfx.h"
-#include "modules/render/drawsdl.h"
-#include "modules/render/draw13.h"
-#include "modules/monitor/monitor_common.h"
-#if (USE_OPENGL)
-#include "modules/render/drawogl.h"
+#ifdef SDLMAME_WIN32
+#include <windows.h>
#endif
+
//============================================================
// PARAMETERS
//============================================================
@@ -68,19 +64,6 @@
#define SDL_VERSION_EQUALS(v1, vnum2) (SDL_VERSIONNUM(v1.major, v1.minor, v1.patch) == vnum2)
-class SDL_DM_Wrapper
-{
-public:
- SDL_DisplayMode mode;
-};
-
-// debugger
-//static int in_background;
-
-
-//============================================================
-// PROTOTYPES
-//============================================================
//============================================================
@@ -92,60 +75,10 @@ bool sdl_osd_interface::window_init()
{
osd_printf_verbose("Enter sdlwindow_init\n");
- // initialize the renderer
- const int fallbacks[VIDEO_MODE_COUNT] = {
- -1, // NONE -> no fallback
- -1, // No GDI on Linux
-#if defined(USE_OPENGL) && USE_OPENGL
- VIDEO_MODE_OPENGL, // BGFX -> OpenGL
- -1, // OpenGL -> no fallback
-#else
- VIDEO_MODE_SDL2ACCEL, // BGFX -> SDL2Accel
-#endif
- -1, // SDL2ACCEL -> no fallback
- -1, // No D3D on Linux
- -1, // SOFT -> no fallback
- };
-
- int current_mode = video_config.mode;
- while (current_mode != VIDEO_MODE_NONE)
- {
- bool error = false;
- switch(current_mode)
- {
- case VIDEO_MODE_BGFX:
- error = renderer_bgfx::init(machine());
- break;
-#if defined(USE_OPENGL) && USE_OPENGL
- case VIDEO_MODE_OPENGL:
- renderer_ogl::init(machine());
- break;
-#endif
- case VIDEO_MODE_SDL2ACCEL:
- renderer_sdl2::init(machine());
- break;
- case VIDEO_MODE_SOFT:
- renderer_sdl1::init(machine());
- break;
- default:
- fatalerror("Unknown video mode.");
- break;
- }
- if (error)
- {
- current_mode = fallbacks[current_mode];
- }
- else
- {
- break;
- }
- }
- video_config.mode = current_mode;
-
- /* We may want to set a number of the hints SDL2 provides.
- * The code below will document which hints were set.
- */
- const char * hints[] = { SDL_HINT_FRAMEBUFFER_ACCELERATION,
+ // We may want to set a number of the hints SDL2 provides.
+ // The code below will document which hints were set.
+ char const *const hints[] = {
+ SDL_HINT_FRAMEBUFFER_ACCELERATION,
SDL_HINT_RENDER_DRIVER, SDL_HINT_RENDER_OPENGL_SHADERS,
SDL_HINT_RENDER_SCALE_QUALITY,
SDL_HINT_RENDER_VSYNC,
@@ -156,25 +89,20 @@ bool sdl_osd_interface::window_init()
SDL_HINT_XINPUT_ENABLED, SDL_HINT_GAMECONTROLLERCONFIG,
SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_HINT_ALLOW_TOPMOST,
SDL_HINT_TIMER_RESOLUTION,
-#if SDL_VERSION_ATLEAST(2, 0, 2)
SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_HINT_VIDEO_ALLOW_SCREENSAVER,
SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK,
SDL_HINT_VIDEO_WIN_D3DCOMPILER, SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT,
SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_HINT_MOUSE_RELATIVE_MODE_WARP,
-#endif
-#if SDL_VERSION_ATLEAST(2, 0, 3)
SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_HINT_VIDEO_HIGHDPI_DISABLED,
SDL_HINT_WINRT_PRIVACY_POLICY_URL, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL,
SDL_HINT_WINRT_HANDLE_BACK_BUTTON,
-#endif
- nullptr
- };
+ };
osd_printf_verbose("\nHints:\n");
- for (int i = 0; hints[i] != nullptr; i++)
+ for (auto const hintname : hints)
{
- char const *const hint(SDL_GetHint(hints[i]));
- osd_printf_verbose("\t%-40s %s\n", hints[i], hint ? hint : "(NULL)");
+ char const *const hintvalue(SDL_GetHint(hintname));
+ osd_printf_verbose("\t%-40s %s\n", hintname, hintvalue ? hintvalue : "(NULL)");
}
// set up the window list
@@ -185,7 +113,7 @@ bool sdl_osd_interface::window_init()
void sdl_osd_interface::update_slider_list()
{
- for (auto window : osd_common_t::s_window_list)
+ for (auto const &window : osd_common_t::window_list())
{
// check if any window has dirty sliders
if (window->renderer().sliders_dirty())
@@ -200,7 +128,7 @@ void sdl_osd_interface::build_slider_list()
{
m_sliders.clear();
- for (auto window : osd_common_t::s_window_list)
+ for (auto const &window : osd_common_t::window_list())
{
std::vector<ui::menu_item> window_sliders = window->renderer().get_slider_list();
m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end());
@@ -217,33 +145,14 @@ void sdl_osd_interface::window_exit()
osd_printf_verbose("Enter sdlwindow_exit\n");
// free all the windows
+ m_focus_window = nullptr;
while (!osd_common_t::s_window_list.empty())
{
- auto window = osd_common_t::s_window_list.front();
-
- // Part of destroy removes the window from the list
+ auto window = std::move(osd_common_t::s_window_list.back());
+ s_window_list.pop_back();
window->destroy();
}
- switch (video_config.mode)
- {
- case VIDEO_MODE_SDL2ACCEL:
- renderer_sdl1::exit();
- break;
- case VIDEO_MODE_SOFT:
- renderer_sdl1::exit();
- break;
- case VIDEO_MODE_BGFX:
- renderer_bgfx::exit();
- break;
-#if (USE_OPENGL)
- case VIDEO_MODE_OPENGL:
- renderer_ogl::exit();
- break;
-#endif
- default:
- break;
- }
osd_printf_verbose("Leave sdlwindow_exit\n");
}
@@ -328,8 +237,6 @@ void sdl_window_info::toggle_full_screen()
m_windowed_dim = get_size();
}
- // reset UI to main menu
- machine().ui().menu_reset();
// kill off the drawers
renderer_reset();
bool is_osx = false;
@@ -339,17 +246,14 @@ void sdl_window_info::toggle_full_screen()
#endif
if (fullscreen() && (video_config.switchres || is_osx))
{
- SDL_SetWindowFullscreen(platform_window(), 0); // Try to set mode
- SDL_SetWindowDisplayMode(platform_window(), &m_original_mode->mode); // Try to set mode
- SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN); // Try to set mode
+ SDL_SetWindowFullscreen(platform_window(), 0);
+ SDL_SetWindowDisplayMode(platform_window(), &m_original_mode);
+ SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN);
}
SDL_DestroyWindow(platform_window());
set_platform_window(nullptr);
-
downcast<sdl_osd_interface &>(machine().osd()).release_keys();
- set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this()));
-
// toggle the window mode
set_fullscreen(!fullscreen());
@@ -360,7 +264,7 @@ void sdl_window_info::modify_prescale(int dir)
{
int new_prescale = prescale();
- if (dir > 0 && prescale() < 3)
+ if (dir > 0 && prescale() < 20)
new_prescale = prescale() + 1;
if (dir < 0 && prescale() > 1)
new_prescale = prescale() - 1;
@@ -377,11 +281,11 @@ void sdl_window_info::modify_prescale(int dir)
}
else
{
- notify_changed();
m_prescale = new_prescale;
+ notify_changed();
}
- machine().ui().popup_time(1, "Prescale %d", prescale());
}
+ machine().ui().popup_time(1, "Prescale %d", prescale());
}
//============================================================
@@ -428,6 +332,293 @@ int sdl_window_info::xy_to_render_target(int x, int y, int *xt, int *yt)
return renderer().xy_to_render_target(x, y, xt, yt);
}
+void sdl_window_info::mouse_entered(unsigned device)
+{
+ m_mouse_inside = true;
+}
+
+void sdl_window_info::mouse_left(unsigned device)
+{
+ m_mouse_inside = false;
+
+ auto info(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), SDL_FingerID(-1), &sdl_pointer_info::compare));
+ if ((m_active_pointers.end() == info) || (info->finger != SDL_FingerID(-1)))
+ return;
+
+ // leaving implicitly releases buttons, so check hold/drag if necessary
+ if (BIT(info->buttons, 0))
+ {
+ assert(0 <= info->clickcnt);
+
+ auto const now(std::chrono::steady_clock::now());
+ auto const exp(std::chrono::milliseconds(250) + info->pressed);
+ int const dx(info->x - info->pressedx);
+ int const dy(info->y - info->pressedy);
+ int const distance((dx * dx) + (dy * dy));
+ if ((exp < now) || (CLICK_DISTANCE < distance))
+ info->clickcnt = -info->clickcnt;
+ }
+
+ // push to UI manager
+ machine().ui_input().push_pointer_leave(
+ target(),
+ osd::ui_event_handler::pointer::MOUSE,
+ info->index,
+ device,
+ info->x, info->y,
+ info->buttons, info->clickcnt);
+
+ // dump pointer data
+ m_pointer_mask &= ~(decltype(m_pointer_mask)(1) << info->index);
+ if (info->index < m_next_pointer)
+ m_next_pointer = info->index;
+ m_active_pointers.erase(info);
+}
+
+void sdl_window_info::mouse_down(unsigned device, int x, int y, unsigned button)
+{
+ if (!m_mouse_inside)
+ return;
+
+ auto const info(map_pointer(SDL_FingerID(-1), device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ if ((x == info->x) && (y == info->y) && BIT(info->buttons, button))
+ return;
+
+ // detect multi-click actions
+ if (0 == button)
+ {
+ info->primary_down(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ CLICK_DISTANCE,
+ false,
+ m_ptrdev_info);
+ }
+
+ // update info and push to UI manager
+ auto const pressed(decltype(info->buttons)(1) << button);
+ info->x = x;
+ info->y = y;
+ info->buttons |= pressed;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::MOUSE,
+ info->index,
+ device,
+ x, y,
+ info->buttons, pressed, 0, info->clickcnt);
+}
+
+void sdl_window_info::mouse_up(unsigned device, int x, int y, unsigned button)
+{
+ if (!m_mouse_inside)
+ return;
+
+ auto const info(map_pointer(SDL_FingerID(-1), device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ if ((x == info->x) && (y == info->y) && !BIT(info->buttons, button))
+ return;
+
+ // detect multi-click actions
+ if (0 == button)
+ {
+ info->check_primary_hold_drag(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ CLICK_DISTANCE);
+ }
+
+ // update info and push to UI manager
+ auto const released(decltype(info->buttons)(1) << button);
+ info->x = x;
+ info->y = y;
+ info->buttons &= ~released;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::MOUSE,
+ info->index,
+ device,
+ x, y,
+ info->buttons, 0, released, info->clickcnt);
+}
+
+void sdl_window_info::mouse_moved(unsigned device, int x, int y)
+{
+ if (!m_mouse_inside)
+ return;
+
+ auto const info(map_pointer(SDL_FingerID(-1), device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ // detect multi-click actions
+ if (BIT(info->buttons, 0))
+ {
+ info->check_primary_hold_drag(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ CLICK_DISTANCE);
+ }
+
+ // update info and push to UI manager
+ info->x = x;
+ info->y = y;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::MOUSE,
+ info->index,
+ device,
+ x, y,
+ info->buttons, 0, 0, info->clickcnt);
+}
+
+void sdl_window_info::mouse_wheel(unsigned device, int y)
+{
+ if (!m_mouse_inside)
+ return;
+
+ auto const info(map_pointer(SDL_FingerID(-1), device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ // push to UI manager
+ machine().ui_input().push_mouse_wheel_event(target(), info->x, info->y, y, 3);
+}
+
+void sdl_window_info::finger_down(SDL_FingerID finger, unsigned device, int x, int y)
+{
+ auto const info(map_pointer(finger, device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ assert(!info->buttons);
+
+ // detect multi-click actions
+ info->primary_down(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ TAP_DISTANCE,
+ true,
+ m_ptrdev_info);
+
+ // update info and push to UI manager
+ info->x = x;
+ info->y = y;
+ info->buttons = 1;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::TOUCH,
+ info->index,
+ device,
+ x, y,
+ 1, 1, 0, info->clickcnt);
+}
+
+void sdl_window_info::finger_up(SDL_FingerID finger, unsigned device, int x, int y)
+{
+ auto info(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), finger, &sdl_pointer_info::compare));
+ if ((m_active_pointers.end() == info) || (info->finger != finger))
+ return;
+
+ assert(1 == info->buttons);
+
+ // check for conversion to a (multi-)click-and-hold/drag
+ info->check_primary_hold_drag(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ TAP_DISTANCE);
+
+ // need to remember touches to recognise multi-tap gestures
+ if (0 < info->clickcnt)
+ {
+ auto const now(std::chrono::steady_clock::now());
+ auto const time = std::chrono::milliseconds(250);
+ if ((time + info->pressed) >= now)
+ {
+ try
+ {
+ unsigned i(0);
+ if (m_ptrdev_info.size() > device)
+ i = m_ptrdev_info[device].clear_expired_touches(now, time);
+ else
+ m_ptrdev_info.resize(device + 1);
+
+ if (std::size(m_ptrdev_info[device].touches) > i)
+ {
+ m_ptrdev_info[device].touches[i].when = info->pressed;
+ m_ptrdev_info[device].touches[i].x = info->pressedx;
+ m_ptrdev_info[device].touches[i].y = info->pressedy;
+ m_ptrdev_info[device].touches[i].cnt = info->clickcnt;
+ }
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("win_window_info: error allocating pointer data\n");
+ }
+ }
+ }
+
+ // push to UI manager
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::TOUCH,
+ info->index,
+ device,
+ x, y,
+ 0, 0, 1, info->clickcnt);
+ machine().ui_input().push_pointer_leave(
+ target(),
+ osd::ui_event_handler::pointer::TOUCH,
+ info->index,
+ device,
+ x, y,
+ 0, info->clickcnt);
+
+ // dump pointer data
+ m_pointer_mask &= ~(decltype(m_pointer_mask)(1) << info->index);
+ if (info->index < m_next_pointer)
+ m_next_pointer = info->index;
+ m_active_pointers.erase(info);
+}
+
+void sdl_window_info::finger_moved(SDL_FingerID finger, unsigned device, int x, int y)
+{
+ auto info(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), finger, &sdl_pointer_info::compare));
+ if ((m_active_pointers.end() == info) || (info->finger != finger))
+
+ assert(1 == info->buttons);
+
+ if ((x != info->x) || (y != info->y))
+ {
+ info->check_primary_hold_drag(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ TAP_DISTANCE);
+
+ // update info and push to UI manager
+ info->x = x;
+ info->y = y;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::TOUCH,
+ info->index,
+ device,
+ x, y,
+ 1, 0, 0, info->clickcnt);
+ }
+}
+
//============================================================
// sdlwindow_video_window_create
// (main thread)
@@ -441,8 +632,6 @@ int sdl_window_info::window_init()
create_target();
- set_renderer(osd_renderer::make_for_type(video_config.mode, static_cast<osd_window*>(this)->shared_from_this()));
-
int result = complete_create();
// handle error conditions
@@ -469,13 +658,14 @@ void sdl_window_info::complete_destroy()
if (fullscreen() && video_config.switchres)
{
- SDL_SetWindowFullscreen(platform_window(), 0); // Try to set mode
- SDL_SetWindowDisplayMode(platform_window(), &m_original_mode->mode); // Try to set mode
- SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN); // Try to set mode
+ SDL_SetWindowFullscreen(platform_window(), 0);
+ SDL_SetWindowDisplayMode(platform_window(), &m_original_mode);
+ SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN);
}
+ renderer_reset();
SDL_DestroyWindow(platform_window());
- // release all keys ...
+ set_platform_window(nullptr);
downcast<sdl_osd_interface &>(machine().osd()).release_keys();
}
@@ -675,36 +865,20 @@ int sdl_window_info::complete_create()
*
*/
osd_printf_verbose("Enter sdl_info::create\n");
- if (renderer().has_flags(osd_renderer::FLAG_NEEDS_OPENGL) && !video_config.novideo)
+ if (renderer_sdl_needs_opengl())
{
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
m_extra_flags = SDL_WINDOW_OPENGL;
}
else
- m_extra_flags = 0;
-
- // We need to workaround an issue in SDL 2.0.4 for OS X where setting the
- // relative mode on the mouse in fullscreen mode makes mouse events stop
- // It is fixed in the latest revisions so we'll assume it'll be fixed
- // in the next public SDL release as well
-#if defined(SDLMAME_MACOSX) && SDL_VERSION_ATLEAST(2, 0, 2) // SDL_HINT_MOUSE_RELATIVE_MODE_WARP is introduced in 2.0.2
- SDL_version linked;
- SDL_GetVersion(&linked);
- int revision = SDL_GetRevisionNumber();
-
- // If we're running the exact version of SDL 2.0.4 (revision 10001) from the
- // SDL web site, we need to work around this issue and send the warp mode hint
- if (SDL_VERSION_EQUALS(linked, SDL_VERSIONNUM(2, 0, 4)) && revision == 10001)
{
- osd_printf_verbose("Using warp mode for relative mouse in OS X SDL 2.0.4\n");
- SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
+ m_extra_flags = 0;
}
-#endif
// create the SDL window
// soft driver also used | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_MOUSE_FOCUS
m_extra_flags |= (fullscreen() ?
- SDL_WINDOW_BORDERLESS | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE);
+ SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE);
#if defined(SDLMAME_WIN32)
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
@@ -780,7 +954,7 @@ int sdl_window_info::complete_create()
if (sdlwindow == nullptr )
{
- if (renderer().has_flags(osd_renderer::FLAG_NEEDS_OPENGL))
+ if (renderer_sdl_needs_opengl())
osd_printf_error("OpenGL not supported on this driver: %s\n", SDL_GetError());
else
osd_printf_error("Window creation failed: %s\n", SDL_GetError());
@@ -788,13 +962,14 @@ int sdl_window_info::complete_create()
}
set_platform_window(sdlwindow);
+ renderer_create();
if (fullscreen() && video_config.switchres)
{
SDL_DisplayMode mode;
//SDL_GetCurrentDisplayMode(window().monitor()->handle, &mode);
SDL_GetWindowDisplayMode(platform_window(), &mode);
- m_original_mode->mode = mode;
+ m_original_mode = mode;
mode.w = temp.width();
mode.h = temp.height();
if (m_win_config.refresh)
@@ -826,24 +1001,6 @@ int sdl_window_info::complete_create()
SDL_SetWindowGrab(platform_window(), SDL_TRUE);
#endif
- // set main window
- if (index() > 0)
- {
- for (auto w : osd_common_t::s_window_list)
- {
- if (w->index() == 0)
- {
- set_main_window(std::dynamic_pointer_cast<osd_window>(w));
- break;
- }
- }
- }
- else
- {
- // We must be the main window
- set_main_window(shared_from_this());
- }
-
// update monitor resolution after mode change to ensure proper pixel aspect
monitor()->refresh();
if (fullscreen() && video_config.switchres)
@@ -1149,16 +1306,63 @@ osd_dim sdl_window_info::get_max_bounds(int constrain)
return maximum.dim();
}
+
+std::vector<sdl_window_info::sdl_pointer_info>::iterator sdl_window_info::map_pointer(SDL_FingerID finger, unsigned device)
+{
+ auto found(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), finger, &sdl_pointer_info::compare));
+ if ((m_active_pointers.end() != found) && (found->finger == finger))
+ return found;
+
+ if ((sizeof(m_next_pointer) * 8) <= m_next_pointer)
+ {
+ assert(~decltype(m_pointer_mask)(0) == m_pointer_mask);
+ osd_printf_warning("sdl_window_info: exceeded maximum number of active pointers\n");
+ return m_active_pointers.end();
+ }
+ assert(!BIT(m_pointer_mask, m_next_pointer));
+
+ try
+ {
+ found = m_active_pointers.emplace(
+ found,
+ sdl_pointer_info(finger, m_next_pointer, device));
+ m_pointer_mask |= decltype(m_pointer_mask)(1) << m_next_pointer;
+ do
+ {
+ ++m_next_pointer;
+ }
+ while (((sizeof(m_next_pointer) * 8) > m_next_pointer) && BIT(m_pointer_mask, m_next_pointer));
+
+ return found;
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_window_info: error allocating pointer data\n");
+ return m_active_pointers.end();
+ }
+}
+
+
+inline sdl_window_info::sdl_pointer_info::sdl_pointer_info(SDL_FingerID f, unsigned i, unsigned d)
+ : pointer_info(i, d)
+ , finger(f)
+{
+}
+
+
+
+
//============================================================
// construction and destruction
//============================================================
sdl_window_info::sdl_window_info(
running_machine &a_machine,
+ render_module &renderprovider,
int index,
- std::shared_ptr<osd_monitor_info> a_monitor,
+ const std::shared_ptr<osd_monitor_info> &a_monitor,
const osd_window_config *config)
- : osd_window_t(a_machine, index, std::move(a_monitor), *config)
+ : osd_window_t(a_machine, renderprovider, index, std::move(a_monitor), *config)
, m_startmaximized(0)
// Following three are used by input code to defer resizes
, m_minimum_dim(0, 0)
@@ -1167,13 +1371,18 @@ sdl_window_info::sdl_window_info(
, m_extra_flags(0)
, m_mouse_captured(false)
, m_mouse_hidden(false)
+ , m_pointer_mask(0)
+ , m_next_pointer(0)
+ , m_mouse_inside(false)
{
//FIXME: these should be per_window in config-> or even better a bit set
m_fullscreen = !video_config.windowed;
m_prescale = video_config.prescale;
m_windowed_dim = osd_dim(config->width, config->height);
- m_original_mode = std::make_unique<SDL_DM_Wrapper>();
+
+ m_ptrdev_info.reserve(1);
+ m_active_pointers.reserve(16);
}
sdl_window_info::~sdl_window_info()
diff --git a/src/osd/sdl/window.h b/src/osd/sdl/window.h
index 190a5ea531c..49fe452192f 100644
--- a/src/osd/sdl/window.h
+++ b/src/osd/sdl/window.h
@@ -11,14 +11,15 @@
#ifndef MAME_OSD_SDL_WINDOW_H
#define MAME_OSD_SDL_WINDOW_H
-#include "osdsdl.h"
-
#include "modules/osdwindow.h"
#include "osdsync.h"
+#include <SDL2/SDL.h>
+
+#include <chrono>
#include <cstdint>
#include <memory>
-#include <list>
+#include <vector>
//============================================================
@@ -27,10 +28,6 @@
class render_target;
-// forward of SDL_DisplayMode not possible (typedef struct) - define wrapper
-
-class SDL_DM_Wrapper;
-
typedef uintptr_t HashT;
#define OSDWORK_CALLBACK(name) void *name(void *param, int threadid)
@@ -38,7 +35,11 @@ typedef uintptr_t HashT;
class sdl_window_info : public osd_window_t<SDL_Window*>
{
public:
- sdl_window_info(running_machine &a_machine, int index, std::shared_ptr<osd_monitor_info> a_monitor,
+ sdl_window_info(
+ running_machine &a_machine,
+ render_module &renderprovider,
+ int index,
+ const std::shared_ptr<osd_monitor_info> &a_monitor,
const osd_window_config *config);
~sdl_window_info();
@@ -62,26 +63,34 @@ public:
int xy_to_render_target(int x, int y, int *xt, int *yt);
+ void mouse_entered(unsigned device);
+ void mouse_left(unsigned device);
+ void mouse_down(unsigned device, int x, int y, unsigned button);
+ void mouse_up(unsigned device, int x, int y, unsigned button);
+ void mouse_moved(unsigned device, int x, int y);
+ void mouse_wheel(unsigned device, int y);
+ void finger_down(SDL_FingerID finger, unsigned device, int x, int y);
+ void finger_up(SDL_FingerID finger, unsigned device, int x, int y);
+ void finger_moved(SDL_FingerID finger, unsigned device, int x, int y);
+
private:
- // window handle and info
- int m_startmaximized;
+ struct sdl_pointer_info : public pointer_info
+ {
+ static constexpr bool compare(sdl_pointer_info const &info, SDL_FingerID finger) { return info.finger < finger; }
- // dimensions
- osd_dim m_minimum_dim;
- osd_dim m_windowed_dim;
+ sdl_pointer_info(sdl_pointer_info const &) = default;
+ sdl_pointer_info(sdl_pointer_info &&) = default;
+ sdl_pointer_info &operator=(sdl_pointer_info const &) = default;
+ sdl_pointer_info &operator=(sdl_pointer_info &&) = default;
- // rendering info
- osd_event m_rendered_event;
+ sdl_pointer_info(SDL_FingerID, unsigned i, unsigned d);
- // Original display_mode
- std::unique_ptr<SDL_DM_Wrapper> m_original_mode;
-
- int m_extra_flags;
+ SDL_FingerID finger;
+ };
// returns 0 on success, else 1
int complete_create();
-private:
int wnd_extra_width();
int wnd_extra_height();
osd_rect constrain_to_aspect_ratio(const osd_rect &rect, int adjustment);
@@ -91,45 +100,35 @@ private:
osd_dim pick_best_mode();
void set_fullscreen(int afullscreen) { m_fullscreen = afullscreen; }
- // monitor info
- bool m_mouse_captured;
- bool m_mouse_hidden;
-
void measure_fps(int update);
-};
-
-struct osd_draw_callbacks
-{
- osd_renderer *(*create)(osd_window *window);
-};
-
-//============================================================
-// PROTOTYPES
-//============================================================
-
-//============================================================
-// PROTOTYPES - drawsdl.c
-//============================================================
-
-int drawsdl_scale_mode(const char *s);
+ std::vector<sdl_pointer_info>::iterator map_pointer(SDL_FingerID finger, unsigned device);
-//============================================================
-// PROTOTYPES - drawogl.c
-//============================================================
+ // window handle and info
+ int m_startmaximized;
-int drawogl_init(running_machine &machine, osd_draw_callbacks *callbacks);
+ // dimensions
+ osd_dim m_minimum_dim;
+ osd_dim m_windowed_dim;
-//============================================================
-// PROTOTYPES - draw13.c
-//============================================================
+ // rendering info
+ osd_event m_rendered_event;
-int drawsdl2_init(running_machine &machine, osd_draw_callbacks *callbacks);
+ // Original display_mode
+ SDL_DisplayMode m_original_mode;
-//============================================================
-// PROTOTYPES - drawbgfx.c
-//============================================================
+ int m_extra_flags;
-int drawbgfx_init(running_machine &machine, osd_draw_callbacks *callbacks);
+ // monitor info
+ bool m_mouse_captured;
+ bool m_mouse_hidden;
+
+ // info on currently active pointers - 64 pointers ought to be enough for anyone
+ uint64_t m_pointer_mask;
+ unsigned m_next_pointer;
+ bool m_mouse_inside;
+ std::vector<pointer_dev_info> m_ptrdev_info;
+ std::vector<sdl_pointer_info> m_active_pointers;
+};
#endif // MAME_OSD_SDL_WINDOW_H