summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/monitor/monitor_sdl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/monitor/monitor_sdl.cpp')
-rw-r--r--src/osd/modules/monitor/monitor_sdl.cpp161
1 files changed, 161 insertions, 0 deletions
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