Merge pull request #1403 from bradhugh/monitor_module

Convert OSD monitor info to modules plus add DXGI implementation
This commit is contained in:
Brad Hughes 2016-09-16 13:51:18 -04:00 committed by GitHub
commit d5ab804c2b
24 changed files with 832 additions and 564 deletions

View File

@ -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"),

View File

@ -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",

View File

@ -16,6 +16,7 @@
#include "winutf8.h"
#include "winutil.h"
#include "modules/lib/osdobj_common.h"
bool debugwin_info::s_window_class_registered = false;

View File

@ -15,6 +15,7 @@
#undef interface
#include "window.h"
#include "winmain.h"
//============================================================
// TYPEDEFS

View File

@ -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();

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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!

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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
//============================================================
@ -479,26 +333,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
//============================================================

View File

@ -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

View File

@ -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));

View File

@ -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
//============================================================

View File

@ -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

View File

@ -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();
}

View File

@ -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;

View File

@ -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;