summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/osd/modules.lua6
-rw-r--r--scripts/src/osd/sdl.lua1
-rw-r--r--src/osd/modules/debugger/win/debugwininfo.cpp1
-rw-r--r--src/osd/modules/input/input_windows.h1
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp20
-rw-r--r--src/osd/modules/lib/osdobj_common.h18
-rw-r--r--src/osd/modules/monitor/monitor_common.cpp116
-rw-r--r--src/osd/modules/monitor/monitor_common.h43
-rw-r--r--src/osd/modules/monitor/monitor_dxgi.cpp172
-rw-r--r--src/osd/modules/monitor/monitor_module.h97
-rw-r--r--src/osd/modules/monitor/monitor_sdl.cpp161
-rw-r--r--src/osd/modules/monitor/monitor_win32.cpp142
-rw-r--r--src/osd/modules/osdwindow.cpp5
-rw-r--r--src/osd/modules/osdwindow.h50
-rw-r--r--src/osd/modules/render/drawd3d.cpp7
-rw-r--r--src/osd/modules/render/drawsdl.cpp3
-rw-r--r--src/osd/sdl/video.cpp168
-rw-r--r--src/osd/sdl/video.h39
-rw-r--r--src/osd/sdl/window.cpp5
-rw-r--r--src/osd/windows/video.cpp220
-rw-r--r--src/osd/windows/video.h30
-rw-r--r--src/osd/windows/window.cpp86
-rw-r--r--src/osd/windows/window.h4
-rw-r--r--src/osd/windows/winmain.cpp1
24 files changed, 832 insertions, 564 deletions
diff --git a/scripts/src/osd/modules.lua b/scripts/src/osd/modules.lua
index 59cbc8c1d32..7fb7a81f90b 100644
--- a/scripts/src/osd/modules.lua
+++ b/scripts/src/osd/modules.lua
@@ -60,6 +60,7 @@ function osdmodulesbuild()
MAME_DIR .. "src/osd/modules/netdev/netdev_module.h",
MAME_DIR .. "src/osd/modules/sound/sound_module.h",
MAME_DIR .. "src/osd/modules/diagnostics/diagnostics_module.h",
+ MAME_DIR .. "src/osd/modules/monitor/monitor_module.h",
MAME_DIR .. "src/osd/modules/lib/osdobj_common.cpp",
MAME_DIR .. "src/osd/modules/lib/osdobj_common.h",
MAME_DIR .. "src/osd/modules/diagnostics/none.cpp",
@@ -118,6 +119,11 @@ function osdmodulesbuild()
MAME_DIR .. "src/osd/modules/ipc/rtc_tcp_connection.h",
MAME_DIR .. "src/osd/modules/ipc/rtc_tcp_server.cpp",
MAME_DIR .. "src/osd/modules/ipc/rtc_tcp_server.h",
+ MAME_DIR .. "src/osd/modules/monitor/monitor_common.h",
+ MAME_DIR .. "src/osd/modules/monitor/monitor_common.cpp",
+ MAME_DIR .. "src/osd/modules/monitor/monitor_win32.cpp",
+ MAME_DIR .. "src/osd/modules/monitor/monitor_dxgi.cpp",
+ MAME_DIR .. "src/osd/modules/monitor/monitor_sdl.cpp",
}
includedirs {
ext_includedir("uv"),
diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua
index 44b957d8dde..af6ff1b98ce 100644
--- a/scripts/src/osd/sdl.lua
+++ b/scripts/src/osd/sdl.lua
@@ -422,7 +422,6 @@ project ("osd_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/sdl/sdlmain.cpp",
MAME_DIR .. "src/osd/osdepend.h",
MAME_DIR .. "src/osd/sdl/video.cpp",
- MAME_DIR .. "src/osd/sdl/video.h",
MAME_DIR .. "src/osd/sdl/window.cpp",
MAME_DIR .. "src/osd/sdl/window.h",
MAME_DIR .. "src/osd/modules/osdwindow.cpp",
diff --git a/src/osd/modules/debugger/win/debugwininfo.cpp b/src/osd/modules/debugger/win/debugwininfo.cpp
index 61f57511d6e..fda0a1144fc 100644
--- a/src/osd/modules/debugger/win/debugwininfo.cpp
+++ b/src/osd/modules/debugger/win/debugwininfo.cpp
@@ -16,6 +16,7 @@
#include "winutf8.h"
#include "winutil.h"
+#include "modules/lib/osdobj_common.h"
bool debugwin_info::s_window_class_registered = false;
diff --git a/src/osd/modules/input/input_windows.h b/src/osd/modules/input/input_windows.h
index 3a4cad97613..0a0e30ac808 100644
--- a/src/osd/modules/input/input_windows.h
+++ b/src/osd/modules/input/input_windows.h
@@ -15,6 +15,7 @@
#undef interface
#include "window.h"
+#include "winmain.h"
//============================================================
// TYPEDEFS
diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp
index 745b71f4d1a..351b87aa269 100644
--- a/src/osd/modules/lib/osdobj_common.cpp
+++ b/src/osd/modules/lib/osdobj_common.cpp
@@ -56,6 +56,7 @@ const options_entry osd_options::s_option_entries[] =
{ OSDOPTION_MAXIMIZE ";max", "1", OPTION_BOOLEAN, "default to maximized windows; otherwise, windows will be minimized" },
{ OSDOPTION_WAITVSYNC ";vs", "0", OPTION_BOOLEAN, "enable waiting for the start of VBLANK before flipping screens; reduces tearing effects" },
{ OSDOPTION_SYNCREFRESH ";srf", "0", OPTION_BOOLEAN, "enable using the start of VBLANK for throttling instead of the game time" },
+ { OSD_MONITOR_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "monitor discovery method" },
// per-window options
{ nullptr, nullptr, OPTION_HEADER, "OSD PER-WINDOW VIDEO OPTIONS" },
@@ -179,6 +180,7 @@ osd_common_t::osd_common_t(osd_options &options)
m_lightgun_input(nullptr),
m_joystick_input(nullptr),
m_output(nullptr),
+ m_monitor_module(nullptr),
m_watchdog(nullptr)
{
osd_output::push(this);
@@ -213,6 +215,10 @@ void osd_common_t::register_options()
REGISTER_MODULE(m_mod_man, SOUND_SDL);
REGISTER_MODULE(m_mod_man, SOUND_NONE);
+ REGISTER_MODULE(m_mod_man, MONITOR_SDL);
+ REGISTER_MODULE(m_mod_man, MONITOR_WIN32);
+ REGISTER_MODULE(m_mod_man, MONITOR_DXGI);
+
#ifdef SDLMAME_MACOSX
REGISTER_MODULE(m_mod_man, DEBUG_OSX);
#endif
@@ -265,8 +271,15 @@ void osd_common_t::register_options()
const char *names[20];
int num;
- m_mod_man.get_module_names(OSD_FONT_PROVIDER, 20, &num, names);
std::vector<const char *> dnames;
+
+ m_mod_man.get_module_names(OSD_MONITOR_PROVIDER, 20, &num, names);
+ for (int i = 0; i < num; i++)
+ dnames.push_back(names[i]);
+ update_option(OSD_MONITOR_PROVIDER, dnames);
+
+ m_mod_man.get_module_names(OSD_FONT_PROVIDER, 20, &num, names);
+ dnames.clear();
for (int i = 0; i < num; i++)
dnames.push_back(names[i]);
update_option(OSD_FONT_PROVIDER, dnames);
@@ -618,6 +631,11 @@ static void output_notifier_callback(const char *outname, INT32 value, void *par
void osd_common_t::init_subsystems()
{
+ // monitors have to be initialized before video init
+ m_monitor_module = select_module_options<monitor_module *>(options(), OSD_MONITOR_PROVIDER);
+ assert(m_monitor_module != nullptr);
+ m_monitor_module->init(options());
+
if (!video_init())
{
video_exit();
diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h
index 7d4238fcbbd..55f14d803f5 100644
--- a/src/osd/modules/lib/osdobj_common.h
+++ b/src/osd/modules/lib/osdobj_common.h
@@ -23,6 +23,7 @@
#include "modules/netdev/netdev_module.h"
#include "modules/midi/midi_module.h"
#include "modules/output/output_module.h"
+#include "modules/monitor/monitor_module.h"
#include "emuopts.h"
#include "../frontend/mame/ui/menuitem.h"
@@ -278,14 +279,15 @@ private:
}
protected:
- sound_module* m_sound;
- debug_module* m_debugger;
- midi_module* m_midi;
- input_module* m_keyboard_input;
- input_module* m_mouse_input;
- input_module* m_lightgun_input;
- input_module* m_joystick_input;
- output_module* m_output;
+ sound_module* m_sound;
+ debug_module* m_debugger;
+ midi_module* m_midi;
+ input_module* m_keyboard_input;
+ input_module* m_mouse_input;
+ input_module* m_lightgun_input;
+ input_module* m_joystick_input;
+ output_module* m_output;
+ monitor_module* m_monitor_module;
std::unique_ptr<osd_watchdog> m_watchdog;
std::vector<ui::menu_item> m_sliders;
diff --git a/src/osd/modules/monitor/monitor_common.cpp b/src/osd/modules/monitor/monitor_common.cpp
new file mode 100644
index 00000000000..5a1a5fa8377
--- /dev/null
+++ b/src/osd/modules/monitor/monitor_common.cpp
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:Brad Hughes, Aaron Giles, Olivier Galibert, R. Belmont
+/*
+* monitor_common.cpp
+*
+*/
+
+#include <algorithm>
+
+#include "monitor_common.h"
+#include "modules/osdwindow.h"
+
+std::shared_ptr<osd_monitor_info> monitor_module_base::pick_monitor(osd_options& options, int index)
+{
+ // get the aspect ratio
+ float aspect = get_aspect(options.aspect(), options.aspect(index), TRUE);
+
+ auto monitor = pick_monitor_internal(options, index);
+ if (aspect != 0)
+ {
+ monitor->set_aspect(aspect);
+ }
+
+ return monitor;
+}
+
+std::shared_ptr<osd_monitor_info> monitor_module_base::monitor_from_handle(std::uint64_t handle)
+{
+ if (!m_initialized)
+ return nullptr;
+
+ auto monitor = m_monitor_index[handle];
+
+ // If we have been initialized, make sure we can find the monitor
+ assert(monitor != nullptr);
+
+ return monitor;
+}
+
+void monitor_module_base::add_monitor(std::shared_ptr<osd_monitor_info> monitor)
+{
+ list().push_back(monitor);
+ m_monitor_index[monitor->oshandle()] = monitor;
+}
+
+std::shared_ptr<osd_monitor_info> monitor_module_base::pick_monitor_internal(osd_options& options, int index)
+{
+ std::string scrname, scrname2;
+
+ // get the screen option
+ scrname = options.screen();
+ scrname2 = options.screen(index);
+
+ // decide which one we want to use
+ if (scrname2 != "auto")
+ scrname = scrname2;
+
+ // look for a match in the name first
+ if (!scrname.empty())
+ {
+ auto mon = std::find_if(std::begin(list()), std::end(list()), [&scrname](auto m)
+ {
+ return m->devicename() == scrname;
+ });
+
+ if (mon != std::end(list()))
+ {
+ return *mon;
+ }
+ }
+
+ // didn't find it; alternate monitors until we hit the jackpot
+ // this allows for more screens than monitors but will put one on each monitor first
+ index %= list().size();
+ auto next_monitor = list()[index];
+ return next_monitor;
+}
+
+float monitor_module_base::get_aspect(const char* defdata, const char* data, int report_error)
+{
+ int num = 0, den = 1;
+
+ if (strcmp(data, OSDOPTVAL_AUTO) == 0)
+ {
+ if (strcmp(defdata, OSDOPTVAL_AUTO) == 0)
+ return 0;
+ data = defdata;
+ }
+ if (sscanf(data, "%d:%d", &num, &den) != 2 && report_error)
+ osd_printf_error("Illegal aspect ratio value = %s\n", data);
+
+ return float(num) / float(den);
+}
+
+int monitor_module_base::init(const osd_options& options)
+{
+ if (!m_initialized)
+ {
+ int result = init_internal(options);
+
+ if (result == 0)
+ m_initialized = true;
+
+ return result;
+ }
+
+ return 0;
+}
+
+void monitor_module_base::exit()
+{
+ // free all of our monitor information
+ list().clear();
+ m_monitor_index.clear();
+ m_initialized = false;
+}
diff --git a/src/osd/modules/monitor/monitor_common.h b/src/osd/modules/monitor/monitor_common.h
new file mode 100644
index 00000000000..c021ebcfcb7
--- /dev/null
+++ b/src/osd/modules/monitor/monitor_common.h
@@ -0,0 +1,43 @@
+// license:BSD-3-Clause
+// copyright-holders:Brad Hughes
+/*
+* monitor_common.h
+*
+*/
+
+#include "modules/lib/osdobj_common.h"
+#include <map>
+
+//============================================================
+// monitor_module_base
+//============================================================
+
+class monitor_module_base : public monitor_module
+{
+private:
+ std::map<std::uint64_t, std::shared_ptr<osd_monitor_info>> m_monitor_index;
+
+protected:
+ bool m_initialized;
+
+public:
+ monitor_module_base(const char* type, const char* name)
+ : monitor_module(type, name),
+ m_initialized(false)
+ {
+ }
+
+ std::shared_ptr<osd_monitor_info> pick_monitor(osd_options& options, int index) override;
+ std::shared_ptr<osd_monitor_info> monitor_from_handle(std::uint64_t handle) override;
+
+ int init(const osd_options& options) override;
+ void exit() override;
+
+protected:
+ virtual int init_internal(const osd_options& options) = 0;
+ void add_monitor(std::shared_ptr<osd_monitor_info> monitor);
+
+private:
+ std::shared_ptr<osd_monitor_info> pick_monitor_internal(osd_options& options, int index);
+ static float get_aspect(const char *defdata, const char *data, int report_error);
+};
diff --git a/src/osd/modules/monitor/monitor_dxgi.cpp b/src/osd/modules/monitor/monitor_dxgi.cpp
new file mode 100644
index 00000000000..6619bdc23f3
--- /dev/null
+++ b/src/osd/modules/monitor/monitor_dxgi.cpp
@@ -0,0 +1,172 @@
+// license:BSD-3-Clause
+// copyright-holders: Brad Hughes
+/*
+* monitor_dxgi.cpp
+*
+*/
+
+#include "modules/osdmodule.h"
+#include "monitor_module.h"
+
+#if defined(OSD_WINDOWS)
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <dxgi1_2.h>
+#include <wrl/client.h>
+#undef interface
+#undef min
+#undef max
+
+#include "strconv.h"
+#include "modules/lib/osdlib.h"
+#include "monitor_common.h"
+#include "window.h"
+#include "windows/video.h"
+
+using namespace Microsoft::WRL;
+
+class dxgi_monitor_info : public osd_monitor_info
+{
+private:
+ ComPtr<IDXGIOutput> m_output; // The output interface
+
+public:
+ dxgi_monitor_info(monitor_module& module, HMONITOR handle, const char* monitor_device, float aspect, ComPtr<IDXGIOutput> output)
+ : osd_monitor_info(module, reinterpret_cast<std::uint64_t>(handle), monitor_device, aspect),
+ m_output(output)
+ {
+ dxgi_monitor_info::refresh();
+ }
+
+ void refresh() override
+ {
+ DXGI_OUTPUT_DESC desc;
+ m_output->GetDesc(&desc);
+
+ // fetch the latest info about the monitor
+ m_name = utf8_from_wstring(desc.DeviceName);
+
+ m_pos_size = RECT_to_osd_rect(desc.DesktopCoordinates);
+ m_usuable_pos_size = RECT_to_osd_rect(desc.DesktopCoordinates);
+ m_is_primary = desc.AttachedToDesktop;
+ }
+};
+
+typedef DWORD(WINAPI *dxgi_create_factory_fn)(REFIID, void**);
+
+class dxgi_monitor_module : public monitor_module_base
+{
+private:
+ osd::dynamic_module::ptr m_dxgi_module;
+ dxgi_create_factory_fn m_create_factory_fn;
+
+public:
+ dxgi_monitor_module()
+ : monitor_module_base(OSD_MONITOR_PROVIDER, "dxgi"),
+ m_dxgi_module(osd::dynamic_module::open({"dxgi.dll"})),
+ m_create_factory_fn(nullptr)
+ {
+ }
+
+ bool probe() override
+ {
+ m_create_factory_fn = m_dxgi_module->bind<dxgi_create_factory_fn>("CreateDXGIFactory1");
+ if (m_create_factory_fn == nullptr)
+ return false;
+
+ return true;
+ }
+
+ // Currently this method implementation is duplicated from the win32 module
+ // however it needs to also handle being able to do this for UWP
+ std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect& rect) override
+ {
+ if (!m_initialized)
+ return nullptr;
+
+ RECT p;
+ p.top = rect.top();
+ p.left = rect.left();
+ p.bottom = rect.bottom();
+ p.right = rect.right();
+
+ auto nearest = monitor_from_handle(reinterpret_cast<std::uintptr_t>(MonitorFromRect(&p, MONITOR_DEFAULTTONEAREST)));
+ assert(nearest != nullptr);
+ return nearest;
+ }
+
+ // Currently this method implementation is duplicated from the win32 module
+ // however it needs to also handle being able to do this for UWP
+ std::shared_ptr<osd_monitor_info> monitor_from_window(const osd_window& window) override
+ {
+ if (!m_initialized)
+ return nullptr;
+
+ auto nearest = monitor_from_handle(reinterpret_cast<std::uintptr_t>(MonitorFromWindow(window.platform_window<HWND>(), MONITOR_DEFAULTTONEAREST)));
+ assert(nearest != nullptr);
+ return nearest;
+ }
+
+protected:
+ int init_internal(const osd_options& options) override
+ {
+ HRESULT result;
+ ComPtr<IDXGIDevice> dxgiDevice;
+ ComPtr<IDXGIFactory2> factory;
+ ComPtr<IDXGIAdapter> adapter;
+
+ result = m_create_factory_fn(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(factory.GetAddressOf()));
+ if (result != ERROR_SUCCESS)
+ {
+ osd_printf_error("CreateDXGIFactory1 failed with error 0x%x\n", static_cast<unsigned int>(result));
+ return 1;
+ }
+
+ UINT iAdapter = 0;
+ while (!factory->EnumAdapters(iAdapter, adapter.ReleaseAndGetAddressOf()))
+ {
+ UINT i = 0;
+ ComPtr<IDXGIOutput> output;
+ DXGI_OUTPUT_DESC desc;
+ while (!adapter->EnumOutputs(i, output.GetAddressOf()))
+ {
+ output->GetDesc(&desc);
+
+ // guess the aspect ratio assuming square pixels
+ RECT * coords = &desc.DesktopCoordinates;
+ float aspect = float(coords->right - coords->left) / float(coords->bottom - coords->top);
+
+ // allocate a new monitor info
+ std::string devicename = utf8_from_wstring(desc.DeviceName);
+
+ // allocate a new monitor info
+ auto monitor = std::make_shared<dxgi_monitor_info>(*this, desc.Monitor, devicename.c_str(), aspect, output);
+
+ // hook us into the list
+ add_monitor(monitor);
+
+ i++;
+ }
+
+ iAdapter++;
+ }
+
+ // if we're verbose, print the list of monitors
+ {
+ for (auto monitor : list())
+ {
+ osd_printf_verbose("Video: Monitor %I64u = \"%s\" %s\n", monitor->oshandle(), monitor->devicename().c_str(), monitor->is_primary() ? "(primary)" : "");
+ }
+ }
+
+ return 0;
+ }
+};
+
+#else
+MODULE_NOT_SUPPORTED(dxgi_monitor_module, OSD_MONITOR_PROVIDER, "dxgi")
+#endif
+
+MODULE_DEFINITION(MONITOR_DXGI, dxgi_monitor_module) \ No newline at end of file
diff --git a/src/osd/modules/monitor/monitor_module.h b/src/osd/modules/monitor/monitor_module.h
new file mode 100644
index 00000000000..3244e7fd42b
--- /dev/null
+++ b/src/osd/modules/monitor/monitor_module.h
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Brad Hughes, Aaron Giles, Olivier Galibert, R. Belmont
+/*
+ * monitor_module.h
+ *
+ */
+
+#ifndef MAME_OSD_MODULES_MONITOR_MONITORMODULE_H
+#define MAME_OSD_MODULES_MONITOR_MONITORMODULE_H
+
+#include <vector>
+
+#include "modules/osdmodule.h"
+#include "modules/osdhelper.h"
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+#define OSD_MONITOR_PROVIDER "monitorprovider"
+
+class monitor_module;
+class osd_window;
+
+//============================================================
+// osd_monitor_info
+//============================================================
+
+class osd_monitor_info
+{
+public:
+ osd_monitor_info(monitor_module &module, std::uint64_t handle, const char *monitor_device, float aspect)
+ : m_is_primary(false), m_name(monitor_device), m_module(module), m_handle(handle), m_aspect(aspect)
+ {
+ }
+
+ virtual ~osd_monitor_info() { }
+
+ virtual void refresh() = 0;
+
+ std::uint64_t oshandle() const { return m_handle; }
+ monitor_module& module() const { return m_module; }
+
+ const osd_rect &position_size() const { return m_pos_size; }
+ const osd_rect &usuable_position_size() const { return m_usuable_pos_size; }
+
+ const std::string &devicename() const
+ {
+ static std::string s_unknown = std::string("UNKNOWN");
+ return m_name.length() ? m_name : s_unknown;
+ }
+
+ float aspect() const { return m_aspect; }
+ float pixel_aspect() const { return m_aspect / (float(m_pos_size.width()) / float(m_pos_size.height())); }
+
+ void update_resolution(const int new_width, const int new_height) const { m_pos_size.resize(new_width, new_height); }
+ void set_aspect(const float a) { m_aspect = a; }
+ bool is_primary() const { return m_is_primary; }
+
+protected:
+ osd_rect m_pos_size;
+ osd_rect m_usuable_pos_size;
+ bool m_is_primary;
+ std::string m_name;
+private:
+ monitor_module& m_module;
+ std::uint64_t m_handle; // handle to the monitor
+ float m_aspect; // computed/configured aspect ratio of the physical device
+};
+
+//============================================================
+// monitor_module
+//============================================================
+
+class monitor_module : public osd_module
+{
+private:
+ std::vector<std::shared_ptr<osd_monitor_info>> m_list;
+
+public:
+ monitor_module(const char *type, const char *name)
+ : osd_module(type, name)
+ {
+ }
+
+ virtual ~monitor_module() { }
+
+ std::vector<std::shared_ptr<osd_monitor_info>> & list() { return m_list; }
+
+ virtual std::shared_ptr<osd_monitor_info> monitor_from_handle(std::uint64_t handle) = 0;
+ virtual std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect &rect) = 0;
+ virtual std::shared_ptr<osd_monitor_info> monitor_from_window(const osd_window &window) = 0;
+
+ virtual std::shared_ptr<osd_monitor_info> pick_monitor(osd_options &options, int index) = 0;
+};
+
+#endif // MAME_OSD_MODULES_MONITOR_MONITORMODULE_H
diff --git a/src/osd/modules/monitor/monitor_sdl.cpp b/src/osd/modules/monitor/monitor_sdl.cpp
new file mode 100644
index 00000000000..ade1a3b1140
--- /dev/null
+++ b/src/osd/modules/monitor/monitor_sdl.cpp
@@ -0,0 +1,161 @@
+// license:BSD-3-Clause
+// copyright-holders: Brad Hughes, Olivier Galibert, R. Belmont
+/*
+ * monitor_sdl.cpp
+ *
+ */
+
+#include "modules/osdmodule.h"
+#include "monitor_module.h"
+
+#if defined(OSD_SDL)
+
+#include <algorithm>
+#include <SDL2/SDL.h>
+
+#include "modules/osdwindow.h"
+#include "monitor_common.h"
+
+inline osd_rect SDL_Rect_to_osd_rect(const SDL_Rect &r)
+{
+ return osd_rect(r.x, r.y, r.w, r.h);
+}
+
+ //============================================================
+ // sdl_monitor_info
+ //============================================================
+
+class sdl_monitor_info : public osd_monitor_info
+{
+public:
+ sdl_monitor_info(monitor_module &module, std::uint64_t handle, const char *monitor_device, float aspect)
+ : osd_monitor_info(module, handle, monitor_device, aspect)
+ {
+ sdl_monitor_info::refresh();
+ }
+
+private:
+ void refresh() override
+ {
+ SDL_DisplayMode dmode;
+
+#if defined(SDLMAME_WIN32)
+ SDL_GetDesktopDisplayMode(oshandle(), &dmode);
+#else
+ SDL_GetCurrentDisplayMode(oshandle(), &dmode);
+#endif
+ SDL_Rect dimensions;
+ SDL_GetDisplayBounds(oshandle(), &dimensions);
+
+ m_pos_size = SDL_Rect_to_osd_rect(dimensions);
+ m_usuable_pos_size = SDL_Rect_to_osd_rect(dimensions);
+ m_is_primary = (oshandle() == 0);
+ }
+};
+
+//============================================================
+// sdl_monitor_module
+//============================================================
+
+class sdl_monitor_module : public monitor_module_base
+{
+public:
+ sdl_monitor_module()
+ : monitor_module_base(OSD_MONITOR_PROVIDER, "sdl")
+ {
+ }
+
+ //
+ // Given a proposed rect, returns the monitor whose bounds intersect the most with it
+ //
+ // Windows OSD uses this kind of mechanism to constrain resizing but SDL does not
+ // The method below will allow this but isn't used by SDL OSD yet
+ //
+ std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect& proposed) override
+ {
+ if (!m_initialized)
+ return nullptr;
+
+ // Determines whether the first intersects less with the proposed rect than the second
+ auto intersects_less = [&proposed](std::shared_ptr<osd_monitor_info> mon1, std::shared_ptr<osd_monitor_info> mon2)
+ {
+ int value1 = compute_intersection(mon1->usuable_position_size(), proposed);
+ int value2 = compute_intersection(mon2->usuable_position_size(), proposed);
+
+ return value1 < value2;
+ };
+
+ // Find the one that intersects with the proposed rect the most
+ auto monitor = std::max_element(std::begin(list()), std::end(list()), intersects_less);
+ return *monitor;
+ }
+
+ std::shared_ptr<osd_monitor_info> monitor_from_window(const osd_window& window) override
+ {
+ if (!m_initialized)
+ return nullptr;
+
+ std::uint64_t display = SDL_GetWindowDisplayIndex(window.platform_window<SDL_Window*>());
+ return monitor_from_handle(display);
+ }
+
+protected:
+ int init_internal(const osd_options& options) override
+ {
+ // make a list of monitors
+ {
+ int i;
+
+ osd_printf_verbose("Enter init_monitors\n");
+
+ for (i = 0; i < SDL_GetNumVideoDisplays(); i++)
+ {
+ char temp[64];
+ snprintf(temp, sizeof(temp) - 1, "%s%d", OSDOPTION_SCREEN, i);
+
+ // allocate a new monitor info
+ std::shared_ptr<osd_monitor_info> monitor = std::make_shared<sdl_monitor_info>(*this, i, temp, 1.0f);
+
+ osd_printf_verbose("Adding monitor %s (%d x %d)\n", monitor->devicename().c_str(),
+ monitor->position_size().width(), monitor->position_size().height());
+
+ // guess the aspect ratio assuming square pixels
+ monitor->set_aspect(static_cast<float>(monitor->position_size().width()) / static_cast<float>(monitor->position_size().height()));
+
+ // hook us into the list
+ add_monitor(monitor);
+ }
+ }
+ osd_printf_verbose("Leave init_monitors\n");
+
+ return 0;
+ }
+
+private:
+ static void osdrect_to_sdlrect(const osd_rect &osd, SDL_Rect &sdl)
+ {
+ sdl.h = osd.height();
+ sdl.w = osd.width();
+ sdl.x = osd.left();
+ sdl.y = osd.top();
+ }
+
+ static int compute_intersection(const osd_rect &rect1, const osd_rect &rect2)
+ {
+ SDL_Rect sdl1, sdl2;
+ osdrect_to_sdlrect(rect1, sdl1);
+ osdrect_to_sdlrect(rect2, sdl2);
+
+ SDL_Rect intersection;
+ if (SDL_IntersectRect(&sdl1, &sdl2, &intersection))
+ return intersection.w + intersection.h;
+
+ return 0;
+ }
+};
+
+#else
+MODULE_NOT_SUPPORTED(sdl_monitor_module, OSD_MONITOR_PROVIDER, "sdl")
+#endif
+
+MODULE_DEFINITION(MONITOR_SDL, sdl_monitor_module) \ No newline at end of file
diff --git a/src/osd/modules/monitor/monitor_win32.cpp b/src/osd/modules/monitor/monitor_win32.cpp
new file mode 100644
index 00000000000..01fe69e9629
--- /dev/null
+++ b/src/osd/modules/monitor/monitor_win32.cpp
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders: Brad Hughes, Aaron Giles
+/*
+ * monitor_win32.cpp
+ *
+ */
+
+#include "modules/osdmodule.h"
+#include "monitor_module.h"
+
+#if defined(OSD_WINDOWS)
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef interface
+#undef min
+#undef max
+
+#include "strconv.h"
+#include "windows/video.h"
+#include "window.h"
+#include "monitor_common.h"
+
+class win32_monitor_module;
+
+class win32_monitor_info : public osd_monitor_info
+{
+private:
+ MONITORINFOEX m_info;
+
+public:
+ win32_monitor_info(monitor_module& module, const HMONITOR handle, const char* monitor_device, float aspect)
+ : osd_monitor_info(module, std::intptr_t(handle), monitor_device, aspect)
+ {
+ win32_monitor_info::refresh();
+ }
+
+ void refresh() override
+ {
+ BOOL result;
+
+ // fetch the latest info about the monitor
+ m_info.cbSize = sizeof(m_info);
+ result = GetMonitorInfo(reinterpret_cast<HMONITOR>(oshandle()), static_cast<LPMONITORINFO>(&m_info));
+ assert(result);
+
+ m_name = utf8_from_tstring(m_info.szDevice);
+
+ m_pos_size = RECT_to_osd_rect(m_info.rcMonitor);
+ m_usuable_pos_size = RECT_to_osd_rect(m_info.rcWork);
+ m_is_primary = ((m_info.dwFlags & MONITORINFOF_PRIMARY) != 0);
+ (void)result; // to silence gcc 4.6
+ }
+};
+
+class win32_monitor_module : public monitor_module_base
+{
+public:
+ win32_monitor_module()
+ : monitor_module_base(OSD_MONITOR_PROVIDER, "win32")
+ {
+ }
+
+ std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect& rect) override
+ {
+ if (!m_initialized)
+ return nullptr;
+
+ RECT p;
+ p.top = rect.top();
+ p.left = rect.left();
+ p.bottom = rect.bottom();
+ p.right = rect.right();
+
+ auto nearest = monitor_from_handle(reinterpret_cast<std::uintptr_t>(MonitorFromRect(&p, MONITOR_DEFAULTTONEAREST)));
+ assert(nearest != nullptr);
+ return nearest;
+ }
+
+ std::shared_ptr<osd_monitor_info> monitor_from_window(const osd_window& window) override
+ {
+ if (!m_initialized)
+ return nullptr;
+
+ auto nearest = monitor_from_handle(reinterpret_cast<std::uintptr_t>(MonitorFromWindow(window.platform_window<HWND>(), MONITOR_DEFAULTTONEAREST)));
+ assert(nearest != nullptr);
+ return nearest;
+ }
+
+protected:
+ int init_internal(const osd_options& options) override
+ {
+ // make a list of monitors
+ EnumDisplayMonitors(nullptr, nullptr, monitor_enum_callback, reinterpret_cast<std::intptr_t>(this));
+
+ // if we're verbose, print the list of monitors
+ {
+ for (auto monitor : list())
+ {
+ osd_printf_verbose("Video: Monitor %I64u = \"%s\" %s\n", monitor->oshandle(), monitor->devicename().c_str(), monitor->is_primary() ? "(primary)" : "");
+ }
+ }
+
+ return 0;
+ }
+
+private:
+ static BOOL CALLBACK monitor_enum_callback(HMONITOR handle, HDC dc, LPRECT rect, LPARAM data)
+ {
+ win32_monitor_module* self = reinterpret_cast<win32_monitor_module*>(data);
+ MONITORINFOEX info;
+ BOOL result;
+
+ // get the monitor info
+ info.cbSize = sizeof(info);
+ result = GetMonitorInfo(handle, static_cast<LPMONITORINFO>(&info));
+ assert(result);
+ (void)result; // to silence gcc 4.6
+
+ // guess the aspect ratio assuming square pixels
+ float aspect = static_cast<float>(info.rcMonitor.right - info.rcMonitor.left) / static_cast<float>(info.rcMonitor.bottom - info.rcMonitor.top);
+
+ // allocate a new monitor info
+ auto temp = utf8_from_tstring(info.szDevice);
+
+ // copy in the data
+ auto monitor = std::make_shared<win32_monitor_info>(*self, handle, temp.c_str(), aspect);
+
+ // hook us into the list
+ self->add_monitor(monitor);
+
+ // enumerate all the available monitors so to list their names in verbose mode
+ return TRUE;
+ }
+};
+
+#else
+MODULE_NOT_SUPPORTED(win32_monitor_module, OSD_MONITOR_PROVIDER, "win32")
+#endif
+
+MODULE_DEFINITION(MONITOR_WIN32, win32_monitor_module) \ No newline at end of file
diff --git a/src/osd/modules/osdwindow.cpp b/src/osd/modules/osdwindow.cpp
index c7afccb029c..16fc8817184 100644
--- a/src/osd/modules/osdwindow.cpp
+++ b/src/osd/modules/osdwindow.cpp
@@ -21,6 +21,11 @@
#include "render/drawsdl.h"
#endif
+float osd_window::pixel_aspect() const
+{
+ return monitor()->pixel_aspect();
+}
+
std::unique_ptr<osd_renderer> osd_renderer::make_for_type(int mode, std::shared_ptr<osd_window> window, int extra_flags)
{
switch(mode)
diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h
index 3fa62babfbf..ca6ddbd375e 100644
--- a/src/osd/modules/osdwindow.h
+++ b/src/osd/modules/osdwindow.h
@@ -41,7 +41,7 @@ enum
VIDEO_MODE_NONE = 0,
VIDEO_MODE_GDI,
VIDEO_MODE_BGFX,
-#if (USE_OPENGL)
+#if defined(USE_OPENGL) && USE_OPENGL
VIDEO_MODE_OPENGL,
#endif
VIDEO_MODE_SDL2ACCEL,
@@ -51,46 +51,6 @@ enum
VIDEO_MODE_COUNT
};
-class osd_monitor_info
-{
-public:
- osd_monitor_info(void *handle, const char *monitor_device, float aspect)
- : m_is_primary(false), m_name(monitor_device), m_handle(handle), m_aspect(aspect)
- {
- }
-
- virtual ~osd_monitor_info() { }
-
- virtual void refresh() = 0;
-
- const void *oshandle() const { return m_handle; }
-
- const osd_rect &position_size() const { return m_pos_size; }
- const osd_rect &usuable_position_size() const { return m_usuable_pos_size; }
-
- const char *devicename() const { return m_name.length() ? m_name.c_str() : "UNKNOWN"; }
-
- float aspect() const { return m_aspect; }
- float pixel_aspect() const { return m_aspect / ((float)m_pos_size.width() / (float)m_pos_size.height()); }
-
- void update_resolution(const int new_width, const int new_height) const { m_pos_size.resize(new_width, new_height); }
- void set_aspect(const float a) { m_aspect = a; }
- bool is_primary() const { return m_is_primary; }
-
- static std::shared_ptr<osd_monitor_info> pick_monitor(osd_options &options, int index);
-
- static std::list<std::shared_ptr<osd_monitor_info>> list;
-
-protected:
- osd_rect m_pos_size;
- osd_rect m_usuable_pos_size;
- bool m_is_primary;
- std::string m_name;
-private:
- void * m_handle; // handle to the monitor
- float m_aspect; // computed/configured aspect ratio of the physical device
-};
-
class osd_window_config
{
public:
@@ -104,6 +64,7 @@ public:
};
class osd_renderer;
+class osd_monitor_info;
class osd_window : public std::enable_shared_from_this<osd_window>
{
@@ -126,15 +87,17 @@ public:
virtual int fullscreen() const = 0;
virtual running_machine &machine() const = 0;
+ 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(); }
int prescale() const { return m_prescale; };
- float pixel_aspect() const { return monitor()->pixel_aspect(); }
+ float pixel_aspect() const;
bool swap_xy()
{
@@ -173,11 +136,8 @@ public:
virtual void update() = 0;
virtual void destroy() = 0;
- void renderer_reset() { m_renderer.reset(); }
#ifndef OSD_SDL
virtual bool win_has_menu() = 0;
- // FIXME: cann we replace winwindow_video_window_monitor(nullptr) with monitor() ?
- virtual std::shared_ptr<osd_monitor_info> winwindow_video_window_monitor(const osd_rect *proposed) = 0;
HDC m_dc; // only used by GDI renderer!
diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp
index 17d77dd4446..61371a05184 100644
--- a/src/osd/modules/render/drawd3d.cpp
+++ b/src/osd/modules/render/drawd3d.cpp
@@ -19,6 +19,7 @@
#include "window.h"
#include "drawd3d.h"
#include "modules/render/d3d/d3dhlsl.h"
+#include "modules/monitor/monitor_module.h"
#undef min
#undef max
#include <utility>
@@ -1227,7 +1228,7 @@ int renderer_d3d9::config_adapter_mode()
// make sure it's a pixel format we can get behind
if (m_pixformat != D3DFMT_X1R5G5B5 && m_pixformat != D3DFMT_R5G6B5 && m_pixformat != D3DFMT_X8R8G8B8)
{
- osd_printf_error("Device %s currently in an unsupported mode\n", win->monitor()->devicename());
+ osd_printf_error("Device %s currently in an unsupported mode\n", win->monitor()->devicename().c_str());
return 1;
}
}
@@ -1250,7 +1251,7 @@ int renderer_d3d9::config_adapter_mode()
result = d3dintf->d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !win->fullscreen());
if (FAILED(result))
{
- osd_printf_error("Proposed video mode not supported on device %s\n", win->monitor()->devicename());
+ osd_printf_error("Proposed video mode not supported on device %s\n", win->monitor()->devicename().c_str());
return 1;
}
return 0;
@@ -1274,7 +1275,7 @@ int renderer_d3d9::get_adapter_for_monitor()
HMONITOR curmonitor = d3dintf->d3dobj->GetAdapterMonitor(adapternum);
// if we match the proposed monitor, this is it
- if (curmonitor == *((HMONITOR *)win->monitor()->oshandle()))
+ if (curmonitor == reinterpret_cast<HMONITOR>(win->monitor()->oshandle()))
{
return adapternum;
}
diff --git a/src/osd/modules/render/drawsdl.cpp b/src/osd/modules/render/drawsdl.cpp
index 4a0c3c0fea1..7b937086bf8 100644
--- a/src/osd/modules/render/drawsdl.cpp
+++ b/src/osd/modules/render/drawsdl.cpp
@@ -27,6 +27,7 @@
#include "window.h"
#include "drawsdl.h"
+#include "modules/monitor/monitor_module.h"
//============================================================
// DEBUGGING
@@ -108,7 +109,7 @@ void renderer_sdl1::setup_texture(const osd_dim &size)
auto win = assert_window();
// Determine preferred pixelformat and set up yuv if necessary
- SDL_GetCurrentDisplayMode(*((UINT64 *)win->monitor()->oshandle()), &mode);
+ SDL_GetCurrentDisplayMode(win->monitor()->oshandle(), &mode);
if (m_yuv_bitmap)
{
diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp
index 38204017290..5ec47a105a0 100644
--- a/src/osd/sdl/video.cpp
+++ b/src/osd/sdl/video.cpp
@@ -34,10 +34,6 @@
osd_video_config video_config;
-// monitor info
-std::list<std::shared_ptr<osd_monitor_info>> osd_monitor_info::list;
-
-
//============================================================
// LOCAL VARIABLES
//============================================================
@@ -49,7 +45,6 @@ std::list<std::shared_ptr<osd_monitor_info>> osd_monitor_info::list;
static void check_osd_inputs(running_machine &machine);
-static float get_aspect(const char *defdata, const char *data, int report_error);
static void get_resolution(const char *defdata, const char *data, osd_window_config *config, int report_error);
@@ -64,9 +59,6 @@ bool sdl_osd_interface::video_init()
// extract data from the options
extract_video_config();
- // set up monitors first
- sdl_monitor_info::init();
-
// we need the beam width in a float, contrary to what the core does.
video_config.beamwidth = options().beam_width_min();
@@ -82,7 +74,7 @@ bool sdl_osd_interface::video_init()
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, osd_monitor_info::pick_monitor(reinterpret_cast<osd_options &>(options()), index), &conf);
+ 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);
if (win->window_init())
return false;
@@ -98,34 +90,6 @@ bool sdl_osd_interface::video_init()
void sdl_osd_interface::video_exit()
{
window_exit();
- sdl_monitor_info::exit();
-}
-
-
-//============================================================
-// sdlvideo_monitor_refresh
-//============================================================
-
-inline osd_rect SDL_Rect_to_osd_rect(const SDL_Rect &r)
-{
- return osd_rect(r.x, r.y, r.w, r.h);
-}
-
-void sdl_monitor_info::refresh()
-{
- SDL_DisplayMode dmode;
-
- #if defined(SDLMAME_WIN32)
- SDL_GetDesktopDisplayMode(m_handle, &dmode);
- #else
- SDL_GetCurrentDisplayMode(m_handle, &dmode);
- #endif
- SDL_Rect dimensions;
- SDL_GetDisplayBounds(m_handle, &dimensions);
-
- m_pos_size = SDL_Rect_to_osd_rect(dimensions);
- m_usuable_pos_size = SDL_Rect_to_osd_rect(dimensions);
- m_is_primary = (m_handle == 0);
}
//============================================================
@@ -154,116 +118,6 @@ void sdl_osd_interface::update(bool skip_redraw)
debugger_update();
}
-
-//============================================================
-// init_monitors
-//============================================================
-
-void sdl_monitor_info::init()
-{
- // make a list of monitors
- {
- int i;
-
- osd_printf_verbose("Enter init_monitors\n");
-
- for (i = 0; i < SDL_GetNumVideoDisplays(); i++)
- {
- char temp[64];
- snprintf(temp, sizeof(temp)-1, "%s%d", OSDOPTION_SCREEN,i);
-
- // allocate a new monitor info
-
- std::shared_ptr<osd_monitor_info> monitor = std::make_shared<sdl_monitor_info>(i, temp, 1.0f);
-
- osd_printf_verbose("Adding monitor %s (%d x %d)\n", monitor->devicename(),
- monitor->position_size().width(), monitor->position_size().height());
-
- // guess the aspect ratio assuming square pixels
- monitor->set_aspect(static_cast<float>(monitor->position_size().width()) / static_cast<float>(monitor->position_size().height()));
-
- // hook us into the list
- osd_monitor_info::list.push_back(monitor);
- }
- }
- osd_printf_verbose("Leave init_monitors\n");
-}
-
-void sdl_monitor_info::exit()
-{
- // free all of our monitor information
- while (!osd_monitor_info::list.empty())
- {
- osd_monitor_info::list.remove(osd_monitor_info::list.front());
- }
-}
-
-
-//============================================================
-// pick_monitor
-//============================================================
-
-std::shared_ptr<osd_monitor_info> osd_monitor_info::pick_monitor(osd_options &generic_options, int index)
-{
- sdl_options &options = reinterpret_cast<sdl_options &>(generic_options);
- std::shared_ptr<osd_monitor_info> monitor;
- const char *scrname, *scrname2;
- int moncount = 0;
- float aspect;
-
- // get the screen option
- scrname = options.screen();
- scrname2 = options.screen(index);
-
- // decide which one we want to use
- if (strcmp(scrname2, "auto") != 0)
- scrname = scrname2;
-
- // get the aspect ratio
- aspect = get_aspect(options.aspect(), options.aspect(index), TRUE);
-
- // look for a match in the name first
- if (scrname != nullptr && (scrname[0] != 0))
- {
- for (auto mon : osd_monitor_info::list)
- {
- moncount++;
- if (strcmp(scrname, mon->devicename()) == 0)
- {
- monitor = mon;
- goto finishit;
- }
- }
- }
-
- // didn't find it; alternate monitors until we hit the jackpot
- index %= moncount;
- for (auto mon : osd_monitor_info::list)
- if (index-- == 0)
- {
- monitor = mon;
- goto finishit;
- }
-
- // return the primary just in case all else fails
- for (auto mon : osd_monitor_info::list)
- if (mon->is_primary())
- {
- monitor = mon;
- goto finishit;
- }
-
- // FIXME: FatalError?
-finishit:
- if (aspect != 0)
- {
- monitor->set_aspect(aspect);
- }
-
- return monitor;
-}
-
-
//============================================================
// check_osd_inputs
//============================================================
@@ -480,26 +334,6 @@ void sdl_osd_interface::extract_video_config()
//============================================================
-// get_aspect
-//============================================================
-
-static float get_aspect(const char *defdata, const char *data, int report_error)
-{
- int num = 0, den = 1;
-
- if (strcmp(data, OSDOPTVAL_AUTO) == 0)
- {
- if (strcmp(defdata,OSDOPTVAL_AUTO) == 0)
- return 0;
- data = defdata;
- }
- if (sscanf(data, "%d:%d", &num, &den) != 2 && report_error)
- osd_printf_error("Illegal aspect ratio value = %s\n", data);
- return (float)num / (float)den;
-}
-
-
-//============================================================
// get_resolution
//============================================================
diff --git a/src/osd/sdl/video.h b/src/osd/sdl/video.h
deleted file mode 100644
index 82db031aba1..00000000000
--- a/src/osd/sdl/video.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// video.h - SDL implementation of MAME video routines
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-
-#ifndef __SDLVIDEO__
-#define __SDLVIDEO__
-
-#include "osdsdl.h"
-#include "modules/osdwindow.h"
-
-//============================================================
-// TYPE DEFINITIONS
-//============================================================
-
-class sdl_monitor_info : public osd_monitor_info
-{
-public:
- sdl_monitor_info(const UINT64 handle, const char *monitor_device, float aspect)
- : osd_monitor_info(&m_handle, monitor_device, aspect), m_handle(handle)
- {
- sdl_monitor_info::refresh();
- }
-
- // STATIC
- static void init();
- static void exit();
-private:
- void virtual refresh() override;
-
- UINT64 m_handle; // handle to the monitor
-};
-
-#endif
diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp
index 450b4b59550..83c967e4306 100644
--- a/src/osd/sdl/window.cpp
+++ b/src/osd/sdl/window.cpp
@@ -38,6 +38,7 @@
#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"
#endif
@@ -502,7 +503,7 @@ osd_dim sdl_window_info::pick_best_mode()
}
// FIXME: this should be provided by monitor !
- num = SDL_GetNumDisplayModes(*((UINT64 *)m_monitor->oshandle()));
+ num = SDL_GetNumDisplayModes(m_monitor->oshandle());
if (num == 0)
{
@@ -514,7 +515,7 @@ osd_dim sdl_window_info::pick_best_mode()
for (i = 0; i < num; ++i)
{
SDL_DisplayMode mode;
- SDL_GetDisplayMode(*((UINT64 *)m_monitor->oshandle()), i, &mode);
+ SDL_GetDisplayMode(m_monitor->oshandle(), i, &mode);
// compute initial score based on difference between target and current
size_score = 1.0f / (1.0f + abs((INT32)mode.w - target_width) + abs((INT32)mode.h - target_height));
diff --git a/src/osd/windows/video.cpp b/src/osd/windows/video.cpp
index 0d4232fcd1c..f752d28e29c 100644
--- a/src/osd/windows/video.cpp
+++ b/src/osd/windows/video.cpp
@@ -18,7 +18,6 @@
// MAMEOS headers
#include "winmain.h"
-#include "video.h"
#include "window.h"
#include "strconv.h"
@@ -35,22 +34,11 @@
osd_video_config video_config;
-// monitor info
-std::list<std::shared_ptr<osd_monitor_info>> osd_monitor_info::list;
-
-
-//============================================================
-// LOCAL VARIABLES
-//============================================================
-
//============================================================
// PROTOTYPES
//============================================================
-static void init_monitors(void);
-
-static float get_aspect(const char *defdata, const char *data, int report_error);
static void get_resolution(const char *defdata, const char *data, osd_window_config *config, int report_error);
@@ -66,9 +54,6 @@ bool windows_osd_interface::video_init()
// extract data from the options
extract_video_config();
- // set up monitors first
- init_monitors();
-
// initialize the window system so we can make windows
window_init();
@@ -76,7 +61,7 @@ bool windows_osd_interface::video_init()
windows_options &options = downcast<windows_options &>(machine().options());
for (int index = 0; index < video_config.numscreens; index++)
{
- win_window_info::create(machine(), index, osd_monitor_info::pick_monitor(options, index), &windows[index]);
+ win_window_info::create(machine(), index, m_monitor_module->pick_monitor(options, index), &windows[index]);
}
if (video_config.mode != VIDEO_MODE_NONE)
@@ -92,65 +77,8 @@ bool windows_osd_interface::video_init()
void windows_osd_interface::video_exit()
{
window_exit();
-
- // free all of our monitor information
- while (!osd_monitor_info::list.empty())
- {
- osd_monitor_info::list.remove(osd_monitor_info::list.front());
- }
-}
-
-
-
-win_monitor_info::win_monitor_info(const HMONITOR handle, const char *monitor_device, float aspect)
- : osd_monitor_info(&m_handle, monitor_device, aspect), m_handle(handle)
-{
- win_monitor_info::refresh();
-}
-
-win_monitor_info::~win_monitor_info()
-{
-}
-
-//============================================================
-// winvideo_monitor_refresh
-//============================================================
-
-void win_monitor_info::refresh()
-{
- BOOL result;
-
- // fetch the latest info about the monitor
- m_info.cbSize = sizeof(m_info);
- result = GetMonitorInfo(m_handle, static_cast<LPMONITORINFO>(&m_info));
- assert(result);
-
- m_name = utf8_from_tstring(m_info.szDevice);
-
- m_pos_size = RECT_to_osd_rect(m_info.rcMonitor);
- m_usuable_pos_size = RECT_to_osd_rect(m_info.rcWork);
- m_is_primary = ((m_info.dwFlags & MONITORINFOF_PRIMARY) != 0);
- (void)result; // to silence gcc 4.6
-}
-
-
-
-//============================================================
-// winvideo_monitor_from_handle
-//============================================================
-
-std::shared_ptr<osd_monitor_info> win_monitor_info::monitor_from_handle(HMONITOR hmonitor)
-{
- // find the matching monitor
- for (auto monitor : osd_monitor_info::list)
- if (*((HMONITOR*)monitor->oshandle()) == hmonitor)
- return monitor;
-
- return nullptr;
}
-
-
//============================================================
// update
//============================================================
@@ -178,131 +106,6 @@ void windows_osd_interface::update(bool skip_redraw)
}
-
-
-
-//============================================================
-// monitor_enum_callback
-//============================================================
-
-BOOL CALLBACK win_monitor_info::monitor_enum_callback(HMONITOR handle, HDC dc, LPRECT rect, LPARAM data)
-{
- MONITORINFOEX info;
- BOOL result;
-
- // get the monitor info
- info.cbSize = sizeof(info);
- result = GetMonitorInfo(handle, (LPMONITORINFO)&info);
- assert(result);
- (void)result; // to silence gcc 4.6
-
- // guess the aspect ratio assuming square pixels
- float aspect = static_cast<float>(info.rcMonitor.right - info.rcMonitor.left) / static_cast<float>(info.rcMonitor.bottom - info.rcMonitor.top);
-
- // allocate a new monitor info
- auto temp = utf8_from_tstring(info.szDevice);
-
- // copy in the data
- auto monitor = std::make_shared<win_monitor_info>(handle, temp.c_str(), aspect);
-
- // hook us into the list
- osd_monitor_info::list.push_back(monitor);
-
- // enumerate all the available monitors so to list their names in verbose mode
- return TRUE;
-}
-
-
-//============================================================
-// init_monitors
-//============================================================
-
-static void init_monitors(void)
-{
- osd_monitor_info **tailptr;
-
- // make a list of monitors
- EnumDisplayMonitors(nullptr, nullptr, win_monitor_info::monitor_enum_callback, (LPARAM)&tailptr);
-
- // if we're verbose, print the list of monitors
- {
- for (auto monitor : osd_monitor_info::list)
- {
- osd_printf_verbose("Video: Monitor %p = \"%s\" %s\n", monitor->oshandle(), monitor->devicename(), monitor->is_primary() ? "(primary)" : "");
- }
- }
-}
-
-
-//============================================================
-// pick_monitor
-//============================================================
-
-std::shared_ptr<osd_monitor_info> osd_monitor_info::pick_monitor(osd_options &osdopts, int index)
-{
- windows_options &options = reinterpret_cast<windows_options &>(osdopts);
- std::shared_ptr<osd_monitor_info> monitor;
- const char *scrname, *scrname2;
- int moncount = 0;
- float aspect;
-
- // get the screen option
- scrname = options.screen();
- scrname2 = options.screen(index);
-
- // decide which one we want to use
- if (strcmp(scrname2, "auto") != 0)
- scrname = scrname2;
-
- // get the aspect ratio
- aspect = get_aspect(options.aspect(), options.aspect(index), TRUE);
-
- // look for a match in the name first
- if (scrname != nullptr && (scrname[0] != 0))
- {
- for (auto mon : osd_monitor_info::list)
- {
- moncount++;
- if (strcmp(scrname, mon->devicename()) == 0)
- {
- monitor = mon;
- goto finishit;
- }
- }
- }
-
- // didn't find it; alternate monitors until we hit the jackpot
- index %= moncount;
- for (auto mon : osd_monitor_info::list)
- {
- if (index-- == 0)
- {
- monitor = mon;
- goto finishit;
- }
- }
-
- // return the primary just in case all else fails
- for (auto mon : osd_monitor_info::list)
- {
- if (mon->is_primary())
- {
- monitor = mon;
- goto finishit;
- }
- }
-
- // FIXME: FatalError?
-finishit:
- if (aspect != 0)
- {
- monitor->set_aspect(aspect);
- }
-
- return monitor;
-}
-
-
//============================================================
// check_osd_inputs
//============================================================
@@ -451,27 +254,6 @@ void windows_osd_interface::extract_video_config()
}
-
-//============================================================
-// get_aspect
-//============================================================
-
-static float get_aspect(const char *defdata, const char *data, int report_error)
-{
- int num = 0, den = 1;
-
- if (strcmp(data, OSDOPTVAL_AUTO) == 0)
- {
- if (strcmp(defdata,OSDOPTVAL_AUTO) == 0)
- return 0;
- data = defdata;
- }
- if (sscanf(data, "%d:%d", &num, &den) != 2 && report_error)
- osd_printf_error("Illegal aspect ratio value = %s\n", data);
- return (float)num / (float)den;
-}
-
-
//============================================================
// get_resolution
//============================================================
diff --git a/src/osd/windows/video.h b/src/osd/windows/video.h
index 59d14fa20d5..3f4b49efbe4 100644
--- a/src/osd/windows/video.h
+++ b/src/osd/windows/video.h
@@ -9,39 +9,11 @@
#ifndef __WIN_VIDEO__
#define __WIN_VIDEO__
-#include "render.h"
-#include "winmain.h"
-#include "modules/osdwindow.h"
-
-//============================================================
-// TYPE DEFINITIONS
-//============================================================
+#include "modules/osdhelper.h"
inline osd_rect RECT_to_osd_rect(const RECT &r)
{
return osd_rect(r.left, r.top, r.right - r.left, r.bottom - r.top);
}
-class win_monitor_info : public osd_monitor_info
-{
-public:
- win_monitor_info(const HMONITOR handle, const char *monitor_device, float aspect);
- virtual ~win_monitor_info();
-
- virtual void refresh() override;
-
- // static
-
- static BOOL CALLBACK monitor_enum_callback(HMONITOR handle, HDC dc, LPRECT rect, LPARAM data);
- static std::shared_ptr<osd_monitor_info> monitor_from_handle(HMONITOR monitor);
-
- HMONITOR handle() const { return m_handle; }
-
-private:
- HMONITOR m_handle; // handle to the monitor
-#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- MONITORINFOEX m_info; // most recently retrieved info
-#endif
-};
-
#endif
diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp
index 12832f8580d..a17fa3006ea 100644
--- a/src/osd/windows/window.cpp
+++ b/src/osd/windows/window.cpp
@@ -32,6 +32,8 @@
#include "winutil.h"
+#include "modules/monitor/monitor_common.h"
+
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#include <agile.h>
using namespace Windows::UI::Core;
@@ -211,7 +213,7 @@ void windows_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())
+ if (window->has_renderer() && window->renderer().sliders_dirty())
{
build_slider_list();
return;
@@ -230,9 +232,12 @@ void windows_osd_interface::build_slider_list()
for (auto window : osd_common_t::s_window_list)
{
- // take the sliders of the first window
- std::vector<ui::menu_item> window_sliders = window->renderer().get_slider_list();
- m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end());
+ if (window->has_renderer())
+ {
+ // take the sliders of the first window
+ std::vector<ui::menu_item> window_sliders = window->renderer().get_slider_list();
+ m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end());
+ }
}
}
@@ -782,7 +787,28 @@ void win_window_info::create(running_machine &machine, int index, std::shared_pt
fatalerror("Unable to complete window creation\n");
}
+std::shared_ptr<osd_monitor_info> win_window_info::monitor_from_rect(const osd_rect* proposed) const
+{
+ std::shared_ptr<osd_monitor_info> monitor;
+ // in window mode, find the nearest
+ if (!fullscreen())
+ {
+ if (proposed != nullptr)
+ {
+ monitor = m_monitor->module().monitor_from_rect(*proposed);
+ }
+ else
+ monitor = m_monitor->module().monitor_from_window(*this);
+ }
+ else
+ {
+ // in full screen, just use the configured monitor
+ monitor = m_monitor;
+ }
+
+ return monitor;
+}
//============================================================
// winwindow_video_window_destroy
@@ -839,7 +865,7 @@ void win_window_info::update()
}
// if we're visible and running and not in the middle of a resize, draw
- if (platform_window<HWND>() != nullptr && m_target != nullptr)
+ if (platform_window<HWND>() != nullptr && m_target != nullptr && has_renderer())
{
bool got_lock = true;
@@ -868,44 +894,6 @@ void win_window_info::update()
}
}
-
-
-//============================================================
-// winwindow_video_window_monitor
-// (window thread)
-//============================================================
-
-std::shared_ptr<osd_monitor_info> win_window_info::winwindow_video_window_monitor(const osd_rect *proposed)
-{
- std::shared_ptr<osd_monitor_info> monitor;
-
- // in window mode, find the nearest
- if (!fullscreen())
- {
- if (proposed != nullptr)
- {
- RECT p;
- p.top = proposed->top();
- p.left = proposed->left();
- p.bottom = proposed->bottom();
- p.right = proposed->right();
- monitor = win_monitor_info::monitor_from_handle(MonitorFromRect(&p, MONITOR_DEFAULTTONEAREST));
- }
- else
- monitor = win_monitor_info::monitor_from_handle(MonitorFromWindow(platform_window<HWND>(), MONITOR_DEFAULTTONEAREST));
- }
-
- // in full screen, just use the configured monitor
- else
- monitor = m_monitor;
-
- // make sure we're up-to-date
- //monitor->refresh();
- return monitor;
-}
-
-
-
//============================================================
// create_window_class
// (main thread)
@@ -1418,6 +1406,8 @@ void win_window_info::draw_video_contents(HDC dc, int update)
osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int adjustment)
{
+ assert(GetCurrentThreadId() == window_threadid);
+
INT32 extrawidth = wnd_extra_width();
INT32 extraheight = wnd_extra_height();
INT32 propwidth, propheight;
@@ -1426,9 +1416,13 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad
INT32 viswidth, visheight;
INT32 adjwidth, adjheight;
float pixel_aspect;
- std::shared_ptr<osd_monitor_info> monitor = winwindow_video_window_monitor(&rect);
+
+ auto monitor = monitor_from_rect(&rect);
- assert(GetCurrentThreadId() == window_threadid);
+ // Sometimes this gets called when monitors have already been torn down
+ // In that the case, just return the unmodified rect
+ if (monitor == nullptr)
+ return rect;
// do not constrain aspect ratio for integer scaled views
if (m_target->scale_mode() != SCALE_FRACTIONAL)
@@ -1727,7 +1721,7 @@ void win_window_info::adjust_window_position_after_major_change()
// in full screen, make sure it covers the primary display
else
{
- std::shared_ptr<osd_monitor_info> monitor = winwindow_video_window_monitor(nullptr);
+ std::shared_ptr<osd_monitor_info> monitor = monitor_from_rect(nullptr);
newrect = monitor->position_size();
}
diff --git a/src/osd/windows/window.h b/src/osd/windows/window.h
index 31fd920e40f..e58dfcae44d 100644
--- a/src/osd/windows/window.h
+++ b/src/osd/windows/window.h
@@ -20,7 +20,6 @@
#include <memory>
#include <list>
-#include "video.h"
#include "render.h"
#include "modules/osdwindow.h"
@@ -56,8 +55,6 @@ public:
void update() override;
- virtual std::shared_ptr<osd_monitor_info> winwindow_video_window_monitor(const osd_rect *proposed) override;
-
virtual bool win_has_menu() override
{
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
@@ -139,6 +136,7 @@ private:
void maximize_window();
void adjust_window_position_after_major_change();
void set_fullscreen(int fullscreen);
+ std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect* proposed) const;
static POINT s_saved_cursor_pos;
diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp
index bbb3a56860d..b660000108c 100644
--- a/src/osd/windows/winmain.cpp
+++ b/src/osd/windows/winmain.cpp
@@ -32,6 +32,7 @@
#include "winutil.h"
#include "winfile.h"
#include "modules/diagnostics/diagnostics_module.h"
+#include "modules/monitor/monitor_common.h"
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
using namespace Windows::ApplicationModel;