diff options
Diffstat (limited to 'src/osd/modules/osdwindow.h')
-rw-r--r-- | src/osd/modules/osdwindow.h | 399 |
1 files changed, 266 insertions, 133 deletions
diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h index 3fe020c56fe..9167a775682 100644 --- a/src/osd/modules/osdwindow.h +++ b/src/osd/modules/osdwindow.h @@ -6,13 +6,21 @@ // //============================================================ -#ifndef __OSDWINDOW__ -#define __OSDWINDOW__ +#ifndef MAME_OSD_MODULES_OSDWINDOW_H +#define MAME_OSD_MODULES_OSDWINDOW_H -#include "render.h" +#pragma once + +#include "emucore.h" #include "osdhelper.h" #include "../frontend/mame/ui/menuitem.h" +#include <cassert> +#include <chrono> +#include <memory> +#include <string> +#include <vector> + // standard windows headers #ifdef OSD_WINDOWS #include <windows.h> @@ -20,32 +28,16 @@ #include <mmsystem.h> #endif -#ifdef OSD_SDL -// forward declaration -struct SDL_Window; -#endif - //============================================================ // TYPE DEFINITIONS //============================================================ -class osd_options; +class osd_monitor_info; +class render_module; class render_primitive_list; -enum -{ - VIDEO_MODE_NONE = 0, - VIDEO_MODE_GDI, - VIDEO_MODE_BGFX, -#if defined(USE_OPENGL) && USE_OPENGL - VIDEO_MODE_OPENGL, -#endif - VIDEO_MODE_SDL2ACCEL, - VIDEO_MODE_D3D, - VIDEO_MODE_SOFT, +class osd_renderer; - VIDEO_MODE_COUNT -}; class osd_window_config { @@ -59,58 +51,37 @@ public: int refresh; // decoded refresh }; -class osd_renderer; -class osd_monitor_info; -class osd_window : public std::enable_shared_from_this<osd_window> +class osd_window { public: - osd_window(const osd_window_config &config) - : -#ifdef OSD_WINDOWS - m_dc(nullptr), m_resize_state(0), -#endif - m_primlist(nullptr), - m_win_config(config), - m_index(0), - m_prescale(1), - m_renderer(nullptr), - m_main(nullptr) - {} - - virtual ~osd_window() { } + virtual ~osd_window(); - virtual render_target *target() = 0; - virtual int fullscreen() const = 0; - virtual running_machine &machine() const = 0; + render_target *target() const { return m_target; } + int fullscreen() const { return m_fullscreen; } + running_machine &machine() const { return m_machine; } + const std::string &title() const { return m_title; } bool has_renderer() const { return m_renderer != nullptr; } osd_renderer &renderer() const { return *m_renderer; } - void set_renderer(std::unique_ptr<osd_renderer> renderer) - { - m_renderer = std::move(renderer); - } - void renderer_reset() { m_renderer.reset(); } + void renderer_reset() { m_renderer.reset(); } // public because OSD object calls it directly during teardown - int prescale() const { return m_prescale; }; + int index() const { return m_index; } + int prescale() const { return m_prescale; } float pixel_aspect() const; - bool swap_xy() - { - bool orientation_swap_xy = - (machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; - bool rotation_swap_xy = - (target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; - return orientation_swap_xy ^ rotation_swap_xy; - }; + bool swap_xy() const; + + bool keepaspect() const; virtual osd_dim get_size() = 0; - virtual osd_monitor_info *monitor() const = 0; + osd_monitor_info *monitor() const { return m_monitor.get(); } + std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect *proposed) const; - std::shared_ptr<osd_window> main_window() const { return m_main; } - void set_main_window(std::shared_ptr<osd_window> main) { m_main = main; } + void create_target(); + void destroy(); // Clips the pointer to the bounds of this window virtual void capture_pointer() = 0; @@ -122,45 +93,252 @@ public: virtual void hide_pointer() = 0; virtual void update() = 0; - virtual void destroy() = 0; + virtual void complete_destroy() = 0; -#if defined(OSD_WINDOWS) || defined(OSD_UWP) - virtual bool win_has_menu() = 0; -#endif +protected: + static inline constexpr int CLICK_DISTANCE = 16; // in pointer units squared + static inline constexpr int TAP_DISTANCE = 49; // taps are less repeatable than clicks -#ifdef OSD_WINDOWS - HDC m_dc; // only used by GDI renderer! - int m_resize_state; -#endif + struct prev_touch + { + prev_touch() = default; + prev_touch(prev_touch const &) = default; + prev_touch(prev_touch &&) = default; + prev_touch &operator=(prev_touch const &) = default; + prev_touch &operator=(prev_touch &&) = default; + + std::chrono::steady_clock::time_point when = std::chrono::steady_clock::time_point::min(); + int x = 0, y = 0, cnt = 0; + }; + + struct pointer_dev_info + { + pointer_dev_info() = default; + pointer_dev_info(pointer_dev_info const &) = default; + pointer_dev_info(pointer_dev_info &&) = default; + pointer_dev_info &operator=(pointer_dev_info const &) = default; + pointer_dev_info &operator=(pointer_dev_info &&) = default; + + unsigned clear_expired_touches(std::chrono::steady_clock::time_point const &now, std::chrono::steady_clock::duration const &time); + unsigned consume_touch(unsigned i); + + prev_touch touches[8]; + }; + + struct pointer_info + { + pointer_info(pointer_info const &) = default; + pointer_info(pointer_info &&) = default; + pointer_info &operator=(pointer_info const &) = default; + pointer_info &operator=(pointer_info &&) = default; + + pointer_info(unsigned i, unsigned d); + + void primary_down( + int cx, + int cy, + std::chrono::steady_clock::duration const &time, + int tolerance, + bool checkprev, + std::vector<pointer_dev_info> &devices); + void check_primary_hold_drag( + int cx, + int cy, + std::chrono::steady_clock::duration const &time, + int tolerance); + + std::chrono::steady_clock::time_point pressed; + unsigned index, device; + int x, y; + unsigned buttons; + int pressedx, pressedy; + int clickcnt; + }; + + osd_window( + running_machine &machine, + render_module &renderprovider, + int index, + const std::shared_ptr<osd_monitor_info> &monitor, + const osd_window_config &config); + + bool renderer_interactive() const; + bool renderer_sdl_needs_opengl() const; + void renderer_create(); + +private: + void set_starting_view(int index, const char *defview, const char *view); + +private: + render_target *m_target; +public: render_primitive_list *m_primlist; osd_window_config m_win_config; +private: int m_index; protected: + bool m_fullscreen; int m_prescale; + private: - std::unique_ptr<osd_renderer> m_renderer; - std::shared_ptr<osd_window> m_main; + running_machine &m_machine; + render_module &m_renderprovider; + std::shared_ptr<osd_monitor_info> m_monitor; + std::unique_ptr<osd_renderer> m_renderer; + const std::string m_title; }; -template <class TWindowHandle> -class osd_window_t : public osd_window + +inline unsigned osd_window::pointer_dev_info::clear_expired_touches( + std::chrono::steady_clock::time_point const &now, + std::chrono::steady_clock::duration const &time) { -private: - TWindowHandle m_platform_window; -public: - osd_window_t(const osd_window_config &config) - : osd_window(config), - m_platform_window(nullptr) + // find first non-expired touch (if any) + unsigned end(0); + while ((std::size(touches) > end) && touches[end].cnt && ((touches[end].when + time) < now)) + touches[end++].cnt = 0; + + // shift non-expired touches back if necessary + if (end) + { + unsigned pos(0); + while ((std::size(touches) > end) && touches[end].cnt) + { + touches[pos++] = std::move(touches[end]); + touches[end++].cnt = 0; + } + return pos; + } + else + { + while ((std::size(touches) > end) && touches[end].cnt) + ++end; + return end; + } +} + +inline unsigned osd_window::pointer_dev_info::consume_touch(unsigned i) +{ + assert(std::size(touches) > i); + touches[i].cnt = 0; + unsigned pos(i + 1); + while ((std::size(touches) > pos) && touches[pos].cnt) + { + touches[i++] = std::move(touches[pos]); + touches[pos++].cnt = 0; + } + return i; +} + +inline osd_window::pointer_info::pointer_info(unsigned i, unsigned d) : + pressed(std::chrono::steady_clock::time_point::min()), + index(i), + device(d), + x(-1), + y(-1), + buttons(0), + pressedx(0), + pressedy(0), + clickcnt(0) +{ +} + +inline void osd_window::pointer_info::primary_down( + int cx, + int cy, + std::chrono::steady_clock::duration const &time, + int tolerance, + bool checkprev, + std::vector<pointer_dev_info> &devices) +{ + auto const now(std::chrono::steady_clock::now()); + auto const exp(time + pressed); + if (0 > clickcnt) + { + // previous click turned into a hold/drag + clickcnt = 1; + } + else if (clickcnt) + { + // potential multi-click action + int const dx(cx - pressedx); + int const dy(cy - pressedy); + int const distance((dx * dx) + (dy * dy)); + if ((exp < now) || (tolerance < distance)) + clickcnt = 1; + else + ++clickcnt; + } + else + { + // first click for this pointer, but may need to check previous touches + clickcnt = 1; + if (checkprev) + { + if (devices.size() > device) + { + auto &devinfo(devices[device]); + unsigned const end(devinfo.clear_expired_touches(now, time)); + for (int i = 0; end > i; ++i) + { + int const dx(cx - devinfo.touches[i].x); + int const dy(cy - devinfo.touches[i].y); + int const distance((dx * dx) + (dy * dy)); + if (tolerance >= distance) + { + // close match - consume it + clickcnt = devinfo.touches[i].cnt + 1; + devinfo.consume_touch(i); + break; + } + } + } + } + } + + // record the time/location where the pointer was pressed + pressed = now; + pressedx = cx; + pressedy = cy; +} + +inline void osd_window::pointer_info::check_primary_hold_drag( + int cx, + int cy, + std::chrono::steady_clock::duration const &time, + int tolerance) +{ + // check for conversion to a (multi-)click-and-hold/drag + if (0 < clickcnt) { + auto const now(std::chrono::steady_clock::now()); + auto const exp(time + pressed); + int const dx(cx - pressedx); + int const dy(cy - pressedy); + int const distance((dx * dx) + (dy * dy)); + if ((exp < now) || (tolerance < distance)) + clickcnt = -clickcnt; } +} + +template <class TWindowHandle> +class osd_window_t : public osd_window +{ +public: TWindowHandle platform_window() const { return m_platform_window; } +protected: + using osd_window::osd_window; + void set_platform_window(TWindowHandle window) { assert(window == nullptr || m_platform_window == nullptr); m_platform_window = window; } + +private: + TWindowHandle m_platform_window = nullptr; }; @@ -170,31 +348,13 @@ public: /* Generic flags */ static const int FLAG_NONE = 0x0000; - static const int FLAG_NEEDS_OPENGL = 0x0001; - static const int FLAG_HAS_VECTOR_SCREEN = 0x0002; + static const int FLAG_HAS_VECTOR_SCREEN = 0x0001; - /* SDL 1.2 flags */ - static const int FLAG_NEEDS_DOUBLEBUF = 0x0100; - static const int FLAG_NEEDS_ASYNCBLIT = 0x0200; - - osd_renderer(std::shared_ptr<osd_window> window, const int flags) - : m_sliders_dirty(false), m_window(window), m_flags(flags) - { } + osd_renderer(osd_window &window) : m_sliders_dirty(false), m_window(window), m_flags(0) { } virtual ~osd_renderer() { } - std::shared_ptr<osd_window> assert_window() const - { - auto win = m_window.lock(); - if (!win) - throw emu_fatalerror("osd_renderer::assert_window: Window weak_ptr is not available!"); - return win; - } - - std::shared_ptr<osd_window> try_getwindow() const - { - return m_window.lock(); - } + osd_window &window() const { return m_window; } bool has_flags(const int flag) const { return ((m_flags & flag)) == flag; } void set_flags(int aflag) { m_flags |= aflag; } @@ -210,14 +370,12 @@ public: virtual void add_audio_to_recording(const int16_t *buffer, int samples_this_frame) { } virtual std::vector<ui::menu_item> get_slider_list() { return m_sliders; } virtual int draw(const int update) = 0; - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) { return 0; }; - virtual void save() { }; - virtual void record() { }; - virtual void toggle_fsfx() { }; + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) { return 0; } + virtual void save() { } + virtual void record() { } + virtual void toggle_fsfx() { } virtual bool sliders_dirty() { return m_sliders_dirty; } - static std::unique_ptr<osd_renderer> make_for_type(int mode, std::shared_ptr<osd_window> window, int extra_flags = FLAG_NONE); - protected: virtual void build_slider_list() { } @@ -227,7 +385,7 @@ protected: std::vector<ui::menu_item> m_sliders; private: - std::weak_ptr<osd_window> m_window; + osd_window &m_window; int m_flags; }; @@ -239,10 +397,6 @@ private: #define MAX_VIDEO_WINDOWS (4) -#define VIDEO_SCALE_MODE_NONE (0) - -#define GLSL_SHADER_MAX 10 - //============================================================ // TYPE DEFINITIONS @@ -253,40 +407,22 @@ struct osd_video_config // global configuration int windowed; // start windowed? int prescale; // prescale factor - int keepaspect; // keep aspect ratio int numscreens; // number of screens - int fullstretch; // fractional stretch // hardware options - int mode; // output mode int waitvsync; // spin until vsync int syncrefresh; // sync only to refresh rate int switchres; // switch resolutions // d3d, accel, opengl int filter; // enable filtering - //int filter; // enable filtering, disabled if glsl_filter>0 - - // OpenGL options - int glsl; - int glsl_filter; // glsl filtering, >0 disables filter - char * glsl_shader_mamebm[GLSL_SHADER_MAX]; // custom glsl shader set, mame bitmap - int glsl_shader_mamebm_num; // custom glsl shader set number, mame bitmap - char * glsl_shader_scrn[GLSL_SHADER_MAX]; // custom glsl shader set, screen bitmap - int glsl_shader_scrn_num; // custom glsl shader number, screen bitmap - int pbo; - int vbo; - int allowtexturerect; // allow GL_ARB_texture_rectangle, default: no - int forcepow2texture; // force power of two textures, default: no - - // dd, d3d + + // d3d int triplebuf; // triple buffer //============================================================ // SDL - options //============================================================ - int novideo; // don't draw, for pure CPU benchmarking - int centerh; int centerv; @@ -298,9 +434,6 @@ struct osd_video_config // X11 options int restrictonemonitor; // in fullscreen, confine to Xinerama monitor 0 - - // YUV options - int scale_mode; }; //============================================================ @@ -309,4 +442,4 @@ struct osd_video_config extern osd_video_config video_config; -#endif /* __OSDWINDOW__ */ +#endif // MAME_OSD_MODULES_OSDWINDOW_H |