diff options
Diffstat (limited to 'src/osd/sdl')
-rw-r--r-- | src/osd/sdl/android_main.cpp | 11 | ||||
-rw-r--r-- | src/osd/sdl/osdsdl.cpp | 852 | ||||
-rw-r--r-- | src/osd/sdl/osdsdl.h | 220 | ||||
-rw-r--r-- | src/osd/sdl/sdlmain.cpp | 442 | ||||
-rw-r--r-- | src/osd/sdl/sdlopts.cpp | 127 | ||||
-rw-r--r-- | src/osd/sdl/sdlopts.h | 100 | ||||
-rwxr-xr-x[-rw-r--r--] | src/osd/sdl/taputil.sh | 4 | ||||
-rw-r--r-- | src/osd/sdl/video.cpp | 217 | ||||
-rw-r--r-- | src/osd/sdl/window.cpp | 792 | ||||
-rw-r--r-- | src/osd/sdl/window.h | 133 |
10 files changed, 1822 insertions, 1076 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..d9268869729 --- /dev/null +++ b/src/osd/sdl/osdsdl.cpp @@ -0,0 +1,852 @@ +// 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(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_2) // Ctrl-@ (NUL) + machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), 0x00); + else 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 4a320319f44..74730f69df5 100644 --- a/src/osd/sdl/osdsdl.h +++ b/src/osd/sdl/osdsdl.h @@ -1,47 +1,31 @@ // license:BSD-3-Clause // copyright-holders:Olivier Galibert, R. Belmont -#ifndef _osdsdl_h_ -#define _osdsdl_h_ +#ifndef MAME_OSD_SDL_OSDSDL_H +#define MAME_OSD_SDL_OSDSDL_H + +#pragma once + +#include "sdlopts.h" #include "modules/lib/osdobj_common.h" #include "modules/osdmodule.h" -#include "modules/font/font_module.h" + +#include <SDL2/SDL.h> + +#include <cassert> +#include <chrono> +#include <memory> +#include <mutex> +#include <unordered_map> +#include <utility> +#include <string> +#include <vector> + //============================================================ // Defines //============================================================ -#define SDLOPTION_INIPATH "inipath" -#define SDLOPTION_SDLVIDEOFPS "sdlvideofps" -#define SDLOPTION_USEALLHEADS "useallheads" -#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_SIXAXIS "sixaxis" -#define SDLOPTION_JOYINDEX "joy_idx" -#define SDLOPTION_KEYBINDEX "keyb_idx" -#define SDLOPTION_MOUSEINDEX "mouse_index" -#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" - #define SDLMAME_LED(x) "led" #x // read by sdlmame @@ -56,63 +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(); - - // performance options - bool video_fps() const { return bool_value(SDLOPTION_SDLVIDEOFPS); } +public: // need extra public section for forward declaration + class subscriber; - // 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); } +private: + class impl + { + public: + std::mutex m_mutex; + std::unordered_multimap<EventType, subscriber *> m_subs; + }; - // full screen options -#ifdef SDLMAME_X11 - bool use_all_heads() const { return bool_value(SDLOPTION_USEALLHEADS); } -#endif + std::shared_ptr<impl> m_impl; - // keyboard mapping - bool keymap() const { return bool_value(SDLOPTION_KEYMAP); } - const char *keymap_file() const { return value(SDLOPTION_KEYMAP_FILE); } +protected: + event_subscription_manager() : m_impl(new impl) + { + } - // joystick mapping - const char *joy_index(int index) const { return value(string_format("%s%d", SDLOPTION_JOYINDEX, index).c_str()); } - bool sixaxis() const { return bool_value(SDLOPTION_SIXAXIS); } + ~event_subscription_manager() = default; - const char *mouse_index(int index) const { return value(string_format("%s%d", SDLOPTION_MOUSEINDEX, index).c_str()); } - const char *keyboard_index(int index) const { return value(string_format("%s%d", SDLOPTION_KEYBINDEX, index).c_str()); } + 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 @@ -122,11 +146,11 @@ public: // general overridables virtual void init(running_machine &machine) override; virtual void update(bool skip_redraw) override; + virtual void input_update(bool relative_reset) override; + virtual void check_osd_inputs() override; // input overridables - virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override; - - virtual void video_register() override; + virtual void customize_input_type_list(std::vector<input_type_entry> &typelist) override; virtual bool video_init() override; virtual bool window_init() override; @@ -134,25 +158,53 @@ public: 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; } -protected: - virtual void build_slider_list() override; - virtual void update_slider_list() override; + virtual void process_events() 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; }; //============================================================ @@ -161,4 +213,4 @@ private: extern int osd_num_processors; -#endif +#endif // MAME_OSD_SDL_OSDSDL_H diff --git a/src/osd/sdl/sdlmain.cpp b/src/osd/sdl/sdlmain.cpp index 37d1434a2e8..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,39 +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 "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 @@ -70,108 +55,6 @@ int sdl_entered_debugger; #endif -//============================================================ -// Local variables -//============================================================ - -const options_entry sdl_options::s_option_entries[] = -{ - { SDLOPTION_INIPATH, INI_PATH, OPTION_STRING, "path to ini files" }, - - // performance options - { nullptr, nullptr, OPTION_HEADER, "SDL PERFORMANCE OPTIONS" }, - { SDLOPTION_SDLVIDEOFPS, "0", OPTION_BOOLEAN, "show sdl video performance" }, - // video options - { nullptr, nullptr, OPTION_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", OPTION_BOOLEAN, "center horizontally within the view area" }, - { SDLOPTION_CENTERV, "1", OPTION_BOOLEAN, "center vertically within the view area" }, - { SDLOPTION_SCALEMODE ";sm", OSDOPTVAL_NONE, OPTION_STRING, "Scale mode: none, hwblit, hwbest, yv12, yuy2, yv12x2, yuy2x2 (-video soft only)" }, - - // full screen options - #ifdef SDLMAME_X11 - { nullptr, nullptr, OPTION_HEADER, "SDL FULL SCREEN OPTIONS" }, - { SDLOPTION_USEALLHEADS, "0", OPTION_BOOLEAN, "split full screen image across monitors" }, - #endif - - // keyboard mapping - { nullptr, nullptr, OPTION_HEADER, "SDL KEYBOARD MAPPING" }, - { SDLOPTION_KEYMAP, "0", OPTION_BOOLEAN, "enable keymap" }, - { SDLOPTION_KEYMAP_FILE, "keymap.dat", OPTION_STRING, "keymap filename" }, - - // joystick mapping - { nullptr, nullptr, OPTION_HEADER, "SDL JOYSTICK MAPPING" }, - { SDLOPTION_JOYINDEX "1", OSDOPTVAL_AUTO, OPTION_STRING, "name of joystick mapped to joystick #1" }, - { SDLOPTION_JOYINDEX "2", OSDOPTVAL_AUTO, OPTION_STRING, "name of joystick mapped to joystick #2" }, - { SDLOPTION_JOYINDEX "3", OSDOPTVAL_AUTO, OPTION_STRING, "name of joystick mapped to joystick #3" }, - { SDLOPTION_JOYINDEX "4", OSDOPTVAL_AUTO, OPTION_STRING, "name of joystick mapped to joystick #4" }, - { SDLOPTION_JOYINDEX "5", OSDOPTVAL_AUTO, OPTION_STRING, "name of joystick mapped to joystick #5" }, - { SDLOPTION_JOYINDEX "6", OSDOPTVAL_AUTO, OPTION_STRING, "name of joystick mapped to joystick #6" }, - { SDLOPTION_JOYINDEX "7", OSDOPTVAL_AUTO, OPTION_STRING, "name of joystick mapped to joystick #7" }, - { SDLOPTION_JOYINDEX "8", OSDOPTVAL_AUTO, OPTION_STRING, "name of joystick mapped to joystick #8" }, - { SDLOPTION_SIXAXIS, "0", OPTION_BOOLEAN, "use special handling for PS3 Sixaxis controllers" }, - -#if (USE_XINPUT) - // lightgun mapping - { nullptr, nullptr, OPTION_HEADER, "SDL LIGHTGUN MAPPING" }, - { SDLOPTION_LIGHTGUNINDEX "1", OSDOPTVAL_AUTO, OPTION_STRING, "name of lightgun mapped to lightgun #1" }, - { SDLOPTION_LIGHTGUNINDEX "2", OSDOPTVAL_AUTO, OPTION_STRING, "name of lightgun mapped to lightgun #2" }, - { SDLOPTION_LIGHTGUNINDEX "3", OSDOPTVAL_AUTO, OPTION_STRING, "name of lightgun mapped to lightgun #3" }, - { SDLOPTION_LIGHTGUNINDEX "4", OSDOPTVAL_AUTO, OPTION_STRING, "name of lightgun mapped to lightgun #4" }, - { SDLOPTION_LIGHTGUNINDEX "5", OSDOPTVAL_AUTO, OPTION_STRING, "name of lightgun mapped to lightgun #5" }, - { SDLOPTION_LIGHTGUNINDEX "6", OSDOPTVAL_AUTO, OPTION_STRING, "name of lightgun mapped to lightgun #6" }, - { SDLOPTION_LIGHTGUNINDEX "7", OSDOPTVAL_AUTO, OPTION_STRING, "name of lightgun mapped to lightgun #7" }, - { SDLOPTION_LIGHTGUNINDEX "8", OSDOPTVAL_AUTO, OPTION_STRING, "name of lightgun mapped to lightgun #8" }, -#endif - - { nullptr, nullptr, OPTION_HEADER, "SDL MOUSE MAPPING" }, - { SDLOPTION_MOUSEINDEX "1", OSDOPTVAL_AUTO, OPTION_STRING, "name of mouse mapped to mouse #1" }, - { SDLOPTION_MOUSEINDEX "2", OSDOPTVAL_AUTO, OPTION_STRING, "name of mouse mapped to mouse #2" }, - { SDLOPTION_MOUSEINDEX "3", OSDOPTVAL_AUTO, OPTION_STRING, "name of mouse mapped to mouse #3" }, - { SDLOPTION_MOUSEINDEX "4", OSDOPTVAL_AUTO, OPTION_STRING, "name of mouse mapped to mouse #4" }, - { SDLOPTION_MOUSEINDEX "5", OSDOPTVAL_AUTO, OPTION_STRING, "name of mouse mapped to mouse #5" }, - { SDLOPTION_MOUSEINDEX "6", OSDOPTVAL_AUTO, OPTION_STRING, "name of mouse mapped to mouse #6" }, - { SDLOPTION_MOUSEINDEX "7", OSDOPTVAL_AUTO, OPTION_STRING, "name of mouse mapped to mouse #7" }, - { SDLOPTION_MOUSEINDEX "8", OSDOPTVAL_AUTO, OPTION_STRING, "name of mouse mapped to mouse #8" }, - - { nullptr, nullptr, OPTION_HEADER, "SDL KEYBOARD MAPPING" }, - { SDLOPTION_KEYBINDEX "1", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #1" }, - { SDLOPTION_KEYBINDEX "2", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #2" }, - { SDLOPTION_KEYBINDEX "3", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #3" }, - { SDLOPTION_KEYBINDEX "4", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #4" }, - { SDLOPTION_KEYBINDEX "5", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #5" }, - { SDLOPTION_KEYBINDEX "6", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #6" }, - { SDLOPTION_KEYBINDEX "7", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #7" }, - { SDLOPTION_KEYBINDEX "8", OSDOPTVAL_AUTO, OPTION_STRING, "name of keyboard mapped to keyboard #8" }, - - // SDL low level driver options - { nullptr, nullptr, OPTION_HEADER, "SDL LOW-LEVEL DRIVER OPTIONS" }, - { SDLOPTION_VIDEODRIVER ";vd", OSDOPTVAL_AUTO, OPTION_STRING, "SDL video driver to use ('x11', 'directfb', ... or 'auto' for SDL default" }, - { SDLOPTION_RENDERDRIVER ";rd", OSDOPTVAL_AUTO, OPTION_STRING, "SDL render driver to use ('software', 'opengl', 'directfb' ... or 'auto' for SDL default" }, - { SDLOPTION_AUDIODRIVER ";ad", OSDOPTVAL_AUTO, OPTION_STRING, "SDL audio driver to use ('alsa', 'arts', ... or 'auto' for SDL default" }, -#if USE_OPENGL - { SDLOPTION_GL_LIB, SDLOPTVAL_GLLIB, OPTION_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, ini_path.c_str()); -} //============================================================ // main @@ -228,290 +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_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); - } - 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..3953a47b7f8 --- /dev/null +++ b/src/osd/sdl/sdlopts.cpp @@ -0,0 +1,127 @@ +// 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" }, + { SDLOPTION_DUAL_LIGHTGUN ";dual", "0", core_options::option_type::BOOLEAN, "enable dual lightgun input" }, + +#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..f6338fe1db6 --- /dev/null +++ b/src/osd/sdl/sdlopts.h @@ -0,0 +1,100 @@ +// 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" +#define SDLOPTION_DUAL_LIGHTGUN "dual_lightgun" +#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); } + bool dual_lightgun() const { return bool_value(SDLOPTION_DUAL_LIGHTGUN); } + + 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/taputil.sh b/src/osd/sdl/taputil.sh index 1a22048b9ca..c230d7c19f8 100644..100755 --- a/src/osd/sdl/taputil.sh +++ b/src/osd/sdl/taputil.sh @@ -22,9 +22,9 @@ ip tuntap del dev $TAP mode tap exit fi -if [ "$#" != "5" ] +if [ "$#" != "4" ] then -echo "usage: mess-tap [-c] [-d] USER EMUADDR HOSTADDR MASK" +echo "usage: mess-tap [-c] [-d] USER EMUADDR HOSTADDR" echo "-c create interface" echo "-d delete interface" echo "USER user to own interface, required to delete" diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp index 88bc1b51ce4..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 "video.h" -#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,86 +99,29 @@ 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); } - // poll the joystick values here - downcast<sdl_osd_interface&>(machine().osd()).poll_inputs(machine()); - - check_osd_inputs(machine()); // if we're running, disable some parts of the debugger if ((machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) != 0) debugger_update(); } //============================================================ -// 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 (machine.ui_input().pressed(IPT_OSD_2)) - { - //FIXME: on a per window basis - video_config.fullstretch = !video_config.fullstretch; - window->target()->set_scale_mode(video_config.fullstretch? SCALE_FRACTIONAL : SCALE_INTEGER); - machine.ui().popup_time(1, "Uneven stretch %s", video_config.fullstretch? "enabled":"disabled"); - } - - if (machine.ui_input().pressed(IPT_OSD_4)) - { - //FIXME: on a per window basis - video_config.keepaspect = !video_config.keepaspect; - window->target()->set_keepaspect(video_config.keepaspect); - machine.ui().popup_time(1, "Keepaspect %s", video_config.keepaspect? "enabled":"disabled"); - } - - #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"); - } - #endif - - 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 video_config.windowed = options().window(); video_config.prescale = options().prescale(); video_config.filter = options().filter(); - video_config.keepaspect = options().keep_aspect(); video_config.numscreens = options().numscreens(); - video_config.fullstretch = options().uneven_stretch(); #ifdef SDLMAME_X11 video_config.restrictonemonitor = !options().use_all_heads(); #endif @@ -192,49 +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; - - // d3d options: extract the data - stemp = options().video(); - if (strcmp(stemp, "auto") == 0) - { -#if (defined SDLMAME_MACOSX || defined SDLMAME_WIN32) - stemp = "opengl"; -#elif (defined __STEAMLINK__) - stemp = "bgfx"; -#else - stemp = "soft"; -#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(); @@ -246,69 +141,12 @@ void sdl_osd_interface::extract_video_config() video_config.syncrefresh = 0; } - if (video_config.prescale < 1 || video_config.prescale > 3) + 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 @@ -317,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 875e06a7b3d..59be82238d0 100644 --- a/src/osd/sdl/window.cpp +++ b/src/osd/sdl/window.cpp @@ -8,40 +8,38 @@ // //============================================================ -#ifdef SDLMAME_WIN32 -#include <windows.h> -#endif - -// standard SDL headers -#include <SDL2/SDL.h> - -// standard C headers -#include <math.h> -#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 "uiinput.h" #include "ui/uimain.h" // OSD headers - -#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" +#include "osdsdl.h" +#include "window.h" + +// standard SDL headers +#include <SDL2/SDL_syswm.h> + +// standard C headers +#include <algorithm> +#include <cassert> +#include <cmath> +#include <list> +#include <memory> + +#ifndef _MSC_VER +#include <unistd.h> +#endif + +#ifdef SDLMAME_WIN32 +#include <windows.h> #endif + //============================================================ // PARAMETERS //============================================================ @@ -66,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 -//============================================================ //============================================================ @@ -90,30 +75,10 @@ bool sdl_osd_interface::window_init() { osd_printf_verbose("Enter sdlwindow_init\n"); - // initialize the drawers - - switch (video_config.mode) - { - case VIDEO_MODE_BGFX: - renderer_bgfx::init(machine()); - break; -#if (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; - } - - /* 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, @@ -124,23 +89,21 @@ 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++) - osd_printf_verbose("\t%-40s %s\n", hints[i], SDL_GetHint(hints[i])); + for (auto const hintname : hints) + { + char const *const hintvalue(SDL_GetHint(hintname)); + osd_printf_verbose("\t%-40s %s\n", hintname, hintvalue ? hintvalue : "(NULL)"); + } // set up the window list osd_printf_verbose("Leave sdlwindow_init\n"); @@ -148,30 +111,6 @@ bool sdl_osd_interface::window_init() } -void sdl_osd_interface::update_slider_list() -{ - for (auto window : osd_common_t::s_window_list) - { - // check if any window has dirty sliders - if (window->renderer().sliders_dirty()) - { - build_slider_list(); - return; - } - } -} - -void sdl_osd_interface::build_slider_list() -{ - m_sliders.clear(); - - for (auto window : osd_common_t::s_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()); - } -} - //============================================================ // sdlwindow_exit // (main thread) @@ -182,33 +121,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"); } @@ -293,8 +213,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; @@ -304,17 +222,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()); @@ -325,7 +240,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; @@ -342,11 +257,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()); } //============================================================ @@ -393,6 +308,291 @@ 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) && (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) @@ -400,31 +600,13 @@ int sdl_window_info::xy_to_render_target(int x, int y, int *xt, int *yt) int sdl_window_info::window_init() { - int result; - // set the initial maximized state // FIXME: Does not belong here - sdl_options &options = downcast<sdl_options &>(m_machine.options()); - m_startmaximized = options.maximize(); - - // add us to the list - osd_common_t::s_window_list.push_back(std::static_pointer_cast<sdl_window_info>(shared_from_this())); + m_startmaximized = downcast<sdl_options &>(machine().options()).maximize(); - set_renderer(osd_renderer::make_for_type(video_config.mode, static_cast<osd_window*>(this)->shared_from_this())); - - // load the layout - m_target = m_machine.render().target_alloc(); - - // set the specific view - set_starting_view(m_index, options.view(), options.view(m_index)); - - // make the window title - if (video_config.numscreens == 1) - sprintf(m_title, "%s: %s [%s]", emulator_info::get_appname(), m_machine.system().type.fullname(), m_machine.system().name); - else - sprintf(m_title, "%s: %s [%s] - Screen %d", emulator_info::get_appname(), m_machine.system().type.fullname(), m_machine.system().name, m_index); + create_target(); - result = complete_create(); + int result = complete_create(); // handle error conditions if (result == 1) @@ -450,31 +632,17 @@ 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(); } -void sdl_window_info::destroy() -{ - //osd_event_wait(window->rendered_event, osd_ticks_per_second()*10); - - // remove us from the list - osd_common_t::s_window_list.remove(std::static_pointer_cast<sdl_window_info>(shared_from_this())); - - // free the textures etc - complete_destroy(); - - // free the render target, after the textures! - machine().render().target_free(m_target); - -} - //============================================================ // pick_best_mode @@ -489,7 +657,7 @@ osd_dim sdl_window_info::pick_best_mode() osd_dim ret(0,0); // determine the minimum width/height for the selected target - m_target->compute_minimum_size(minimum_width, minimum_height); + target()->compute_minimum_size(minimum_width, minimum_height); // use those as the target for now target_width = minimum_width * std::max(1, prescale()); @@ -502,7 +670,7 @@ osd_dim sdl_window_info::pick_best_mode() } // FIXME: this should be provided by monitor ! - num = SDL_GetNumDisplayModes(m_monitor->oshandle()); + num = SDL_GetNumDisplayModes(monitor()->oshandle()); if (num == 0) { @@ -514,7 +682,7 @@ osd_dim sdl_window_info::pick_best_mode() for (i = 0; i < num; ++i) { SDL_DisplayMode mode; - SDL_GetDisplayMode(m_monitor->oshandle(), i, &mode); + SDL_GetDisplayMode(monitor()->oshandle(), i, &mode); // compute initial score based on difference between target and current size_score = 1.0f / (1.0f + abs((int32_t)mode.w - target_width) + abs((int32_t)mode.h - target_height)); @@ -556,20 +724,16 @@ osd_dim sdl_window_info::pick_best_mode() void sdl_window_info::update() { - osd_ticks_t event_wait_ticks; - // adjust the cursor state - //sdlwindow_update_cursor_state(machine, window); - update_cursor_state(); // if we're visible and running and not in the middle of a resize, draw - if (m_target != nullptr) + if (target() != nullptr) { int tempwidth, tempheight; // see if the games video mode has changed - m_target->compute_minimum_size(tempwidth, tempheight); + target()->compute_minimum_size(tempwidth, tempheight); if (osd_dim(tempwidth, tempheight) != m_minimum_dim) { m_minimum_dim = osd_dim(tempwidth, tempheight); @@ -586,6 +750,7 @@ void sdl_window_info::update() } } + osd_ticks_t event_wait_ticks; if (video_config.waitvsync && video_config.syncrefresh) event_wait_ticks = osd_ticks_per_second(); // block at most a second else @@ -601,13 +766,10 @@ void sdl_window_info::update() // and redraw now - // Some configurations require events to be polled in the worker thread - downcast< sdl_osd_interface& >(machine().osd()).process_events_buf(); - // Check whether window has vector screens { - const screen_device *screen = screen_device_iterator(machine().root_device()).byindex(m_index); + const screen_device *screen = screen_device_enumerator(machine().root_device()).byindex(index()); if ((screen != nullptr) && (screen->screen_type() == SCREEN_TYPE_VECTOR)) renderer().set_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN); else @@ -616,20 +778,20 @@ void sdl_window_info::update() m_primlist = &primlist; - // if no bitmap, just fill if (m_primlist == nullptr) { + // if no bitmap, just fill } - // otherwise, render with our drawing system else { - if( video_config.perftest ) + // otherwise, render with our drawing system + if (video_config.perftest) measure_fps(update); else renderer().draw(update); } - /* all done, ready for next */ + // all done, ready for next m_rendered_event.set(); } } @@ -637,27 +799,6 @@ void sdl_window_info::update() //============================================================ -// set_starting_view -// (main thread) -//============================================================ - -void sdl_window_info::set_starting_view(int index, const char *defview, const char *view) -{ - int viewindex; - - // choose non-auto over auto - if (strcmp(view, "auto") == 0 && strcmp(defview, "auto") != 0) - view = defview; - - // query the video system to help us pick a view - viewindex = target()->configured_view(view, index, video_config.numscreens); - - // set the view - target()->set_view(viewindex); -} - - -//============================================================ // complete_create //============================================================ @@ -681,9 +822,13 @@ int sdl_window_info::complete_create() temp = m_windowed_dim; } else if (m_startmaximized) - temp = get_max_bounds(video_config.keepaspect ); + { + temp = get_max_bounds(keepaspect()); + } else - temp = get_min_bounds(video_config.keepaspect ); + { + temp = get_min_bounds(keepaspect()); + } // create the window ..... @@ -694,50 +839,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 ); - - /* FIXME: A reminder that gamma is wrong throughout MAME. Currently, SDL2.0 doesn't seem to - * support the following attribute although my hardware lists GL_ARB_framebuffer_sRGB as an extension. - * - * SDL_GL_SetAttribute( SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1 ); - * - */ m_extra_flags = SDL_WINDOW_OPENGL; } else - m_extra_flags = 0; - -#ifdef SDLMAME_MACOSX - /* FIMXE: On OSX, SDL_WINDOW_FULLSCREEN_DESKTOP seems to be more reliable. - * It however creates issues with white borders, i.e. the screen clear - * does not work. This happens both with opengl and accel. - */ -#endif - - // 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"); @@ -746,17 +861,74 @@ int sdl_window_info::complete_create() // get monitor work area for centering osd_rect work = monitor()->usuable_position_size(); - // create the SDL window - auto sdlwindow = SDL_CreateWindow(m_title, + // create or attach to an existing window + SDL_Window *sdlwindow; +#ifdef SDLMAME_X11 + const char *attach_window = downcast<sdl_options &>(machine().options()).attach_window(); +#else + const char *attach_window = nullptr; +#endif + if (attach_window && *attach_window) + { + // we're attaching to an existing window; parse the argument + unsigned long long attach_window_value; + try + { + attach_window_value = std::stoull(attach_window, nullptr, 0); + } + catch (std::invalid_argument &) + { + osd_printf_error("Invalid -attach_window value: %s\n", attach_window); + return 1; + } + + // and attach to it + sdlwindow = SDL_CreateWindowFrom((void *)attach_window_value); + if (!sdlwindow) + { + osd_printf_error("Failed to attach to window \"%s\": %s\n", attach_window, SDL_GetError()); + return 1; + } + + // perform SDL subsystem-specific tasks + SDL_SysWMinfo swmi; + SDL_VERSION(&swmi.version); + if (SDL_GetWindowWMInfo(sdlwindow, &swmi)) + { + switch (swmi.subsystem) + { +#ifdef SDLMAME_X11 + case SDL_SYSWM_X11: + // by default, SDL_CreateWindowFrom() doesn't ensure that we're getting the events that we + // expect + XSelectInput(swmi.info.x11.display, swmi.info.x11.window, + FocusChangeMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | KeyPressMask | KeyReleaseMask | + PropertyChangeMask | StructureNotifyMask | + ExposureMask | KeymapStateMask); + break; +#endif // SDLMAME_X11 + + default: + break; + } + } + } + else + { + // create the SDL window + sdlwindow = SDL_CreateWindow(title().c_str(), work.left() + (work.width() - temp.width()) / 2, work.top() + (work.height() - temp.height()) / 2, temp.width(), temp.height(), m_extra_flags); + } + //window().sdl_window() = SDL_CreateWindow(window().m_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, // width, height, m_extra_flags); 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()); @@ -764,13 +936,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) @@ -802,24 +975,6 @@ int sdl_window_info::complete_create() SDL_SetWindowGrab(platform_window(), SDL_TRUE); #endif - // set main window - if (m_index > 0) - { - for (auto w : osd_common_t::s_window_list) - { - if (w->m_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) @@ -830,8 +985,8 @@ int sdl_window_info::complete_create() return 1; // Make sure we have a consistent state - SDL_ShowCursor(0); - SDL_ShowCursor(1); + SDL_ShowCursor(SDL_DISABLE); + SDL_ShowCursor(SDL_ENABLE); return 0; } @@ -910,14 +1065,9 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad int32_t viswidth, visheight; int32_t adjwidth, adjheight; float pixel_aspect; - std::shared_ptr<osd_monitor_info> monitor = m_monitor; - - // do not constrain aspect ratio for integer scaled views - if (m_target->scale_mode() != SCALE_FRACTIONAL) - return rect; // get the pixel aspect ratio for the target monitor - pixel_aspect = monitor->pixel_aspect(); + pixel_aspect = monitor()->pixel_aspect(); // determine the proposed width/height propwidth = rect.width() - extrawidth; @@ -929,21 +1079,21 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad { case WMSZ_BOTTOM: case WMSZ_TOP: - m_target->compute_visible_area(10000, propheight, pixel_aspect, m_target->orientation(), propwidth, propheight); + target()->compute_visible_area(10000, propheight, pixel_aspect, target()->orientation(), propwidth, propheight); break; case WMSZ_LEFT: case WMSZ_RIGHT: - m_target->compute_visible_area(propwidth, 10000, pixel_aspect, m_target->orientation(), propwidth, propheight); + target()->compute_visible_area(propwidth, 10000, pixel_aspect, target()->orientation(), propwidth, propheight); break; default: - m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), propwidth, propheight); + target()->compute_visible_area(propwidth, propheight, pixel_aspect, target()->orientation(), propwidth, propheight); break; } // get the minimum width/height for the current layout - m_target->compute_minimum_size(minwidth, minheight); + target()->compute_minimum_size(minwidth, minheight); // clamp against the absolute minimum propwidth = std::max(propwidth, MIN_WINDOW_DIM); @@ -956,13 +1106,13 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad // clamp against the maximum (fit on one screen for full screen mode) if (m_fullscreen) { - maxwidth = monitor->position_size().width() - extrawidth; - maxheight = monitor->position_size().height() - extraheight; + maxwidth = monitor()->position_size().width() - extrawidth; + maxheight = monitor()->position_size().height() - extraheight; } else { - maxwidth = monitor->usuable_position_size().width() - extrawidth; - maxheight = monitor->usuable_position_size().height() - extraheight; + maxwidth = monitor()->usuable_position_size().width() - extrawidth; + maxheight = monitor()->usuable_position_size().height() - extraheight; // further clamp to the maximum width/height in the window if (m_win_config.width != 0) @@ -976,7 +1126,11 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad propheight = std::min(propheight, maxheight); // compute the visible area based on the proposed rectangle - m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), viswidth, visheight); + target()->compute_visible_area(propwidth, propheight, pixel_aspect, target()->orientation(), viswidth, visheight); + + // clamp visable area to the proposed rectangle + viswidth = std::min(viswidth, propwidth); + visheight = std::min(visheight, propheight); // compute the adjustments we need to make adjwidth = (viswidth + extrawidth) - rect.width(); @@ -1024,7 +1178,13 @@ osd_dim sdl_window_info::get_min_bounds(int constrain) //assert(GetCurrentThreadId() == window_threadid); // get the minimum target size - m_target->compute_minimum_size(minwidth, minheight); + target()->compute_minimum_size(minwidth, minheight); + + // check if visible area is bigger + int32_t viswidth, visheight; + target()->compute_visible_area(minwidth, minheight, monitor()->aspect(), target()->orientation(), viswidth, visheight); + minwidth = std::max(viswidth, minwidth); + minheight = std::max(visheight, minheight); // expand to our minimum dimensions if (minwidth < MIN_WINDOW_DIM) @@ -1037,7 +1197,7 @@ osd_dim sdl_window_info::get_min_bounds(int constrain) minheight += wnd_extra_height(); // if we want it constrained, figure out which one is larger - if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL) + if (constrain) { // first constrain with no height limit osd_rect test1(0,0,minwidth,10000); @@ -1089,8 +1249,8 @@ osd_dim sdl_window_info::get_max_bounds(int constrain) //assert(GetCurrentThreadId() == window_threadid); // compute the maximum client area - // m_monitor->refresh(); - osd_rect maximum = m_monitor->usuable_position_size(); + // monitor()->refresh(); + osd_rect maximum = monitor()->usuable_position_size(); // clamp to the window's max int tempw = maximum.width(); @@ -1111,7 +1271,7 @@ osd_dim sdl_window_info::get_max_bounds(int constrain) maximum = maximum.resize(tempw, temph); // constrain to fit - if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL) + if (constrain) maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT); // remove extra window stuff @@ -1120,43 +1280,87 @@ 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(*config) - , m_next(nullptr) + : 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) , m_windowed_dim(0, 0) , m_rendered_event(0, 1) - , m_target(nullptr) , m_extra_flags(0) - , m_machine(a_machine) - , m_monitor(a_monitor) - , m_fullscreen(0) , m_mouse_captured(false) , m_mouse_hidden(false) + , m_pointer_mask(0) + , m_next_pointer(0) + , m_mouse_inside(false) { - m_index = index; - //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 = global_alloc(SDL_DM_Wrapper); + + m_ptrdev_info.reserve(1); + m_active_pointers.reserve(16); } sdl_window_info::~sdl_window_info() { - global_free(m_original_mode); } diff --git a/src/osd/sdl/window.h b/src/osd/sdl/window.h index d6010e91ed2..49fe452192f 100644 --- a/src/osd/sdl/window.h +++ b/src/osd/sdl/window.h @@ -8,17 +8,18 @@ // //============================================================ -#ifndef __SDLWINDOW__ -#define __SDLWINDOW__ - -#include "osdsdl.h" -#include "video.h" +#ifndef MAME_OSD_SDL_WINDOW_H +#define MAME_OSD_SDL_WINDOW_H #include "modules/osdwindow.h" +#include "osdsync.h" + +#include <SDL2/SDL.h> +#include <chrono> #include <cstdint> #include <memory> -#include <list> +#include <vector> //============================================================ @@ -27,18 +28,18 @@ 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, ATTR_UNUSED int threadid) +#define OSDWORK_CALLBACK(name) void *name(void *param, int threadid) 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(); @@ -49,7 +50,7 @@ public: void toggle_full_screen(); void modify_prescale(int dir); void resize(int32_t width, int32_t height); - void destroy() override; + void complete_destroy() override; void capture_pointer() override; void release_pointer() override; @@ -62,43 +63,36 @@ public: int xy_to_render_target(int x, int y, int *xt, int *yt); - running_machine &machine() const override { return m_machine; } - osd_monitor_info *monitor() const override { return m_monitor.get(); } - int fullscreen() const override { return m_fullscreen; } - - render_target *target() override { return m_target; } - - int prescale() const { return m_prescale; } - - // Pointer to next window - sdl_window_info * m_next; + 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 - char m_title[256]; - 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; - render_target * m_target; - - // Original display_mode - SDL_DM_Wrapper *m_original_mode; + sdl_pointer_info(SDL_FingerID, unsigned i, unsigned d); - int m_extra_flags; + SDL_FingerID finger; + }; // returns 0 on success, else 1 int complete_create(); - void complete_destroy(); -private: int wnd_extra_width(); int wnd_extra_height(); - void set_starting_view(int index, const char *defview, const char *view); osd_rect constrain_to_aspect_ratio(const osd_rect &rect, int adjustment); osd_dim get_min_bounds(int constrain); osd_dim get_max_bounds(int constrain); @@ -106,50 +100,35 @@ private: osd_dim pick_best_mode(); void set_fullscreen(int afullscreen) { m_fullscreen = afullscreen; } - // Pointer to machine - running_machine & m_machine; - - // monitor info - std::shared_ptr<osd_monitor_info> m_monitor; - int m_fullscreen; - bool m_mouse_captured; - bool m_mouse_hidden; - void measure_fps(int update); -}; - -struct osd_draw_callbacks -{ - osd_renderer *(*create)(osd_window *window); -}; + std::vector<sdl_pointer_info>::iterator map_pointer(SDL_FingerID finger, unsigned device); -//============================================================ -// PROTOTYPES -//============================================================ - -//============================================================ -// PROTOTYPES - drawsdl.c -//============================================================ - -int drawsdl_scale_mode(const char *s); - -//============================================================ -// 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 /* __SDLWINDOW__ */ +#endif // MAME_OSD_SDL_WINDOW_H |