diff options
Diffstat (limited to 'src/osd')
60 files changed, 1179 insertions, 792 deletions
diff --git a/src/osd/mac/window.cpp b/src/osd/mac/window.cpp index 4056958b0d9..ea2adbb631f 100644 --- a/src/osd/mac/window.cpp +++ b/src/osd/mac/window.cpp @@ -20,6 +20,7 @@ #include "emu.h" #include "emuopts.h" #include "render.h" +#include "screen.h" #include "ui/uimain.h" // OSD headers @@ -68,17 +69,43 @@ bool mac_osd_interface::window_init() { osd_printf_verbose("Enter macwindow_init\n"); - // initialize the drawers - - switch (video_config.mode) - { - case VIDEO_MODE_BGFX: - renderer_bgfx::init(machine()); - break; - case VIDEO_MODE_OPENGL: - renderer_ogl::init(machine()); + // initialize the renderer + const int fallbacks[VIDEO_MODE_COUNT] = { + -1, // NONE -> no fallback + -1, // No GDI on macOS + VIDEO_MODE_OPENGL, // BGFX -> OpenGL + -1, // OpenGL -> no fallback + -1, // No SDL2ACCEL on macOS + -1, // No D3D on macOS + -1 // No SOFT on macOS + }; + + int current_mode = video_config.mode; + while (current_mode != VIDEO_MODE_NONE) + { + bool error = false; + switch(current_mode) + { + case VIDEO_MODE_BGFX: + error = renderer_bgfx::init(machine()); + break; + case VIDEO_MODE_OPENGL: + renderer_ogl::init(machine()); + break; + default: + fatalerror("Unknown video mode."); + break; + } + if (error) + { + current_mode = fallbacks[current_mode]; + } + else + { break; + } } + video_config.mode = current_mode; // set up the window list osd_printf_verbose("Leave macwindow_init\n"); diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp index 9f26fb2c778..5e477200dc2 100644 --- a/src/osd/modules/debugger/debuggdbstub.cpp +++ b/src/osd/modules/debugger/debuggdbstub.cpp @@ -13,6 +13,7 @@ #include "debug/textbuf.h" #include "debug_module.h" #include "debugger.h" +#include "fileio.h" #include "modules/lib/osdobj_common.h" #include "modules/osdmodule.h" diff --git a/src/osd/modules/debugger/debugimgui.cpp b/src/osd/modules/debugger/debugimgui.cpp index 6271adf97a5..944ed203b79 100644 --- a/src/osd/modules/debugger/debugimgui.cpp +++ b/src/osd/modules/debugger/debugimgui.cpp @@ -142,7 +142,7 @@ private: struct image_type_entry { - floppy_image_format_t* format; + const floppy_image_format_t* format; std::string shortname; std::string longname; }; @@ -987,9 +987,9 @@ void debug_imgui::create_image() { image_init_result res; - if(m_dialog_image->image_type() == IO_FLOPPY) + auto *fd = dynamic_cast<floppy_image_device *>(m_dialog_image); + if(fd != nullptr) { - auto *fd = static_cast<floppy_image_device *>(m_dialog_image); res = fd->create(m_path,nullptr,nullptr); if(res == image_init_result::PASS) fd->setup_write(m_typelist.at(m_format_sel).format); @@ -1061,7 +1061,7 @@ void debug_imgui::refresh_typelist() if(fd == nullptr) return; - for(floppy_image_format_t* flist : fd->get_formats()) + for(const floppy_image_format_t* flist : fd->get_formats()) { if(flist->supports_save()) { @@ -1199,7 +1199,8 @@ void debug_imgui::draw_create_dialog(const char* label) } // format combo box for floppy devices - if(m_dialog_image->image_type() == IO_FLOPPY) + auto *fd = dynamic_cast<floppy_image_device *>(m_dialog_image); + if(fd != nullptr) { std::string combo_str; combo_str.clear(); diff --git a/src/osd/modules/debugger/osx/debugview.mm b/src/osd/modules/debugger/osx/debugview.mm index df7c4dbcc01..8853be80622 100644 --- a/src/osd/modules/debugger/osx/debugview.mm +++ b/src/osd/modules/debugger/osx/debugview.mm @@ -675,7 +675,7 @@ static void debugwin_view_update(debug_view &view, void *osdprivate) NSUInteger start = 0, length = 0; for (uint32_t col = origin.x; col < origin.x + size.x; col++) { - [[text mutableString] appendFormat:@"%c", data[col - origin.x].byte]; + [[text mutableString] appendFormat:@"%C", unichar(data[col - origin.x].byte)]; if ((start < length) && (attr != data[col - origin.x].attrib)) { NSRange const run = NSMakeRange(start, length - start); diff --git a/src/osd/modules/debugger/qt/mainwindow.cpp b/src/osd/modules/debugger/qt/mainwindow.cpp index b0043c06dee..afea2e07919 100644 --- a/src/osd/modules/debugger/qt/mainwindow.cpp +++ b/src/osd/modules/debugger/qt/mainwindow.cpp @@ -220,7 +220,7 @@ void MainWindow::toggleBreakpointAtCursor(bool changedTo) command = string_format("bpset 0x%X", address); else command = string_format("bpclear 0x%X", bp->index()); - m_machine.debugger().console().execute_command(command.c_str(), true); + m_machine.debugger().console().execute_command(command, true); } refreshAll(); @@ -242,7 +242,7 @@ void MainWindow::enableBreakpointAtCursor(bool changedTo) { int32_t const bpindex = bp->index(); std::string command = string_format(bp->enabled() ? "bpdisable 0x%X" : "bpenable 0x%X", bpindex); - m_machine.debugger().console().execute_command(command.c_str(), true); + m_machine.debugger().console().execute_command(command, true); } } @@ -257,7 +257,7 @@ void MainWindow::runToCursor(bool changedTo) { offs_t address = downcast<debug_view_disasm*>(dasmView)->selected_address(); std::string command = string_format("go 0x%X", address); - m_machine.debugger().console().execute_command(command.c_str(), true); + m_machine.debugger().console().execute_command(command, true); } } diff --git a/src/osd/modules/debugger/win/consolewininfo.cpp b/src/osd/modules/debugger/win/consolewininfo.cpp index 1265417c61f..afddcf31d6c 100644 --- a/src/osd/modules/debugger/win/consolewininfo.cpp +++ b/src/osd/modules/debugger/win/consolewininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// consolewininfo.c - Win32 debug window handling +// consolewininfo.cpp - Win32 debug window handling // //============================================================ @@ -20,6 +20,8 @@ #include "strconv.h" #include "winutf8.h" +#include "softlist_dev.h" + consolewin_info::consolewin_info(debugger_windows_interface &debugger) : disasmbasewin_info(debugger, true, "Debug", nullptr), diff --git a/src/osd/modules/input/input_common.h b/src/osd/modules/input/input_common.h index 49c4e768dcf..a26d6f5375e 100644 --- a/src/osd/modules/input/input_common.h +++ b/src/osd/modules/input/input_common.h @@ -295,7 +295,8 @@ private: std::vector<std::unique_ptr<device_info>> m_list; public: - size_t size() const { return m_list.size(); } + auto size() const { return m_list.size(); } + auto empty() const { return m_list.empty(); } auto begin() { return m_list.begin(); } auto end() { return m_list.end(); } @@ -318,7 +319,8 @@ public: m_list.erase(std::remove_if(std::begin(m_list), std::end(m_list), device_matches), m_list.end()); } - void for_each_device(std::function<void (device_info*)> action) + template <typename T> + void for_each_device(T &&action) { for (auto &device: m_list) action(device.get()); @@ -445,7 +447,7 @@ protected: public: const osd_options * options() const { return m_options; } - input_device_list * devicelist() { return &m_devicelist; } + input_device_list & devicelist() { return m_devicelist; } bool input_enabled() const { return m_input_enabled; } bool input_paused() const { return m_input_paused; } bool mouse_enabled() const { return m_mouse_enabled; } @@ -502,7 +504,7 @@ public: virtual void exit() override { - devicelist()->free_all_devices(); + devicelist().free_all_devices(); } protected: diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp index 8ceb29e21f4..7295b23de12 100644 --- a/src/osd/modules/input/input_dinput.cpp +++ b/src/osd/modules/input/input_dinput.cpp @@ -238,7 +238,7 @@ public: result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_REL); if (result != DI_OK && result != DI_PROPNOEFFECT) { - osd_printf_error("DirectInput: Unable to set relative mode for mouse %u (%s)\n", static_cast<unsigned int>(devicelist()->size()), devinfo->name()); + osd_printf_error("DirectInput: Unable to set relative mode for mouse %u (%s)\n", static_cast<unsigned int>(devicelist().size()), devinfo->name()); goto error; } @@ -277,7 +277,7 @@ public: error: if (devinfo) - devicelist()->free_device(*devinfo); + devicelist().free_device(*devinfo); goto exit; } }; @@ -449,10 +449,10 @@ void dinput_joystick_device::poll() int dinput_joystick_device::configure() { HRESULT result; - auto devicelist = static_cast<input_module_base&>(module()).devicelist(); + auto &devicelist = static_cast<input_module_base&>(module()).devicelist(); // temporary approximation of index - int devindex = devicelist->size(); + int devindex = devicelist.size(); // set absolute mode result = dinput_set_dword_property(dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_ABS); diff --git a/src/osd/modules/input/input_dinput.h b/src/osd/modules/input/input_dinput.h index 8600e73a04d..20bced84883 100644 --- a/src/osd/modules/input/input_dinput.h +++ b/src/osd/modules/input/input_dinput.h @@ -72,7 +72,7 @@ public: std::string utf8_instance_id = utf8_instance_name + " product_" + guid_to_string(instance->guidProduct) + " instance_" + guid_to_string(instance->guidInstance); // allocate memory for the device object - TDevice &devinfo = module.devicelist()->create_device<TDevice>(machine, std::move(utf8_instance_name), std::move(utf8_instance_id), module); + TDevice &devinfo = module.devicelist().create_device<TDevice>(machine, std::move(utf8_instance_name), std::move(utf8_instance_id), module); // attempt to create a device result = m_dinput->CreateDevice(instance->guidInstance, devinfo.dinput.device.GetAddressOf(), nullptr); @@ -133,7 +133,7 @@ public: return &devinfo; error: - module.devicelist()->free_device(devinfo); + module.devicelist().free_device(devinfo); return nullptr; } diff --git a/src/osd/modules/input/input_rawinput.cpp b/src/osd/modules/input/input_rawinput.cpp index 248b7bb48ab..6424a0d1099 100644 --- a/src/osd/modules/input/input_rawinput.cpp +++ b/src/osd/modules/input/input_rawinput.cpp @@ -19,6 +19,7 @@ #include <algorithm> #include <functional> #include <mutex> +#include <new> // MAME headers #include "emu.h" @@ -35,12 +36,6 @@ namespace { -// Typedefs for dynamically loaded functions -typedef UINT (WINAPI *get_rawinput_device_list_ptr)(PRAWINPUTDEVICELIST, PUINT, UINT); -typedef UINT (WINAPI *get_rawinput_data_ptr)( HRAWINPUT, UINT, LPVOID, PUINT, UINT); -typedef UINT (WINAPI *get_rawinput_device_info_ptr)(HANDLE, UINT, LPVOID, PUINT); -typedef BOOL (WINAPI *register_rawinput_devices_ptr)(PCRAWINPUTDEVICE, UINT, UINT); - class safe_regkey { private: @@ -294,7 +289,7 @@ public: rawinput_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : rawinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_KEYBOARD, module), - keyboard({{0}}) + keyboard({ { 0 } }) { } @@ -326,7 +321,7 @@ class rawinput_mouse_device : public rawinput_device private: std::mutex m_device_lock; public: - mouse_state mouse; + mouse_state mouse; rawinput_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : rawinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_MOUSE, module), @@ -442,12 +437,7 @@ public: class rawinput_module : public wininput_module { private: - osd::dynamic_module::ptr m_user32_dll; - get_rawinput_device_list_ptr get_rawinput_device_list = nullptr; - get_rawinput_data_ptr get_rawinput_data = nullptr; - get_rawinput_device_info_ptr get_rawinput_device_info = nullptr; - register_rawinput_devices_ptr register_rawinput_devices = nullptr; - std::mutex m_module_lock; + std::mutex m_module_lock; public: rawinput_module(const char *type, const char *name) : wininput_module(type, name) @@ -456,163 +446,234 @@ public: bool probe() override { - m_user32_dll = osd::dynamic_module::open({ "user32.dll" }); - - get_rawinput_device_list = m_user32_dll->bind<get_rawinput_device_list_ptr>("GetRawInputDeviceList"); - get_rawinput_data = m_user32_dll->bind<get_rawinput_data_ptr>("GetRawInputData"); - get_rawinput_device_info = m_user32_dll->bind<get_rawinput_device_info_ptr>("GetRawInputDeviceInfoW"); - register_rawinput_devices = m_user32_dll->bind<register_rawinput_devices_ptr>("RegisterRawInputDevices"); - - return get_rawinput_device_list && get_rawinput_data && get_rawinput_device_info && register_rawinput_devices; + return true; } void input_init(running_machine &machine) override { - // get the number of devices, allocate a device list, and fetch it + // get initial number of devices UINT device_count = 0; - if ((*get_rawinput_device_list)(nullptr, &device_count, sizeof(RAWINPUTDEVICELIST)) != 0) + if (GetRawInputDeviceList(nullptr, &device_count, sizeof(RAWINPUTDEVICELIST)) != 0) + { + osd_printf_error("Error getting initial number of RawInput devices.\n"); return; - - if (device_count == 0) + } + if (!device_count) return; - auto rawinput_devices = std::make_unique<RAWINPUTDEVICELIST[]>(device_count); - if ((*get_rawinput_device_list)(rawinput_devices.get(), &device_count, sizeof(RAWINPUTDEVICELIST)) == UINT(-1)) + std::unique_ptr<RAWINPUTDEVICELIST []> rawinput_devices; + UINT retrieved; + do + { + rawinput_devices.reset(new (std::nothrow) RAWINPUTDEVICELIST [device_count]); + if (!rawinput_devices) + { + osd_printf_error("Error allocating buffer for RawInput device list.\n"); + return; + } + retrieved = GetRawInputDeviceList(rawinput_devices.get(), &device_count, sizeof(RAWINPUTDEVICELIST)); + } + while ((UINT(-1) == retrieved) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)); + if (UINT(-1) == retrieved) + { + osd_printf_error("Error listing RawInput devices.\n"); return; + } // iterate backwards through devices; new devices are added at the head - for (int devnum = device_count - 1; devnum >= 0; devnum--) - { - RAWINPUTDEVICELIST *device = &rawinput_devices[devnum]; - add_rawinput_device(machine, device); - } + for (int devnum = retrieved - 1; devnum >= 0; devnum--) + add_rawinput_device(machine, rawinput_devices[devnum]); // don't enable global inputs when debugging if (!machine.options().debug()) - { m_global_inputs_enabled = downcast<windows_options &>(machine.options()).global_inputs(); - } // If we added no devices, no need to register for notifications - if (devicelist()->size() == 0) + if (devicelist().empty()) return; // finally, register to receive raw input WM_INPUT messages if we found devices RAWINPUTDEVICE registration; registration.usUsagePage = usagepage(); registration.usUsage = usage(); - registration.dwFlags = m_global_inputs_enabled ? 0x00000100 : 0; + registration.dwFlags = RIDEV_DEVNOTIFY; + if (m_global_inputs_enabled) + registration.dwFlags |= RIDEV_INPUTSINK; registration.hwndTarget = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(); // register the device - (*register_rawinput_devices)(®istration, 1, sizeof(registration)); + RegisterRawInputDevices(®istration, 1, sizeof(registration)); } protected: - virtual void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) = 0; + virtual void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) = 0; virtual USHORT usagepage() = 0; virtual USHORT usage() = 0; int init_internal() override { - if (!get_rawinput_device_list || !get_rawinput_data || - !get_rawinput_device_info || !register_rawinput_devices ) - { - return 1; - } - - osd_printf_verbose("RawInput: APIs detected\n"); return 0; } template<class TDevice> - TDevice *create_rawinput_device(running_machine &machine, PRAWINPUTDEVICELIST rawinputdevice) + TDevice *create_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &rawinputdevice) { // determine the length of the device name, allocate it, and fetch it if not nameless UINT name_length = 0; - if ((*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, nullptr, &name_length) != 0) + if (GetRawInputDeviceInfoW(rawinputdevice.hDevice, RIDI_DEVICENAME, nullptr, &name_length) != 0) return nullptr; std::unique_ptr<WCHAR []> tname = std::make_unique<WCHAR []>(name_length + 1); - if (name_length > 1 && (*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, tname.get(), &name_length) == UINT(-1)) + if (name_length > 1 && GetRawInputDeviceInfoW(rawinputdevice.hDevice, RIDI_DEVICENAME, tname.get(), &name_length) == UINT(-1)) return nullptr; // if this is an RDP name, skip it - if (_tcsstr(tname.get(), TEXT("Root#RDP_")) != nullptr) + if (wcsstr(tname.get(), L"Root#RDP_") != nullptr) return nullptr; // improve the name and then allocate a device - std::wstring name = rawinput_device_improve_name(tname.get()); - - // convert name to utf8 - std::string utf8_name = osd::text::from_wstring(name); + std::string utf8_name = osd::text::from_wstring(rawinput_device_improve_name(tname.get())); - // set device id to raw input name + // set device ID to raw input name std::string utf8_id = osd::text::from_wstring(tname.get()); - TDevice &devinfo = devicelist()->create_device<TDevice>(machine, std::move(utf8_name), std::move(utf8_id), *this); + tname.reset(); + + TDevice &devinfo = devicelist().create_device<TDevice>(machine, std::move(utf8_name), std::move(utf8_id), *this); // Add the handle - devinfo.set_handle(rawinputdevice->hDevice); + devinfo.set_handle(rawinputdevice.hDevice); return &devinfo; } bool handle_input_event(input_event eventid, void *eventdata) override { - // Only handle raw input data - if (!input_enabled() || eventid != INPUT_EVENT_RAWINPUT) - return false; - - HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT*>(eventdata); - - BYTE small_buffer[4096]; - std::unique_ptr<BYTE[]> larger_buffer; - LPBYTE data = small_buffer; - UINT size; + switch (eventid) + { + // handle raw input data + case INPUT_EVENT_RAWINPUT: + { + // ignore if not enabled + if (!input_enabled()) + return false; + + HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata); + + BYTE small_buffer[4096]; + std::unique_ptr<BYTE []> larger_buffer; + LPBYTE data = small_buffer; + UINT size; + + // determine the size of data buffer we need + if (GetRawInputData(rawinputdevice, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER)) != 0) + return false; + + // if necessary, allocate a temporary buffer and fetch the data + if (size > sizeof(small_buffer)) + { + larger_buffer.reset(new (std::nothrow) BYTE [size]); + data = larger_buffer.get(); + if (!data) + return false; + } + + // fetch the data and process the appropriate message types + UINT result = GetRawInputData(rawinputdevice, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER)); + if (UINT(-1) == result) + { + return false; + } + else if (result) + { + std::lock_guard<std::mutex> scope_lock(m_module_lock); + + auto *input = reinterpret_cast<RAWINPUT *>(data); + if (!input->header.hDevice) + return false; + + // find the device in the list and update + auto target_device = std::find_if( + devicelist().begin(), + devicelist().end(), + [input] (auto const &device) + { + auto devinfo = dynamic_cast<rawinput_device *>(device.get()); + return devinfo && (input->header.hDevice == devinfo->device_handle()); + }); + if (devicelist().end() == target_device) + return false; + + static_cast<rawinput_device *>(target_device->get())->queue_events(input, 1); + return true; + } + } + break; - // ignore if not enabled - if (!input_enabled()) - return false; + case INPUT_EVENT_ARRIVAL: + { + HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata); + + // determine the length of the device name, allocate it, and fetch it if not nameless + UINT name_length = 0; + if (GetRawInputDeviceInfoW(rawinputdevice, RIDI_DEVICENAME, nullptr, &name_length) != 0) + return false; + + std::unique_ptr<WCHAR []> tname = std::make_unique<WCHAR []>(name_length + 1); + if (name_length > 1 && GetRawInputDeviceInfoW(rawinputdevice, RIDI_DEVICENAME, tname.get(), &name_length) == UINT(-1)) + return false; + std::string utf8_id = osd::text::from_wstring(tname.get()); + tname.reset(); + + std::lock_guard<std::mutex> scope_lock(m_module_lock); + + // find the device in the list and update + auto target_device = std::find_if( + devicelist().begin(), + devicelist().end(), + [&utf8_id] (auto const &device) + { + auto devinfo = dynamic_cast<rawinput_device *>(device.get()); + return devinfo && !devinfo->device_handle() && (devinfo->id() == utf8_id); + }); + if (devicelist().end() == target_device) + return false; - // determine the size of databuffer we need - if ((*get_rawinput_data)(rawinputdevice, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER)) != 0) - return false; + static_cast<rawinput_device *>(target_device->get())->set_handle(rawinputdevice); + return true; + } + break; - // if necessary, allocate a temporary buffer and fetch the data - if (size > sizeof(small_buffer)) - { - larger_buffer = std::make_unique<BYTE[]>(size); - data = larger_buffer.get(); - if (data == nullptr) - return false; - } + case INPUT_EVENT_REMOVAL: + { + HRAWINPUT rawinputdevice = *static_cast<HRAWINPUT *>(eventdata); - // fetch the data and process the appropriate message types - bool result = (*get_rawinput_data)(static_cast<HRAWINPUT>(rawinputdevice), RID_INPUT, data, &size, sizeof(RAWINPUTHEADER)); - if (result) - { - std::lock_guard<std::mutex> scope_lock(m_module_lock); + std::lock_guard<std::mutex> scope_lock(m_module_lock); - auto *input = reinterpret_cast<RAWINPUT*>(data); + // find the device in the list and update + auto target_device = std::find_if( + devicelist().begin(), + devicelist().end(), + [rawinputdevice] (auto const &device) + { + auto devinfo = dynamic_cast<rawinput_device *>(device.get()); + return devinfo && (rawinputdevice == devinfo->device_handle()); + }); - // find the device in the list and update - auto target_device = std::find_if( - devicelist()->begin(), - devicelist()->end(), - [input] (auto const &device) - { - auto devinfo = dynamic_cast<rawinput_device *>(device.get()); - return devinfo && (input->header.hDevice == devinfo->device_handle()); - }); + if (devicelist().end() == target_device) + return false; - if (target_device != devicelist()->end()) - { - static_cast<rawinput_device *>((*target_device).get())->queue_events(input, 1); + (*target_device)->reset(); + static_cast<rawinput_device *>(target_device->get())->set_handle(nullptr); return true; } + break; + + default: + break; } + // must have been unhandled return false; } }; @@ -633,10 +694,10 @@ protected: USHORT usagepage() override { return 1; } USHORT usage() override { return 6; } - void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override + void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override { // make sure this is a keyboard - if (device->dwType != RIM_TYPEKEYBOARD) + if (device.dwType != RIM_TYPEKEYBOARD) return; // allocate and link in a new device @@ -679,10 +740,10 @@ protected: USHORT usagepage() override { return 1; } USHORT usage() override { return 2; } - void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override + void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override { // make sure this is a mouse - if (device->dwType != RIM_TYPEMOUSE) + if (device.dwType != RIM_TYPEMOUSE) return; // allocate and link in a new device @@ -728,11 +789,11 @@ protected: USHORT usagepage() override { return 1; } USHORT usage() override { return 2; } - void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override + void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST const &device) override { // make sure this is a mouse - if (device->dwType != RIM_TYPEMOUSE) + if (device.dwType != RIM_TYPEMOUSE) return; // allocate and link in a new device diff --git a/src/osd/modules/input/input_sdl.cpp b/src/osd/modules/input/input_sdl.cpp index 58901627bcf..8937e4cb2a6 100644 --- a/src/osd/modules/input/input_sdl.cpp +++ b/src/osd/modules/input/input_sdl.cpp @@ -20,12 +20,13 @@ #include <SDL2/SDL.h> #include <cctype> // ReSharper disable once CppUnusedIncludeDirective +#include <algorithm> #include <cstddef> -#include <mutex> +#include <iterator> #include <memory> +#include <mutex> +#include <optional> #include <queue> -#include <iterator> -#include <algorithm> // MAME headers #include "emu.h" @@ -373,6 +374,14 @@ protected: class sdl_keyboard_device : public sdl_device { public: + // state information for a keyboard + struct keyboard_state + { + int32_t state[0x3ff]; // must be int32_t! + int8_t oldkey[MAX_KEYS]; + int8_t currkey[MAX_KEYS]; + }; + keyboard_state keyboard; sdl_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : @@ -483,6 +492,13 @@ private: int last_y; public: + // state information for a mouse + struct mouse_state + { + int32_t lX, lY; + int32_t buttons[MAX_BUTTONS]; + }; + mouse_state mouse; sdl_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : @@ -602,40 +618,40 @@ public: // sdl_joystick_device //============================================================ -// state information for a joystick -struct sdl_joystick_state -{ - int32_t axes[MAX_AXES]; - int32_t buttons[MAX_BUTTONS]; - int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; - int32_t balls[MAX_AXES]; -}; - -struct sdl_api_state -{ - SDL_Joystick *device; - SDL_Haptic *hapdevice; - SDL_JoystickID joystick_id; -}; - class sdl_joystick_device : public sdl_device { public: + // state information for a joystick + struct sdl_joystick_state + { + int32_t axes[MAX_AXES]; + int32_t buttons[MAX_BUTTONS]; + int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; + int32_t balls[MAX_AXES]; + }; + + struct sdl_api_state + { + SDL_Joystick *device = nullptr; + SDL_Haptic *hapdevice = nullptr; + SDL_JoystickID joystick_id; + std::optional<std::string> serial; + }; + sdl_joystick_state joystick; sdl_api_state sdl_state; sdl_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : sdl_device(machine, std::move(name), std::move(id), DEVICE_CLASS_JOYSTICK, module), - joystick({{0}}), - sdl_state({ nullptr }) + joystick({{0}}) { } ~sdl_joystick_device() { - if (sdl_state.device != nullptr) + if (sdl_state.device) { - if (sdl_state.hapdevice != nullptr) + if (sdl_state.hapdevice) { SDL_HapticClose(sdl_state.hapdevice); sdl_state.hapdevice = nullptr; @@ -665,38 +681,10 @@ public: break; case SDL_JOYHATMOTION: - if (sdlevent.jhat.value & SDL_HAT_UP) - { - joystick.hatsU[sdlevent.jhat.hat] = 0x80; - } - else - { - joystick.hatsU[sdlevent.jhat.hat] = 0; - } - if (sdlevent.jhat.value & SDL_HAT_DOWN) - { - joystick.hatsD[sdlevent.jhat.hat] = 0x80; - } - else - { - joystick.hatsD[sdlevent.jhat.hat] = 0; - } - if (sdlevent.jhat.value & SDL_HAT_LEFT) - { - joystick.hatsL[sdlevent.jhat.hat] = 0x80; - } - else - { - joystick.hatsL[sdlevent.jhat.hat] = 0; - } - if (sdlevent.jhat.value & SDL_HAT_RIGHT) - { - joystick.hatsR[sdlevent.jhat.hat] = 0x80; - } - else - { - joystick.hatsR[sdlevent.jhat.hat] = 0; - } + joystick.hatsU[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_UP) ? 0x80 : 0; + joystick.hatsD[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_DOWN) ? 0x80 : 0; + joystick.hatsL[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_LEFT) ? 0x80 : 0; + joystick.hatsR[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_RIGHT) ? 0x80 : 0; break; case SDL_JOYBUTTONDOWN: @@ -704,6 +692,21 @@ public: if (sdlevent.jbutton.button < MAX_BUTTONS) joystick.buttons[sdlevent.jbutton.button] = (sdlevent.jbutton.state == SDL_PRESSED) ? 0x80 : 0; break; + + case SDL_JOYDEVICEREMOVED: + osd_printf_verbose("Joystick: %s [GUID %s] disconnected\n", name(), id()); + reset(); + if (sdl_state.device) + { + if (sdl_state.hapdevice) + { + SDL_HapticClose(sdl_state.hapdevice); + sdl_state.hapdevice = nullptr; + } + SDL_JoystickClose(sdl_state.device); + sdl_state.device = nullptr; + } + break; } } }; @@ -786,9 +789,10 @@ public: void handle_event(SDL_Event &sdlevent) override { // By default dispatch event to every device - devicelist()->for_each_device([&sdlevent](auto device) { - downcast<sdl_device*>(device)->queue_events(&sdlevent, 1); - }); + devicelist().for_each_device( + [&sdlevent](auto device) { + downcast<sdl_device*>(device)->queue_events(&sdlevent, 1); + }); } }; @@ -810,13 +814,12 @@ public: { sdl_input_module::input_init(machine); - static int event_types[] = { - static_cast<int>(SDL_KEYDOWN), - static_cast<int>(SDL_KEYUP), - static_cast<int>(SDL_TEXTINPUT) - }; + static int const event_types[] = { + int(SDL_KEYDOWN), + int(SDL_KEYUP), + int(SDL_TEXTINPUT) }; - sdl_event_manager::instance().subscribe(event_types, std::size(event_types), this); + sdl_event_manager::instance().subscribe(event_types, this); // Read our keymap and store a pointer to our table m_key_trans_table = sdlinput_read_keymap(machine); @@ -826,7 +829,7 @@ public: osd_printf_verbose("Keyboard: Start initialization\n"); // SDL only has 1 keyboard add it now - auto &devinfo = devicelist()->create_device<sdl_keyboard_device>(machine, "System keyboard", "System keyboard", *this); + auto &devinfo = devicelist().create_device<sdl_keyboard_device>(machine, "System keyboard", "System keyboard", *this); // populate it for (int keynum = 0; local_table[keynum].mame_key != ITEM_ID_INVALID; keynum++) @@ -942,19 +945,18 @@ public: { sdl_input_module::input_init(machine); - static int event_types[] = { - static_cast<int>(SDL_MOUSEMOTION), - static_cast<int>(SDL_MOUSEBUTTONDOWN), - static_cast<int>(SDL_MOUSEBUTTONUP), - static_cast<int>(SDL_MOUSEWHEEL) - }; + static int const event_types[] = { + int(SDL_MOUSEMOTION), + int(SDL_MOUSEBUTTONDOWN), + int(SDL_MOUSEBUTTONUP), + int(SDL_MOUSEWHEEL) }; - sdl_event_manager::instance().subscribe(event_types, std::size(event_types), this); + sdl_event_manager::instance().subscribe(event_types, this); osd_printf_verbose("Mouse: Start initialization\n"); // SDL currently only supports one mouse - auto &devinfo = devicelist()->create_device<sdl_mouse_device>(machine, "System mouse", "System mouse", *this); + auto &devinfo = devicelist().create_device<sdl_mouse_device>(machine, "System mouse", "System mouse", *this); // add the axes devinfo.device()->add_item("X", ITEM_ID_XAXIS, generic_axis_get_state<std::int32_t>, &devinfo.mouse.lX); @@ -981,12 +983,15 @@ void devmap_register(device_map_t &devmap, int physical_idx, const std::string & auto entry = std::find_if( std::begin(devmap.map), std::end(devmap.map), - [&name] (auto &item) { return (item.name == name) && (item.physical < 0); }); + [&name] (auto const &item) { return (item.name == name) && (item.physical < 0); }); // If we didn't find it by name, find the first free slot if (entry == std::end(devmap.map)) { - entry = std::find_if(std::begin(devmap.map), std::end(devmap.map), [] (auto &item) { return item.name.empty(); }); + entry = std::find_if( + std::begin(devmap.map), + std::end(devmap.map), + [] (auto const &item) { return item.name.empty(); }); } if (entry != std::end(devmap.map)) @@ -1054,13 +1059,12 @@ public: char tempname[512]; - m_sixaxis_mode = downcast<const sdl_options*>(options())->sixaxis(); + m_sixaxis_mode = downcast<const sdl_options *>(options())->sixaxis(); devmap_init(machine, &m_joy_map, SDLOPTION_JOYINDEX, 8, "Joystick mapping"); osd_printf_verbose("Joystick: Start initialization\n"); - int physical_stick; - for (physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++) + for (int physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++) { std::string joy_name = remove_spaces(SDL_JoystickNameForIndex(physical_stick)); devmap_register(m_joy_map, physical_stick, joy_name); @@ -1073,28 +1077,40 @@ public: if (!devinfo) continue; - physical_stick = m_joy_map.map[stick].physical; - SDL_Joystick *joy = SDL_JoystickOpen(physical_stick); + int const physical_stick = m_joy_map.map[stick].physical; + SDL_Joystick *const joy = SDL_JoystickOpen(physical_stick); SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy); char guid_str[256]; guid_str[0] = '\0'; - SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)-1); + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1); devinfo->sdl_state.device = joy; devinfo->sdl_state.joystick_id = SDL_JoystickInstanceID(joy); devinfo->sdl_state.hapdevice = SDL_HapticOpenFromJoystick(joy); - - osd_printf_verbose("Joystick: %s [GUID %s]\n", SDL_JoystickNameForIndex(physical_stick), guid_str); - osd_printf_verbose("Joystick: ... %d axes, %d buttons %d hats %d balls\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy), SDL_JoystickNumBalls(joy)); +#if SDL_VERSION_ATLEAST(2, 0, 14) + char const *const serial = SDL_JoystickGetSerial(joy); + if (serial) + devinfo->sdl_state.serial = serial; + else +#endif // SDL_VERSION_ATLEAST(2, 0, 14) + devinfo->sdl_state.serial = std::nullopt; + + osd_printf_verbose("Joystick: %s [GUID %s] Vendor ID %04X, Product ID %04X, Revision %04X\n", + SDL_JoystickNameForIndex(physical_stick), + guid_str, + SDL_JoystickGetVendor(joy), + SDL_JoystickGetProduct(joy), + SDL_JoystickGetProductVersion(joy)); + osd_printf_verbose("Joystick: ... %d axes, %d buttons %d hats %d balls\n", + SDL_JoystickNumAxes(joy), + SDL_JoystickNumButtons(joy), + SDL_JoystickNumHats(joy), + SDL_JoystickNumBalls(joy)); osd_printf_verbose("Joystick: ... Physical id %d mapped to logical id %d\n", physical_stick, stick + 1); - if (devinfo->sdl_state.hapdevice != nullptr) - { + if (devinfo->sdl_state.hapdevice) osd_printf_verbose("Joystick: ... Has haptic capability\n"); - } else - { osd_printf_verbose("Joystick: ... Does not have haptic capability\n"); - } // loop over all axes for (int axis = 0; axis < SDL_JoystickNumAxes(joy); axis++) @@ -1108,7 +1124,7 @@ public: else itemid = ITEM_ID_OTHER_AXIS_ABSOLUTE; - snprintf(tempname, sizeof(tempname), "A%d %s", axis, devinfo->name().c_str()); + snprintf(tempname, sizeof(tempname), "A%d", axis + 1); devinfo->device()->add_item(tempname, itemid, generic_axis_get_state<std::int32_t>, &devinfo->joystick.axes[axis]); } @@ -1128,7 +1144,7 @@ public: else itemid = ITEM_ID_OTHER_SWITCH; - snprintf(tempname, sizeof(tempname), "button %d", button); + snprintf(tempname, sizeof(tempname), "Button %d", button + 1); devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.buttons[button]); } @@ -1137,16 +1153,16 @@ public: { input_item_id itemid; - snprintf(tempname, sizeof(tempname), "hat %d Up", hat); + snprintf(tempname, sizeof(tempname), "Hat %d Up", hat + 1); itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1UP + 4 * hat : ITEM_ID_OTHER_SWITCH); devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsU[hat]); - snprintf(tempname, sizeof(tempname), "hat %d Down", hat); + snprintf(tempname, sizeof(tempname), "Hat %d Down", hat + 1); itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1DOWN + 4 * hat : ITEM_ID_OTHER_SWITCH); devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsD[hat]); - snprintf(tempname, sizeof(tempname), "hat %d Left", hat); + snprintf(tempname, sizeof(tempname), "Hat %d Left", hat + 1); itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1LEFT + 4 * hat : ITEM_ID_OTHER_SWITCH); devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsL[hat]); - snprintf(tempname, sizeof(tempname), "hat %d Right", hat); + snprintf(tempname, sizeof(tempname), "Hat %d Right", hat + 1); itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1RIGHT + 4 * hat : ITEM_ID_OTHER_SWITCH); devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsR[hat]); } @@ -1161,46 +1177,90 @@ public: else itemid = ITEM_ID_OTHER_AXIS_RELATIVE; - snprintf(tempname, sizeof(tempname), "R%d %s", ball * 2, devinfo->name().c_str()); + snprintf(tempname, sizeof(tempname), "R%d X", ball + 1); devinfo->device()->add_item(tempname, (input_item_id)itemid, generic_axis_get_state<std::int32_t>, &devinfo->joystick.balls[ball * 2]); - snprintf(tempname, sizeof(tempname), "R%d %s", ball * 2 + 1, devinfo->name().c_str()); + snprintf(tempname, sizeof(tempname), "R%d Y", ball + 1); devinfo->device()->add_item(tempname, (input_item_id)(itemid + 1), generic_axis_get_state<std::int32_t>, &devinfo->joystick.balls[ball * 2 + 1]); } } - static int event_types[] = { - static_cast<int>(SDL_JOYAXISMOTION), - static_cast<int>(SDL_JOYBALLMOTION), - static_cast<int>(SDL_JOYHATMOTION), - static_cast<int>(SDL_JOYBUTTONDOWN), - static_cast<int>(SDL_JOYBUTTONUP) - }; + static int const event_types[] = { + int(SDL_JOYAXISMOTION), + int(SDL_JOYBALLMOTION), + int(SDL_JOYHATMOTION), + int(SDL_JOYBUTTONDOWN), + int(SDL_JOYBUTTONUP), + int(SDL_JOYDEVICEADDED), + int(SDL_JOYDEVICEREMOVED) }; - sdl_event_manager::instance().subscribe(event_types, std::size(event_types), this); + sdl_event_manager::instance().subscribe(event_types, this); osd_printf_verbose("Joystick: End initialization\n"); } virtual void handle_event(SDL_Event &sdlevent) override { - // Figure out which joystick this event id destined for - auto target_device = std::find_if( - devicelist()->begin(), - devicelist()->end(), - [&sdlevent] (auto &device) + if (SDL_JOYDEVICEADDED == sdlevent.type) + { + SDL_Joystick *const joy = SDL_JoystickOpen(sdlevent.jdevice.which); + if (joy) + { + SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy); + char guid_str[256]; + guid_str[0] = '\0'; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1); + char const *serial = nullptr; +#if SDL_VERSION_ATLEAST(2, 0, 14) + serial = SDL_JoystickGetSerial(joy); +#endif + auto target_device = std::find_if( + devicelist().begin(), + devicelist().end(), + [&guid_str, &serial] (auto const &device) + { + auto &devinfo = downcast<sdl_joystick_device &>(*device); + return + !devinfo.sdl_state.device && + (devinfo.id() == guid_str) && + ((serial && devinfo.sdl_state.serial && (*devinfo.sdl_state.serial == serial)) || (!serial && !devinfo.sdl_state.serial)); + }); + if (devicelist().end() != target_device) { - std::unique_ptr<device_info> &ptr = device; - return downcast<sdl_joystick_device*>(ptr.get())->sdl_state.joystick_id == sdlevent.jdevice.which; - }); - - // If we find a matching joystick, dispatch the event to the joystick - if (target_device != devicelist()->end()) + auto &devinfo = downcast<sdl_joystick_device &>(**target_device); + devinfo.sdl_state.device = joy; + devinfo.sdl_state.joystick_id = SDL_JoystickInstanceID(joy); + devinfo.sdl_state.hapdevice = SDL_HapticOpenFromJoystick(joy); + osd_printf_verbose("Joystick: %s [GUID %s] reconnected\n", devinfo.name(), guid_str); + } + else + { + SDL_JoystickClose(joy); + } + } + } + else { - downcast<sdl_joystick_device*>((*target_device).get())->queue_events(&sdlevent, 1); + // Figure out which joystick this event id destined for + sdl_joystick_device *const target_device = find_joystick(sdlevent.jdevice.which); // FIXME: this depends on SDL_JoystickID being the same size as Sint32 + + // If we find a matching joystick, dispatch the event to the joystick + if (target_device) + target_device->queue_events(&sdlevent, 1); } } private: + sdl_joystick_device *find_joystick(SDL_JoystickID instance) + { + for (auto &ptr : devicelist()) + { + sdl_joystick_device *const device = downcast<sdl_joystick_device *>(ptr.get()); + if (device->sdl_state.device && (device->sdl_state.joystick_id == instance)) + return device; + } + return nullptr; + } + sdl_joystick_device *create_joystick_device(running_machine &machine, device_map_t *devmap, int index, input_device_class devclass) { char tempname[20]; @@ -1215,16 +1275,16 @@ private: { snprintf(tempname, std::size(tempname), "NC%d", index); m_sixaxis_mode - ? devicelist()->create_device<sdl_sixaxis_joystick_device>(machine, tempname, guid_str, *this) - : devicelist()->create_device<sdl_joystick_device>(machine, tempname, guid_str, *this); + ? devicelist().create_device<sdl_sixaxis_joystick_device>(machine, tempname, guid_str, *this) + : devicelist().create_device<sdl_joystick_device>(machine, tempname, guid_str, *this); } return nullptr; } return m_sixaxis_mode - ? &devicelist()->create_device<sdl_sixaxis_joystick_device>(machine, std::string(devmap->map[index].name), guid_str, *this) - : &devicelist()->create_device<sdl_joystick_device>(machine, std::string(devmap->map[index].name), guid_str, *this); + ? &devicelist().create_device<sdl_sixaxis_joystick_device>(machine, std::string(devmap->map[index].name), guid_str, *this) + : &devicelist().create_device<sdl_joystick_device>(machine, std::string(devmap->map[index].name), guid_str, *this); } }; diff --git a/src/osd/modules/input/input_sdlcommon.cpp b/src/osd/modules/input/input_sdlcommon.cpp index 92e3653e4d1..1f84e28f2f6 100644 --- a/src/osd/modules/input/input_sdlcommon.cpp +++ b/src/osd/modules/input/input_sdlcommon.cpp @@ -267,7 +267,7 @@ void sdl_osd_interface::release_keys() { auto keybd = dynamic_cast<input_module_base*>(m_keyboard_input); if (keybd != nullptr) - keybd->devicelist()->reset_devices(); + keybd->devicelist().reset_devices(); } bool sdl_osd_interface::should_hide_mouse() diff --git a/src/osd/modules/input/input_sdlcommon.h b/src/osd/modules/input/input_sdlcommon.h index 030a8ca4bd7..74b12a875ba 100644 --- a/src/osd/modules/input/input_sdlcommon.h +++ b/src/osd/modules/input/input_sdlcommon.h @@ -8,40 +8,17 @@ // //============================================================ -#ifndef INPUT_SDLCOMMON_H_ -#define INPUT_SDLCOMMON_H_ +#ifndef MAME_OSD_INPUT_INPUT_SDLCOMMON_H +#define MAME_OSD_INPUT_INPUT_SDLCOMMON_H + +#pragma once -#include <unordered_map> #include <algorithm> +#include <unordered_map> #define MAX_DEVMAP_ENTRIES 16 #define SDL_MODULE_EVENT_BUFFER_SIZE 5 -// state information for a keyboard -struct keyboard_state -{ - int32_t state[0x3ff]; // must be int32_t! - int8_t oldkey[MAX_KEYS]; - int8_t currkey[MAX_KEYS]; -}; - -// state information for a mouse -struct mouse_state -{ - int32_t lX, lY; - int32_t buttons[MAX_BUTTONS]; -}; - - -// state information for a joystick; DirectInput state must be first element -struct joystick_state -{ - SDL_Joystick *device; - int32_t axes[MAX_AXES]; - int32_t buttons[MAX_BUTTONS]; - int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; - int32_t balls[MAX_AXES]; -}; struct device_map_t { @@ -79,15 +56,14 @@ public: { } - void subscribe(int* event_types, int num_event_types, TSubscriber *subscriber) + template <size_t N> + void subscribe(int const (&event_types)[N], TSubscriber *subscriber) { std::lock_guard<std::mutex> scope_lock(m_lock); // Add the subscription - for (int i = 0; i < num_event_types; i++) - { - m_subscription_index.emplace(event_types[i], subscriber); - } + for (int i : event_types) + m_subscription_index.emplace(i, subscriber); } void unsubscribe(TSubscriber *subscriber) @@ -199,4 +175,4 @@ static inline void devmap_init(running_machine &machine, device_map_t *devmap, c } } -#endif +#endif // MAME_OSD_INPUT_INPUT_SDLCOMMON_H diff --git a/src/osd/modules/input/input_win32.cpp b/src/osd/modules/input/input_win32.cpp index ff154140f7f..a02b2ee426e 100644 --- a/src/osd/modules/input/input_win32.cpp +++ b/src/osd/modules/input/input_win32.cpp @@ -74,7 +74,7 @@ public: virtual void input_init(running_machine &machine) override { // Add a single win32 keyboard device that we'll monitor using Win32 - auto &devinfo = devicelist()->create_device<win32_keyboard_device>(machine, "Win32 Keyboard 1", "Win32 Keyboard 1", *this); + auto &devinfo = devicelist().create_device<win32_keyboard_device>(machine, "Win32 Keyboard 1", "Win32 Keyboard 1", *this); keyboard_trans_table &table = keyboard_trans_table::instance(); @@ -106,7 +106,7 @@ public: case INPUT_EVENT_KEYDOWN: case INPUT_EVENT_KEYUP: args = static_cast<KeyPressEventArgs*>(eventdata); - devicelist()->for_each_device([args](auto device) + devicelist().for_each_device([args](auto device) { auto keyboard = dynamic_cast<win32_keyboard_device*>(device); if (keyboard != nullptr) @@ -206,7 +206,7 @@ public: return; // allocate a device - auto &devinfo = devicelist()->create_device<win32_mouse_device>(machine, "Win32 Mouse 1", "Win32 Mouse 1", *this); + auto &devinfo = devicelist().create_device<win32_mouse_device>(machine, "Win32 Mouse 1", "Win32 Mouse 1", *this); // populate the axes for (int axisnum = 0; axisnum < 2; axisnum++) @@ -235,7 +235,7 @@ public: return false; auto args = static_cast<MouseButtonEventArgs*>(eventdata); - devicelist()->for_each_device([args](auto device) + devicelist().for_each_device([args](auto device) { auto mouse = dynamic_cast<win32_mouse_device*>(device); if (mouse != nullptr) @@ -268,7 +268,7 @@ public: m_lightgun_shared_axis_mode = downcast<windows_options &>(machine.options()).dual_lightgun(); // Since we are about to be added to the list, the current size is the zero-based index of where we will be - m_gun_index = downcast<wininput_module&>(module).devicelist()->size(); + m_gun_index = downcast<wininput_module&>(module).devicelist().size(); } void poll() override @@ -391,7 +391,7 @@ public: static const char *const gun_names[] = { "Win32 Gun 1", "Win32 Gun 2" }; // allocate a device - auto &devinfo = devicelist()->create_device<win32_lightgun_device>(machine, gun_names[gunnum], gun_names[gunnum], *this); + auto &devinfo = devicelist().create_device<win32_lightgun_device>(machine, gun_names[gunnum], gun_names[gunnum], *this); // populate the axes for (int axisnum = 0; axisnum < 2; axisnum++) @@ -421,7 +421,7 @@ public: return false; auto args = static_cast<MouseButtonEventArgs*>(eventdata); - devicelist()->for_each_device([args](auto device) + devicelist().for_each_device([args](auto device) { auto lightgun = dynamic_cast<win32_lightgun_device*>(device); if (lightgun != nullptr) diff --git a/src/osd/modules/input/input_windows.cpp b/src/osd/modules/input/input_windows.cpp index bbe109eb53a..4415e71f3a4 100644 --- a/src/osd/modules/input/input_windows.cpp +++ b/src/osd/modules/input/input_windows.cpp @@ -27,39 +27,39 @@ bool windows_osd_interface::should_hide_mouse() const { bool hidemouse = false; - wininput_module* mod; + wininput_module *mod; - mod = dynamic_cast<wininput_module*>(m_keyboard_input); + mod = dynamic_cast<wininput_module *>(m_keyboard_input); if (mod) hidemouse |= mod->should_hide_mouse(); - mod = dynamic_cast<wininput_module*>(m_mouse_input); + mod = dynamic_cast<wininput_module *>(m_mouse_input); if (mod) hidemouse |= mod->should_hide_mouse(); - mod = dynamic_cast<wininput_module*>(m_lightgun_input); + mod = dynamic_cast<wininput_module *>(m_lightgun_input); if (mod) hidemouse |= mod->should_hide_mouse(); - mod = dynamic_cast<wininput_module*>(m_joystick_input); + mod = dynamic_cast<wininput_module *>(m_joystick_input); if (mod) hidemouse |= mod->should_hide_mouse(); return hidemouse; } -bool windows_osd_interface::handle_input_event(input_event eventid, void* eventdata) const +bool windows_osd_interface::handle_input_event(input_event eventid, void *eventdata) const { bool handled = false; - wininput_module* mod; + wininput_module *mod; - mod = dynamic_cast<wininput_module*>(m_keyboard_input); + mod = dynamic_cast<wininput_module *>(m_keyboard_input); if (mod) handled |= mod->handle_input_event(eventid, eventdata); - mod = dynamic_cast<wininput_module*>(m_mouse_input); + mod = dynamic_cast<wininput_module *>(m_mouse_input); if (mod) handled |= mod->handle_input_event(eventid, eventdata); - mod = dynamic_cast<wininput_module*>(m_lightgun_input); + mod = dynamic_cast<wininput_module *>(m_lightgun_input); if (mod) handled |= mod->handle_input_event(eventid, eventdata); - mod = dynamic_cast<wininput_module*>(m_joystick_input); + mod = dynamic_cast<wininput_module *>(m_joystick_input); if (mod) handled |= mod->handle_input_event(eventid, eventdata); return handled; diff --git a/src/osd/modules/input/input_x11.cpp b/src/osd/modules/input/input_x11.cpp index e7481d6470e..0657e99fd2d 100644 --- a/src/osd/modules/input/input_x11.cpp +++ b/src/osd/modules/input/input_x11.cpp @@ -538,9 +538,9 @@ public: osd_printf_verbose("Device %i: Registered %i events.\n", static_cast<int>(info->id), events_registered); // register ourself to handle events from event manager - int event_types[] = { motion_type, button_press_type, button_release_type }; + int const event_types[] = { motion_type, button_press_type, button_release_type }; osd_printf_verbose("Events types to register: motion:%d, press:%d, release:%d\n", motion_type, button_press_type, button_release_type); - x11_event_manager::instance().subscribe(event_types, std::size(event_types), this); + x11_event_manager::instance().subscribe(event_types, this); } osd_printf_verbose("Lightgun: End initialization\n"); @@ -582,14 +582,14 @@ public: } // Figure out which lightgun this event id destined for - auto target_device = std::find_if(devicelist()->begin(), devicelist()->end(), [deviceid](auto &device) + auto target_device = std::find_if(devicelist().begin(), devicelist().end(), [deviceid](auto &device) { std::unique_ptr<device_info> &ptr = device; return downcast<x11_input_device*>(ptr.get())->x11_state.deviceid == deviceid; }); // If we find a matching lightgun, dispatch the event to the lightgun - if (target_device != devicelist()->end()) + if (target_device != devicelist().end()) { downcast<x11_input_device*>((*target_device).get())->queue_events(&xevent, 1); } @@ -604,7 +604,7 @@ private: { char tempname[20]; snprintf(tempname, std::size(tempname), "NC%d", index); - return &devicelist()->create_device<x11_lightgun_device>(machine, tempname, tempname, *this); + return &devicelist().create_device<x11_lightgun_device>(machine, tempname, tempname, *this); } else { @@ -612,7 +612,7 @@ private: } } - return &devicelist()->create_device<x11_lightgun_device>(machine, std::string(m_lightgun_map.map[index].name), std::string(m_lightgun_map.map[index].name), *this); + return &devicelist().create_device<x11_lightgun_device>(machine, std::string(m_lightgun_map.map[index].name), std::string(m_lightgun_map.map[index].name), *this); } void add_lightgun_buttons(XAnyClassPtr first_info_class, int num_classes, x11_lightgun_device &devinfo) const diff --git a/src/osd/modules/input/input_xinput.cpp b/src/osd/modules/input/input_xinput.cpp index dd4c418aacd..152e16b4e81 100644 --- a/src/osd/modules/input/input_xinput.cpp +++ b/src/osd/modules/input/input_xinput.cpp @@ -186,7 +186,7 @@ xinput_joystick_device * xinput_api_helper::create_xinput_device(running_machine snprintf(device_name, sizeof(device_name), "XInput Player %u", index + 1); // allocate the device object - auto &devinfo = module.devicelist()->create_device<xinput_joystick_device>(machine, device_name, device_name, module, shared_from_this()); + auto &devinfo = module.devicelist().create_device<xinput_joystick_device>(machine, device_name, device_name, module, shared_from_this()); // Set the player ID devinfo.xinput_state.player_index = index; @@ -201,12 +201,12 @@ xinput_joystick_device * xinput_api_helper::create_xinput_device(running_machine // xinput_joystick_device //============================================================ -xinput_joystick_device::xinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, std::shared_ptr<xinput_api_helper> helper) - : device_info(machine, std::string(name), std::string(id), DEVICE_CLASS_JOYSTICK, module), - gamepad({{0}}), - xinput_state({0}), - m_xinput_helper(helper), - m_configured(false) +xinput_joystick_device::xinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, std::shared_ptr<xinput_api_helper> helper) : + device_info(machine, std::string(name), std::string(id), DEVICE_CLASS_JOYSTICK, module), + gamepad({ { 0 } }), + xinput_state({ 0 }), + m_xinput_helper(helper), + m_configured(false) { } diff --git a/src/osd/modules/lib/osdlib.h b/src/osd/modules/lib/osdlib.h index 4a06b7052f5..8ca4762a111 100644 --- a/src/osd/modules/lib/osdlib.h +++ b/src/osd/modules/lib/osdlib.h @@ -163,7 +163,7 @@ public: static ptr open(std::vector<std::string> &&libraries); - virtual ~dynamic_module() { }; + virtual ~dynamic_module() { } template <typename T> typename std::enable_if_t<std::is_pointer_v<T>, T> bind(char const *symbol) diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index be06da29767..52ddca76ca0 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -159,7 +159,7 @@ const options_entry osd_options::s_option_entries[] = { OSDOPTION_BGFX_DEBUG, "0", OPTION_BOOLEAN, "enable BGFX debugging statistics" }, { OSDOPTION_BGFX_SCREEN_CHAINS, "default", OPTION_STRING, "comma-delimited list of screen chain JSON names, colon-delimited per-window" }, { OSDOPTION_BGFX_SHADOW_MASK, "slot-mask.png", OPTION_STRING, "shadow mask texture name" }, - { OSDOPTION_BGFX_LUT, "", OPTION_STRING, "LUT texture name" }, + { OSDOPTION_BGFX_LUT, "lut-default.png", OPTION_STRING, "LUT texture name" }, { OSDOPTION_BGFX_AVI_NAME, OSDOPTVAL_AUTO, OPTION_STRING, "filename for BGFX output logging" }, // End of list diff --git a/src/osd/modules/osdhelper.h b/src/osd/modules/osdhelper.h index 093c392e249..85cbfc906c1 100644 --- a/src/osd/modules/osdhelper.h +++ b/src/osd/modules/osdhelper.h @@ -20,8 +20,8 @@ public: constexpr int width() const { return m_w; } constexpr int height() const { return m_h; } - constexpr bool operator!=(const osd_dim &other) { return (m_w != other.width()) || (m_h != other.height()); } - constexpr bool operator==(const osd_dim &other) { return (m_w == other.width()) && (m_h == other.height()); } + constexpr bool operator!=(const osd_dim &other) const { return (m_w != other.width()) || (m_h != other.height()); } + constexpr bool operator==(const osd_dim &other) const { return (m_w == other.width()) && (m_h == other.height()); } private: int m_w; diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h index 730e8a67894..9cd05c29d17 100644 --- a/src/osd/modules/osdwindow.h +++ b/src/osd/modules/osdwindow.h @@ -225,10 +225,10 @@ public: virtual void add_audio_to_recording(const int16_t *buffer, int samples_this_frame) { } virtual std::vector<ui::menu_item> get_slider_list() { return m_sliders; } virtual int draw(const int update) = 0; - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) { return 0; }; - virtual void save() { }; - virtual void record() { }; - virtual void toggle_fsfx() { }; + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) { return 0; } + virtual void save() { } + virtual void record() { } + virtual void toggle_fsfx() { } virtual bool sliders_dirty() { return m_sliders_dirty; } static std::unique_ptr<osd_renderer> make_for_type(int mode, std::shared_ptr<osd_window> window, int extra_flags = FLAG_NONE); diff --git a/src/osd/modules/output/output_module.h b/src/osd/modules/output/output_module.h index 9046fda3252..36194e356ea 100644 --- a/src/osd/modules/output/output_module.h +++ b/src/osd/modules/output/output_module.h @@ -29,7 +29,7 @@ public: virtual void notify(const char *outname, int32_t value) = 0; - void set_machine(running_machine *machine) { m_machine = machine; }; + void set_machine(running_machine *machine) { m_machine = machine; } running_machine &machine() const { return *m_machine; } private: running_machine *m_machine; diff --git a/src/osd/modules/render/aviwrite.cpp b/src/osd/modules/render/aviwrite.cpp index ec6ce21c543..9148244111b 100644 --- a/src/osd/modules/render/aviwrite.cpp +++ b/src/osd/modules/render/aviwrite.cpp @@ -10,6 +10,7 @@ #include "aviwrite.h" #include "modules/lib/osdobj_common.h" +#include "fileio.h" #include "screen.h" diff --git a/src/osd/modules/render/bgfx/chainentryreader.cpp b/src/osd/modules/render/bgfx/chainentryreader.cpp index ba3ae1c9e67..5ac97fd1d45 100644 --- a/src/osd/modules/render/bgfx/chainentryreader.cpp +++ b/src/osd/modules/render/bgfx/chainentryreader.cpp @@ -9,6 +9,7 @@ #include <string> #include "emu.h" +#include "fileio.h" #include "rendutil.h" #include <modules/render/copyutil.h> @@ -34,11 +35,11 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s { if (!validate_parameters(value, prefix)) { - printf("Failed validation\n"); + osd_printf_error("Chain entry failed validation.\n"); return nullptr; } - bgfx_effect* effect = chains.effects().effect(value["effect"].GetString()); + bgfx_effect* effect = chains.effects().get_or_load_effect(chains.options(), value["effect"].GetString()); if (effect == nullptr) { return nullptr; diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp index 73128c12a0b..afbb7a99500 100644 --- a/src/osd/modules/render/bgfx/chainmanager.cpp +++ b/src/osd/modules/render/bgfx/chainmanager.cpp @@ -61,11 +61,11 @@ chain_manager::~chain_manager() void chain_manager::init_texture_converters() { m_converters.push_back(nullptr); - m_converters.push_back(m_effects.effect("misc/texconv_palette16")); - m_converters.push_back(m_effects.effect("misc/texconv_rgb32")); + m_converters.push_back(m_effects.get_or_load_effect(m_options, "misc/texconv_palette16")); + m_converters.push_back(m_effects.get_or_load_effect(m_options, "misc/texconv_rgb32")); m_converters.push_back(nullptr); - m_converters.push_back(m_effects.effect("misc/texconv_yuy16")); - m_adjuster = m_effects.effect("misc/bcg_adjust"); + m_converters.push_back(m_effects.get_or_load_effect(m_options, "misc/texconv_yuy16")); + m_adjuster = m_effects.get_or_load_effect(m_options, "misc/bcg_adjust"); } void chain_manager::refresh_available_chains() @@ -468,7 +468,10 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive * if (texture == nullptr) { - bgfx_texture *texture = new bgfx_texture(full_name, dst_format, tex_width, tex_height, mem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, pitch, prim.m_rowpixels, width_div_factor, width_mul_factor); + uint32_t flags = BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT; + if (!PRIMFLAG_GET_TEXWRAP(prim.m_flags)) + flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; + bgfx_texture *texture = new bgfx_texture(full_name, dst_format, tex_width, tex_height, mem, flags, pitch, prim.m_rowpixels, width_div_factor, width_mul_factor); m_textures.add_provider(full_name, texture); if (prim.m_prim->texture.palette) diff --git a/src/osd/modules/render/bgfx/effect.cpp b/src/osd/modules/render/bgfx/effect.cpp index 6707b5cfc43..06fddee66ad 100644 --- a/src/osd/modules/render/bgfx/effect.cpp +++ b/src/osd/modules/render/bgfx/effect.cpp @@ -25,6 +25,7 @@ bgfx_effect::bgfx_effect(uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx: delete uniforms[i]; continue; } + uniforms[i]->create(); m_uniforms[uniforms[i]->name()] = uniforms[i]; } } diff --git a/src/osd/modules/render/bgfx/effect.h b/src/osd/modules/render/bgfx/effect.h index 02ef9fd4f54..ca1be77c73d 100644 --- a/src/osd/modules/render/bgfx/effect.h +++ b/src/osd/modules/render/bgfx/effect.h @@ -26,7 +26,8 @@ public: ~bgfx_effect(); void submit(int view, uint64_t blend = 0L); - bgfx_uniform* uniform(std::string name); + bgfx_uniform *uniform(std::string name); + bool is_valid() { return m_program_handle.idx != bgfx::kInvalidHandle; } private: uint64_t m_state; diff --git a/src/osd/modules/render/bgfx/effectmanager.cpp b/src/osd/modules/render/bgfx/effectmanager.cpp index 6462ae75f72..98bc9a72097 100644 --- a/src/osd/modules/render/bgfx/effectmanager.cpp +++ b/src/osd/modules/render/bgfx/effectmanager.cpp @@ -23,68 +23,79 @@ #include "effectreader.h" #include "effect.h" -using namespace rapidjson; - -effect_manager::~effect_manager() -{ - for (std::pair<std::string, bgfx_effect*> effect : m_effects) - { - delete effect.second; - } - m_effects.clear(); -} - -bgfx_effect* effect_manager::effect(std::string name) -{ - std::map<std::string, bgfx_effect*>::iterator iter = m_effects.find(name); - if (iter != m_effects.end()) - { - return iter->second; - } - - return load_effect(name); -} - -bgfx_effect* effect_manager::load_effect(std::string name) +static bool prepare_effect_document(std::string &name, osd_options &options, rapidjson::Document &document) { std::string full_name = name; - if (full_name.length() < 5 || (full_name.compare(full_name.length() - 5, 5, ".json") != 0)) { + if (full_name.length() < 5 || (full_name.compare(full_name.length() - 5, 5, ".json") != 0)) + { full_name = full_name + ".json"; } + std::string path; - osd_subst_env(path, util::string_format("%s" PATH_SEPARATOR "effects" PATH_SEPARATOR, m_options.bgfx_path())); + osd_subst_env(path, util::string_format("%s" PATH_SEPARATOR "effects" PATH_SEPARATOR, options.bgfx_path())); path += full_name; bx::FileReader reader; if (!bx::open(&reader, path.c_str())) { - printf("Unable to open effect file %s\n", path.c_str()); - return nullptr; + osd_printf_error("Unable to open effect file %s\n", path.c_str()); + return false; } int32_t size (bx::getSize(&reader)); - char* data = new char[size + 1]; bx::read(&reader, reinterpret_cast<void*>(data), size); bx::close(&reader); data[size] = 0; - Document document; - document.Parse<kParseCommentsFlag>(data); + document.Parse<rapidjson::kParseCommentsFlag>(data); delete [] data; - if (document.HasParseError()) { - std::string error(GetParseError_En(document.GetParseError())); - printf("Unable to parse effect %s. Errors returned:\n", path.c_str()); - printf("%s\n", error.c_str()); + if (document.HasParseError()) + { + std::string error(rapidjson::GetParseError_En(document.GetParseError())); + osd_printf_error("Unable to parse effect %s. Errors returned:\n", path.c_str()); + osd_printf_error("%s\n", error.c_str()); + return false; + } + + return true; +} + +effect_manager::~effect_manager() +{ + for (std::pair<std::string, bgfx_effect*> effect : m_effects) + { + delete effect.second; + } + m_effects.clear(); +} + +bgfx_effect* effect_manager::get_or_load_effect(osd_options &options, std::string name) +{ + std::map<std::string, bgfx_effect*>::iterator iter = m_effects.find(name); + if (iter != m_effects.end()) + { + return iter->second; + } + + return load_effect(options, name); +} + +bgfx_effect* effect_manager::load_effect(osd_options &options, std::string name) +{ + rapidjson::Document document; + if (!prepare_effect_document(name, options, document)) + { return nullptr; } - bgfx_effect* effect = effect_reader::read_from_value(document, "Effect '" + name + "': ", m_shaders); + bgfx_effect* effect = effect_reader::read_from_value(document, "Effect '" + name + "': ", options, m_shaders); - if (effect == nullptr) { - printf("Unable to load effect %s\n", path.c_str()); + if (effect == nullptr) + { + osd_printf_error("Unable to load effect %s\n", name.c_str()); return nullptr; } @@ -92,3 +103,14 @@ bgfx_effect* effect_manager::load_effect(std::string name) return effect; } + +bool effect_manager::validate_effect(osd_options &options, std::string name) +{ + rapidjson::Document document; + if (!prepare_effect_document(name, options, document)) + { + return false; + } + + return effect_reader::validate_value(document, "Effect '" + name + "': ", options); +} diff --git a/src/osd/modules/render/bgfx/effectmanager.h b/src/osd/modules/render/bgfx/effectmanager.h index 8125741c7ff..5d8bf3f5c93 100644 --- a/src/osd/modules/render/bgfx/effectmanager.h +++ b/src/osd/modules/render/bgfx/effectmanager.h @@ -25,16 +25,16 @@ class bgfx_effect; class effect_manager { public: - effect_manager(osd_options& options, shader_manager& shaders) : m_options(options), m_shaders(shaders) { } + effect_manager(shader_manager& shaders) : m_shaders(shaders) { } ~effect_manager(); // Getters - bgfx_effect* effect(std::string name); + bgfx_effect* get_or_load_effect(osd_options &options, std::string name); + static bool validate_effect(osd_options &options, std::string name); private: - bgfx_effect* load_effect(std::string name); + bgfx_effect* load_effect(osd_options& options, std::string name); - osd_options& m_options; shader_manager& m_shaders; std::map<std::string, bgfx_effect*> m_effects; }; diff --git a/src/osd/modules/render/bgfx/effectreader.cpp b/src/osd/modules/render/bgfx/effectreader.cpp index 3e51cb9d9dc..fd59b0bde44 100644 --- a/src/osd/modules/render/bgfx/effectreader.cpp +++ b/src/osd/modules/render/bgfx/effectreader.cpp @@ -23,13 +23,77 @@ #include "effectreader.h" -bgfx_effect* effect_reader::read_from_value(const Value& value, std::string prefix, shader_manager& shaders) +bgfx_effect *effect_reader::read_from_value(const Value& value, std::string prefix, osd_options &options, shader_manager& shaders) { - if (!validate_parameters(value, prefix)) + uint64_t flags = 0; + std::string vertex_name; + std::string fragment_name; + bgfx::ShaderHandle vertex_shader = BGFX_INVALID_HANDLE; + bgfx::ShaderHandle fragment_shader = BGFX_INVALID_HANDLE; + std::vector<bgfx_uniform *> uniforms; + + if (!get_base_effect_data(value, prefix, flags, vertex_name, fragment_name, uniforms)) + { + return nullptr; + } + + if (!get_shader_data(value, options, shaders, vertex_name, vertex_shader, fragment_name, fragment_shader)) { + clear_uniform_list(uniforms); return nullptr; } + bgfx_effect *effect = new bgfx_effect(flags, vertex_shader, fragment_shader, uniforms); + if (effect->is_valid()) + { + return effect; + } + + delete effect; + + return nullptr; +} + +bool effect_reader::validate_value(const Value& value, std::string prefix, osd_options &options) +{ + if (!validate_parameters(value, prefix)) + { + return false; + } + + uint64_t flags = 0; + std::string vertex_name; + std::string fragment_name; + std::vector<bgfx_uniform *> uniforms; + + if (!get_base_effect_data(value, prefix, flags, vertex_name, fragment_name, uniforms)) + { + return false; + } + + if (!shader_manager::is_shader_present(options, vertex_name)) + { + clear_uniform_list(uniforms); + return false; + } + + if (!shader_manager::is_shader_present(options, fragment_name)) + { + clear_uniform_list(uniforms); + return false; + } + + return true; +} + +bool effect_reader::get_base_effect_data(const Value& value, std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name, + std::vector<bgfx_uniform *> &uniforms) +{ + if (!validate_parameters(value, prefix)) + { + return false; + } + uint64_t blend = 0; if (value.HasMember("blend")) { @@ -38,34 +102,21 @@ bgfx_effect* effect_reader::read_from_value(const Value& value, std::string pref uint64_t depth = depth_reader::read_from_value(value["depth"], prefix + "depth: "); uint64_t cull = cull_reader::read_from_value(value["cull"]); uint64_t write = write_reader::read_from_value(value["write"]); + flags = blend | depth | cull | write; - std::vector<bgfx_uniform*> uniforms; const Value& uniform_array = value["uniforms"]; for (uint32_t i = 0; i < uniform_array.Size(); i++) { - bgfx_uniform* uniform = uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: "); + bgfx_uniform *uniform = uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: "); if (uniform == nullptr) { - return nullptr; + return false; } uniforms.push_back(uniform); } - std::string vertex_name(value["vertex"].GetString()); - bgfx::ShaderHandle vertex_shader = shaders.shader(vertex_name); - if (vertex_shader.idx == 0xffff) - { - for (bgfx_uniform* uniform : uniforms) - { - if (uniform != nullptr) - { - delete uniform; - } - } - return nullptr; - } + vertex_name = value["vertex"].GetString(); - std::string fragment_name(""); if (value.HasMember("fragment")) { fragment_name = value["fragment"].GetString(); @@ -74,20 +125,38 @@ bgfx_effect* effect_reader::read_from_value(const Value& value, std::string pref { fragment_name = value["pixel"].GetString(); } - bgfx::ShaderHandle fragment_shader = shaders.shader(fragment_name); - if (fragment_shader.idx == 0xffff) + else { - for (bgfx_uniform* uniform : uniforms) - { - if (uniform != nullptr) - { - delete uniform; - } - } - return nullptr; + fragment_name = ""; } - return new bgfx_effect(blend | depth | cull | write, vertex_shader, fragment_shader, uniforms); + return true; +} + +bool effect_reader::get_shader_data(const Value& value, osd_options &options, shader_manager &shaders, std::string &vertex_name, bgfx::ShaderHandle &vertex_shader, + std::string &fragment_name, bgfx::ShaderHandle &fragment_shader) +{ + vertex_shader = shaders.load_shader(options, vertex_name); + if (vertex_shader.idx == bgfx::kInvalidHandle) + { + return false; + } + + fragment_shader = shaders.load_shader(options, fragment_name); + if (fragment_shader.idx == bgfx::kInvalidHandle) + { + return false; + } + + return true; +} + +void effect_reader::clear_uniform_list(std::vector<bgfx_uniform *> &uniforms) +{ + for (bgfx_uniform *uniform : uniforms) + { + delete uniform; + } } bool effect_reader::validate_parameters(const Value& value, std::string prefix) diff --git a/src/osd/modules/render/bgfx/effectreader.h b/src/osd/modules/render/bgfx/effectreader.h index 0bc1b334435..d632c7326c2 100644 --- a/src/osd/modules/render/bgfx/effectreader.h +++ b/src/osd/modules/render/bgfx/effectreader.h @@ -16,14 +16,21 @@ #include "statereader.h" class bgfx_effect; +class bgfx_uniform; class shader_manager; class effect_reader : public state_reader { public: - static bgfx_effect* read_from_value(const Value& value, std::string prefix, shader_manager& shaders); + static bgfx_effect *read_from_value(const Value& value, std::string prefix, osd_options &options, shader_manager& shaders); + static bool validate_value(const Value& value, std::string prefix, osd_options &options); private: + static bool get_base_effect_data(const Value& value, std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name, + std::vector<bgfx_uniform *> &uniforms); + static bool get_shader_data(const Value& value, osd_options &options, shader_manager &shaders, std::string &vertex_name, bgfx::ShaderHandle &vertex_shader, + std::string &fragment_name, bgfx::ShaderHandle &fragment_shader); + static void clear_uniform_list(std::vector<bgfx_uniform *> &uniforms); static bool validate_parameters(const Value& value, std::string prefix); }; diff --git a/src/osd/modules/render/bgfx/shadermanager.cpp b/src/osd/modules/render/bgfx/shadermanager.cpp index 7583b58dec5..dd131e719a5 100644 --- a/src/osd/modules/render/bgfx/shadermanager.cpp +++ b/src/osd/modules/render/bgfx/shadermanager.cpp @@ -28,7 +28,7 @@ shader_manager::~shader_manager() m_shaders.clear(); } -bgfx::ShaderHandle shader_manager::shader(std::string name) +bgfx::ShaderHandle shader_manager::get_or_load_shader(osd_options &options, std::string name) { std::map<std::string, bgfx::ShaderHandle>::iterator iter = m_shaders.find(name); if (iter != m_shaders.end()) @@ -36,12 +36,49 @@ bgfx::ShaderHandle shader_manager::shader(std::string name) return iter->second; } - return load_shader(name); + bgfx::ShaderHandle handle = load_shader(options, name); + if (handle.idx != bgfx::kInvalidHandle) + { + m_shaders[name] = handle; + } + + return handle; +} + +bgfx::ShaderHandle shader_manager::load_shader(osd_options &options, std::string name) +{ + std::string shader_path = make_path_string(options, name); + const bgfx::Memory* mem = load_mem(shader_path + name + ".bin"); + if (mem != nullptr) + { + return bgfx::createShader(mem); + } + + return BGFX_INVALID_HANDLE; } -bgfx::ShaderHandle shader_manager::load_shader(std::string name) +bool shader_manager::is_shader_present(osd_options &options, std::string name) { - std::string shader_path(m_options.bgfx_path()); + std::string shader_path = make_path_string(options, name); + std::string file_name = shader_path + name + ".bin"; + bx::FileReader reader; + if (bx::open(&reader, file_name.c_str())) + { + uint32_t expected_size(bx::getSize(&reader)); + uint8_t *data = new uint8_t[expected_size]; + uint32_t read_size = (uint32_t)bx::read(&reader, data, expected_size); + delete [] data; + bx::close(&reader); + + return expected_size == read_size; + } + + return false; +} + +std::string shader_manager::make_path_string(osd_options &options, std::string name) +{ + std::string shader_path(options.bgfx_path()); shader_path += PATH_SEPARATOR "shaders" PATH_SEPARATOR; switch (bgfx::getRendererType()) { @@ -81,17 +118,7 @@ bgfx::ShaderHandle shader_manager::load_shader(std::string name) shader_path += PATH_SEPARATOR; osd_subst_env(shader_path, shader_path); - const bgfx::Memory* mem = load_mem(shader_path + name + ".bin"); - if (mem != nullptr) - { - bgfx::ShaderHandle handle = bgfx::createShader(mem); - - m_shaders[name] = handle; - - return handle; - } - - return BGFX_INVALID_HANDLE; + return shader_path; } const bgfx::Memory* shader_manager::load_mem(std::string name) @@ -109,7 +136,7 @@ const bgfx::Memory* shader_manager::load_mem(std::string name) } else { - printf("Unable to load shader %s\n", name.c_str()); + osd_printf_error("Unable to load shader %s\n", name.c_str()); } return nullptr; } diff --git a/src/osd/modules/render/bgfx/shadermanager.h b/src/osd/modules/render/bgfx/shadermanager.h index bee48dcea81..d58a669f22f 100644 --- a/src/osd/modules/render/bgfx/shadermanager.h +++ b/src/osd/modules/render/bgfx/shadermanager.h @@ -24,18 +24,19 @@ class shader_manager { public: - shader_manager(osd_options& options) : m_options(options) { } + shader_manager() { } ~shader_manager(); // Getters - bgfx::ShaderHandle shader(std::string name); + bgfx::ShaderHandle get_or_load_shader(osd_options &options, std::string name); + static bgfx::ShaderHandle load_shader(osd_options &options, std::string name); + static bool is_shader_present(osd_options &options, std::string name); private: - bgfx::ShaderHandle load_shader(std::string name); + static std::string make_path_string(osd_options &options, std::string name); static const bgfx::Memory* load_mem(std::string name); std::map<std::string, bgfx::ShaderHandle> m_shaders; - osd_options& m_options; }; #endif // __DRAWBGFX_SHADER_MANAGER__ diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc index 4bd5a57e3ef..c91a8948bf1 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc @@ -9,7 +9,7 @@ uniform vec4 u_aspect; void main() { - float wid = u_width.x*u_tex_size0.x/(320.*u_aspect.x);; + float wid = u_width.x*u_tex_size0.x/(320.*u_aspect.x); v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid)); // Do the standard vertex processing. diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_blit_yuy16.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_blit_yuy16.sc index 91e3c3ed462..af3eb3e3954 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_blit_yuy16.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_blit_yuy16.sc @@ -13,9 +13,10 @@ uniform vec4 u_inv_tex_size0; vec3 ycc_to_rgb(float y, float cb, float cr) { - float r = saturate(y + 1.40200 * (cr - 0.5)); - float g = saturate(y - 0.34414 * (cb - 0.5) - 0.71414 * (cr - 0.5)); - float b = saturate(y + 1.77200 * (cb - 0.5)); + float common = 1.168627 * (y - 0.062745); + float r = saturate(common + 1.603922 * (cr - 0.5)); + float g = saturate(common - 0.392157 * (cb - 0.5) - 0.815686 * (cr - 0.5)); + float b = saturate(common + 2.023529 * (cb - 0.5)); return vec3(r, g, b); } @@ -27,7 +28,7 @@ void main() float mod_val = mod(original_uv.x, 2.0); vec2 rounded_uv = vec2(original_uv.x - mod_val, original_uv.y); vec4 srcpix = texture2D(s_tex, rounded_uv * u_inv_tex_size0.xy + half_texel.x); - + float cr = srcpix.r; float cb = srcpix.b; if (mod_val < 1.0) diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_lut.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_lut.sc index 2c8cffab7e1..6b00e4a1934 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_lut.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_lut.sc @@ -5,9 +5,9 @@ $input v_color0, v_texcoord0 #include "common.sh" -#define LUT_TEXTURE_WIDTH 4096.0f -#define LUT_SIZE 64.0f -#define LUT_SCALE vec2(1.0f / LUT_TEXTURE_WIDTH, 1.0f / LUT_SIZE) +// Autos +uniform vec4 u_tex_size1; +uniform vec4 u_inv_tex_size1; SAMPLER2D(s_tex, 0); SAMPLER2D(s_3dlut, 1); @@ -17,13 +17,12 @@ void main() vec4 bp = texture2D(s_tex, v_texcoord0); vec3 color = bp.rgb; // NOTE: Do not change the order of parameters here. - vec3 lutcoord = vec3(color.rg * ((LUT_SIZE - 1.0f) + 0.5f) * - LUT_SCALE, (LUT_SIZE - 1.0f) * color.b); + vec3 lutcoord = vec3(color.rg * ((u_tex_size1.y - 1.0) + 0.5) * u_inv_tex_size1.xy, (u_tex_size1.y - 1.0) * color.b); float shift = floor(lutcoord.z); - lutcoord.x += shift * LUT_SCALE.y; + lutcoord.x += shift * u_inv_tex_size1.y; color.rgb = mix(texture2D(s_3dlut, lutcoord.xy).rgb, - texture2D(s_3dlut, vec2(lutcoord.x + LUT_SCALE.y, + texture2D(s_3dlut, vec2(lutcoord.x + u_inv_tex_size1.y, lutcoord.y)).rgb, lutcoord.z - shift); gl_FragColor = vec4(color, bp.a) * v_color0; } diff --git a/src/osd/modules/render/bgfx/texturemanager.cpp b/src/osd/modules/render/bgfx/texturemanager.cpp index 1fe6fe13b60..af960707523 100644 --- a/src/osd/modules/render/bgfx/texturemanager.cpp +++ b/src/osd/modules/render/bgfx/texturemanager.cpp @@ -14,6 +14,7 @@ #include "texturemanager.h" #include "texture.h" #include "bgfxutil.h" +#include "fileio.h" #include "rendutil.h" #include "modules/render/copyutil.h" @@ -67,7 +68,7 @@ bgfx_texture* texture_manager::create_png_texture(std::string path, std::string if (bitmap.width() == 0 || bitmap.height() == 0) { - printf("Unable to load PNG '%s' from path '%s'\n", file_name.c_str(), path.c_str()); + osd_printf_error("Unable to load PNG '%s' from path '%s'\n", file_name.c_str(), path.c_str()); return nullptr; } @@ -80,7 +81,7 @@ bgfx_texture* texture_manager::create_png_texture(std::string path, std::string auto* base = reinterpret_cast<uint32_t *>(bitmap.raw_pixptr(0)); for (int y = 0; y < height; y++) { - copy_util::copyline_argb32(data32 + y * width, base + y * rowpixels, width, nullptr); + copy_util::copyline_argb32_to_bgra(data32 + y * width, base + y * rowpixels, width, nullptr); } if (screen >= 0) diff --git a/src/osd/modules/render/bgfx/uniform.cpp b/src/osd/modules/render/bgfx/uniform.cpp index dc81475ad59..36f68b7a9c7 100644 --- a/src/osd/modules/render/bgfx/uniform.cpp +++ b/src/osd/modules/render/bgfx/uniform.cpp @@ -13,7 +13,7 @@ bgfx_uniform::bgfx_uniform(std::string name, bgfx::UniformType::Enum type) : m_name(name) , m_type(type) { - m_handle = bgfx::createUniform(m_name.c_str(), m_type); + m_handle = BGFX_INVALID_HANDLE; m_data_size = get_size_for_type(type); if (m_data_size > 0) { @@ -23,10 +23,18 @@ bgfx_uniform::bgfx_uniform(std::string name, bgfx::UniformType::Enum type) bgfx_uniform::~bgfx_uniform() { - bgfx::destroy(m_handle); + if (m_handle.idx != bgfx::kInvalidHandle) + { + bgfx::destroy(m_handle); + } delete [] m_data; } +void bgfx_uniform::create() +{ + m_handle = bgfx::createUniform(m_name.c_str(), m_type); +} + void bgfx_uniform::upload() { if (m_type != bgfx::UniformType::Sampler) diff --git a/src/osd/modules/render/bgfx/uniform.h b/src/osd/modules/render/bgfx/uniform.h index aa4c2cc097a..f7873f400a9 100644 --- a/src/osd/modules/render/bgfx/uniform.h +++ b/src/osd/modules/render/bgfx/uniform.h @@ -23,6 +23,8 @@ public: virtual void upload(); + void create(); + // Getters std::string name() { return m_name; } bgfx::UniformType::Enum type() const { return m_type; } diff --git a/src/osd/modules/render/bgfx/view.cpp b/src/osd/modules/render/bgfx/view.cpp index 4385500edb1..1e3b2a6000d 100644 --- a/src/osd/modules/render/bgfx/view.cpp +++ b/src/osd/modules/render/bgfx/view.cpp @@ -26,11 +26,14 @@ void bgfx_view::update() { } void bgfx_ortho_view::setup() { - if (m_window_index != 0) + if (m_window_index == 0) + { + bgfx::setViewFrameBuffer(m_index, BGFX_INVALID_HANDLE); + } + else { bgfx::setViewFrameBuffer(m_index, m_backbuffer->target()); } - bgfx::setViewRect(m_index, 0, 0, m_view_width, m_view_height); while ((m_index + 1) > m_seen_views.size()) diff --git a/src/osd/modules/render/bgfx/windowparameter.h b/src/osd/modules/render/bgfx/windowparameter.h index a30b928b817..0ba4224de40 100644 --- a/src/osd/modules/render/bgfx/windowparameter.h +++ b/src/osd/modules/render/bgfx/windowparameter.h @@ -24,7 +24,7 @@ public: virtual ~bgfx_window_parameter() { } virtual float value() override { return float(m_index); } - virtual void tick(double delta) override { }; + virtual void tick(double delta) override { } private: uint32_t m_index; diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index eabcd5bcb81..22a6b5af508 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -13,6 +13,7 @@ #include "rendlay.h" #include "rendutil.h" #include "emuopts.h" +#include "fileio.h" #include "aviio.h" #include "png.h" #include "screen.h" @@ -504,7 +505,7 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r snap_width = winoptions.d3d_snap_width(); snap_height = winoptions.d3d_snap_height(); - this->options = make_unique_clear<hlsl_options>().release(); + this->options = new hlsl_options; this->options->params_init = false; // copy last options if initialized @@ -2318,7 +2319,7 @@ void shaders::init_slider_list() } internal_sliders.clear(); - const screen_device *first_screen = screen_device_enumerator(machine->root_device()).first();; + const screen_device *first_screen = screen_device_enumerator(machine->root_device()).first(); if (first_screen == nullptr) { return; diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h index 5a34d9830df..f72197cb7b1 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.h +++ b/src/osd/modules/render/d3d/d3dhlsl.h @@ -175,92 +175,92 @@ class movie_recorder; /* in the future this will be moved into an OSD/emu shared buffer */ struct hlsl_options { - bool params_init; - bool params_dirty; - int shadow_mask_tile_mode; - float shadow_mask_alpha; - char shadow_mask_texture[1024]; - int shadow_mask_count_x; - int shadow_mask_count_y; - float shadow_mask_u_size; - float shadow_mask_v_size; - float shadow_mask_u_offset; - float shadow_mask_v_offset; - float distortion; - float cubic_distortion; - float distort_corner; - float round_corner; - float smooth_border; - float reflection; - float vignetting; - float scanline_alpha; - float scanline_scale; - float scanline_height; - float scanline_variation; - float scanline_bright_scale; - float scanline_bright_offset; - float scanline_jitter; - float hum_bar_alpha; - float defocus[2]; - float converge_x[3]; - float converge_y[3]; - float radial_converge_x[3]; - float radial_converge_y[3]; - float red_ratio[3]; - float grn_ratio[3]; - float blu_ratio[3]; - float offset[3]; - float scale[3]; - float power[3]; - float floor[3]; - float phosphor[3]; - float saturation; - int chroma_mode; - float chroma_a[2]; - float chroma_b[2]; - float chroma_c[2]; - float chroma_conversion_gain[3]; - float chroma_y_gain[3]; + bool params_init = false; + bool params_dirty = false; + int shadow_mask_tile_mode = 0; + float shadow_mask_alpha = 0.0; + char shadow_mask_texture[1024]{ 0 }; + int shadow_mask_count_x = 0; + int shadow_mask_count_y = 0; + float shadow_mask_u_size = 0.0; + float shadow_mask_v_size = 0.0; + float shadow_mask_u_offset = 0.0; + float shadow_mask_v_offset = 0.0; + float distortion = 0.0; + float cubic_distortion = 0.0; + float distort_corner = 0.0; + float round_corner = 0.0; + float smooth_border = 0.0; + float reflection = 0.0; + float vignetting = 0.0; + float scanline_alpha = 0.0; + float scanline_scale = 0.0; + float scanline_height = 0.0; + float scanline_variation = 0.0; + float scanline_bright_scale = 0.0; + float scanline_bright_offset = 0.0; + float scanline_jitter = 0.0; + float hum_bar_alpha = 0.0; + float defocus[2]{ 0.0 }; + float converge_x[3]{ 0.0 }; + float converge_y[3]{ 0.0 }; + float radial_converge_x[3]{ 0.0 }; + float radial_converge_y[3]{ 0.0 }; + float red_ratio[3]{ 0.0 }; + float grn_ratio[3]{ 0.0 }; + float blu_ratio[3]{ 0.0 }; + float offset[3]{ 0.0 }; + float scale[3]{ 0.0 }; + float power[3]{ 0.0 }; + float floor[3]{ 0.0 }; + float phosphor[3]{ 0.0 }; + float saturation = 0.0; + int chroma_mode = 0; + float chroma_a[2]{ 0.0 }; + float chroma_b[2]{ 0.0 }; + float chroma_c[2]{ 0.0 }; + float chroma_conversion_gain[3]{ 0.0 }; + float chroma_y_gain[3]{ 0.0 }; // NTSC - int yiq_enable; - float yiq_jitter; - float yiq_cc; - float yiq_a; - float yiq_b; - float yiq_o; - float yiq_p; - float yiq_n; - float yiq_y; - float yiq_i; - float yiq_q; - float yiq_scan_time; - int yiq_phase_count; + int yiq_enable = 0; + float yiq_jitter = 0.0; + float yiq_cc = 0.0; + float yiq_a = 0.0; + float yiq_b = 0.0; + float yiq_o = 0.0; + float yiq_p = 0.0; + float yiq_n = 0.0; + float yiq_y = 0.0; + float yiq_i = 0.0; + float yiq_q = 0.0; + float yiq_scan_time = 0.0; + int yiq_phase_count = 0; // Vectors - float vector_beam_smooth; - float vector_length_scale; - float vector_length_ratio; + float vector_beam_smooth = 0.0; + float vector_length_scale = 0.0; + float vector_length_ratio = 0.0; // Bloom - int bloom_blend_mode; - float bloom_scale; - float bloom_overdrive[3]; - float bloom_level0_weight; - float bloom_level1_weight; - float bloom_level2_weight; - float bloom_level3_weight; - float bloom_level4_weight; - float bloom_level5_weight; - float bloom_level6_weight; - float bloom_level7_weight; - float bloom_level8_weight; + int bloom_blend_mode = 0; + float bloom_scale = 0.0; + float bloom_overdrive[3]{ 0.0 }; + float bloom_level0_weight = 0.0; + float bloom_level1_weight = 0.0; + float bloom_level2_weight = 0.0; + float bloom_level3_weight = 0.0; + float bloom_level4_weight = 0.0; + float bloom_level5_weight = 0.0; + float bloom_level6_weight = 0.0; + float bloom_level7_weight = 0.0; + float bloom_level8_weight = 0.0; // Final - char lut_texture[1024]; - int lut_enable; - char ui_lut_texture[1024]; - int ui_lut_enable; + char lut_texture[1024]{ 0 }; + int lut_enable = 0; + char ui_lut_texture[1024]{ 0 }; + int ui_lut_enable = 0; }; struct slider_desc diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp index 29cb8deda00..07570882ec0 100644 --- a/src/osd/modules/render/drawbgfx.cpp +++ b/src/osd/modules/render/drawbgfx.cpp @@ -75,8 +75,10 @@ char const *const renderer_bgfx::WINDOW_PREFIX = "Window 0, "; // STATICS //============================================================ -bool renderer_bgfx::s_window_set = false; uint32_t renderer_bgfx::s_current_view = 0; +bool renderer_bgfx::s_bgfx_library_initialized = false; +uint32_t renderer_bgfx::s_width[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +uint32_t renderer_bgfx::s_height[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //============================================================ // renderer_bgfx - constructor @@ -134,31 +136,96 @@ renderer_bgfx::~renderer_bgfx() delete m_targets; } + + //============================================================ -// renderer_bgfx::create +// renderer_bgfx::init_bgfx_library +//============================================================ + +void renderer_bgfx::init_bgfx_library() +{ + std::string backend(m_options.bgfx_backend()); + + bgfx::Init init; + init.type = bgfx::RendererType::Count; + init.vendorId = BGFX_PCI_ID_NONE; + init.resolution.width = s_width[0]; + init.resolution.height = s_height[0]; + init.resolution.numBackBuffers = 1; + init.resolution.reset = BGFX_RESET_NONE; + init.platformData = m_platform_data; + if (backend == "auto") + { + } + else if (backend == "dx9" || backend == "d3d9") + { + init.type = bgfx::RendererType::Direct3D9; + } + else if (backend == "dx11" || backend == "d3d11") + { + init.type = bgfx::RendererType::Direct3D11; + } + else if (backend == "dx12" || backend == "d3d12") + { + init.type = bgfx::RendererType::Direct3D12; + } + else if (backend == "gles") + { + init.type = bgfx::RendererType::OpenGLES; + } + else if (backend == "glsl" || backend == "opengl") + { + init.type = bgfx::RendererType::OpenGL; + } + else if (backend == "vulkan") + { + init.type = bgfx::RendererType::Vulkan; + } + else if (backend == "metal") + { + init.type = bgfx::RendererType::Metal; + } + else + { + osd_printf_verbose("Unknown backend type '%s', going with auto-detection.\n", backend.c_str()); + } + + bgfx::init(init); + bgfx::reset(s_width[0], s_height[0], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); + // Enable debug text if requested. + bool bgfx_debug = m_options.bgfx_debug(); + bgfx::setDebug(bgfx_debug ? BGFX_DEBUG_STATS : BGFX_DEBUG_TEXT); + + ScreenVertex::init(); + + imguiCreate(); +} + + + +//============================================================ +// Utilities for setting up window handles //============================================================ #ifdef OSD_WINDOWS -inline void winSetHwnd(::HWND _window) +inline void winSetHwnd(bgfx::PlatformData &platform_data, ::HWND _window) { - bgfx::PlatformData pd; - pd.ndt = NULL; - pd.nwh = _window; - pd.context = NULL; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); + platform_data.ndt = NULL; + platform_data.nwh = _window; + platform_data.context = NULL; + platform_data.backBuffer = NULL; + platform_data.backBufferDS = NULL; + bgfx::setPlatformData(platform_data); } #elif defined(OSD_MAC) -inline void macSetWindow(void *_window) +inline void macSetWindow(bgfx::PlatformData &platform_data, void *_window) { - bgfx::PlatformData pd; - pd.ndt = NULL; - pd.nwh = GetOSWindow(_window); - pd.context = NULL; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); + platform_data.ndt = NULL; + platform_data.nwh = GetOSWindow(_window); + platform_data.context = NULL; + platform_data.backBuffer = NULL; + platform_data.backBufferDS = NULL; + bgfx::setPlatformData(platform_data); } #elif defined(OSD_SDL) static void* sdlNativeWindowHandle(SDL_Window* _window) @@ -181,7 +248,7 @@ static void* sdlNativeWindowHandle(SDL_Window* _window) # endif // BX_PLATFORM_ } -inline bool sdlSetWindow(SDL_Window* _window) +inline bool sdlSetWindow(bgfx::PlatformData &platform_data, SDL_Window* _window) { SDL_SysWMinfo wmi; SDL_VERSION(&wmi.version); @@ -190,117 +257,83 @@ inline bool sdlSetWindow(SDL_Window* _window) return false; } - bgfx::PlatformData pd; # if BX_PLATFORM_LINUX || BX_PLATFORM_BSD - pd.ndt = wmi.info.x11.display; - pd.nwh = (void*)(uintptr_t)wmi.info.x11.window; + platform_data.ndt = wmi.info.x11.display; + platform_data.nwh = (void*)(uintptr_t)wmi.info.x11.window; # elif BX_PLATFORM_OSX - pd.ndt = NULL; - pd.nwh = wmi.info.cocoa.window; + platform_data.ndt = NULL; + platform_data.nwh = wmi.info.cocoa.window; # elif BX_PLATFORM_WINDOWS - pd.ndt = NULL; - pd.nwh = wmi.info.win.window; + platform_data.ndt = NULL; + platform_data.nwh = wmi.info.win.window; # endif // BX_PLATFORM_ - pd.context = NULL; - pd.backBuffer = NULL; - pd.backBufferDS = NULL; - bgfx::setPlatformData(pd); + platform_data.context = NULL; + platform_data.backBuffer = NULL; + platform_data.backBufferDS = NULL; + bgfx::setPlatformData(platform_data); return true; } #endif + + +//============================================================ +// renderer_bgfx::create +//============================================================ + int renderer_bgfx::create() { - // create renderer std::shared_ptr<osd_window> win = assert_window(); osd_dim wdim = win->get_size(); - m_width[win->index()] = wdim.width(); - m_height[win->index()] = wdim.height(); + s_width[win->index()] = wdim.width(); + s_height[win->index()] = wdim.height(); + m_dimensions = wdim; + + if (s_bgfx_library_initialized) + { + exit(); + } + if (win->index() == 0) { - if (!s_window_set) - { - s_window_set = true; - ScreenVertex::init(); - } - else - { - bgfx::shutdown(); - bgfx::PlatformData blank_pd; - memset(&blank_pd, 0, sizeof(bgfx::PlatformData)); - bgfx::setPlatformData(blank_pd); - } #ifdef OSD_WINDOWS - winSetHwnd(std::static_pointer_cast<win_window_info>(win)->platform_window()); + winSetHwnd(m_platform_data, std::static_pointer_cast<win_window_info>(win)->platform_window()); #elif defined(OSD_MAC) - macSetWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()); + macSetWindow(m_platform_data, std::static_pointer_cast<mac_window_info>(win)->platform_window()); #else - sdlSetWindow(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()); + sdlSetWindow(m_platform_data, std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()); #endif - std::string backend(m_options.bgfx_backend()); - bgfx::Init init; - init.type = bgfx::RendererType::Count; - init.vendorId = BGFX_PCI_ID_NONE; - init.resolution.width = wdim.width(); - init.resolution.height = wdim.height(); - init.resolution.reset = BGFX_RESET_NONE; - if (backend == "auto") - { - } - else if (backend == "dx9" || backend == "d3d9") - { - init.type = bgfx::RendererType::Direct3D9; - } - else if (backend == "dx11" || backend == "d3d11") - { - init.type = bgfx::RendererType::Direct3D11; - } - else if (backend == "dx12" || backend == "d3d12") - { - init.type = bgfx::RendererType::Direct3D12; - } - else if (backend == "gles") - { - init.type = bgfx::RendererType::OpenGLES; - } - else if (backend == "glsl" || backend == "opengl") - { - init.type = bgfx::RendererType::OpenGL; - } - else if (backend == "vulkan") - { - init.type = bgfx::RendererType::Vulkan; - } - else if (backend == "metal") - { - init.type = bgfx::RendererType::Metal; - } - else - { - printf("Unknown backend type '%s', going with auto-detection\n", backend.c_str()); - } - bgfx::init(init); - bgfx::reset(m_width[win->index()], m_height[win->index()], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); - // Enable debug text. - bgfx::setDebug(m_options.bgfx_debug() ? BGFX_DEBUG_STATS : BGFX_DEBUG_TEXT); - m_dimensions = osd_dim(m_width[0], m_height[0]); + + init_bgfx_library(); } + // finish creating the renderer m_textures = new texture_manager(); m_targets = new target_manager(*m_textures); - m_shaders = new shader_manager(m_options); - m_effects = new effect_manager(m_options, *m_shaders); + m_shaders = new shader_manager(); + m_effects = new effect_manager(*m_shaders); + + // Create program from shaders. + m_gui_effect[0] = m_effects->get_or_load_effect(m_options, "gui_opaque"); + m_gui_effect[1] = m_effects->get_or_load_effect(m_options, "gui_blend"); + m_gui_effect[2] = m_effects->get_or_load_effect(m_options, "gui_multiply"); + m_gui_effect[3] = m_effects->get_or_load_effect(m_options, "gui_add"); + + m_screen_effect[0] = m_effects->get_or_load_effect(m_options, "screen_opaque"); + m_screen_effect[1] = m_effects->get_or_load_effect(m_options, "screen_blend"); + m_screen_effect[2] = m_effects->get_or_load_effect(m_options, "screen_multiply"); + m_screen_effect[3] = m_effects->get_or_load_effect(m_options, "screen_add"); if (win->index() != 0) { #ifdef OSD_WINDOWS - m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), m_width[win->index()], m_height[win->index()]); + m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), s_width[win->index()], s_height[win->index()]); #elif defined(OSD_MAC) - m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), m_width[win->index()], m_height[win->index()]); + m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), s_width[win->index()], s_height[win->index()]); #else - m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), m_width[win->index()], m_height[win->index()]); + m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), s_width[win->index()], s_height[win->index()]); #endif bgfx::touch(win->index()); @@ -309,23 +342,6 @@ int renderer_bgfx::create() } } - // Create program from shaders. - m_gui_effect[0] = m_effects->effect("gui_opaque"); - m_gui_effect[1] = m_effects->effect("gui_blend"); - m_gui_effect[2] = m_effects->effect("gui_multiply"); - m_gui_effect[3] = m_effects->effect("gui_add"); - - m_screen_effect[0] = m_effects->effect("screen_opaque"); - m_screen_effect[1] = m_effects->effect("screen_blend"); - m_screen_effect[2] = m_effects->effect("screen_multiply"); - m_screen_effect[3] = m_effects->effect("screen_add"); - - if ( m_gui_effect[0] == nullptr || m_gui_effect[1] == nullptr || m_gui_effect[2] == nullptr || m_gui_effect[3] == nullptr || - m_screen_effect[0] == nullptr || m_screen_effect[1] == nullptr || m_screen_effect[2] == nullptr || m_screen_effect[3] == nullptr) - { - fatalerror("BGFX: Unable to load required shaders. Please check and reinstall the %s folder\n", m_options.bgfx_path()); - } - m_chains = new chain_manager(win->machine(), m_options, *m_textures, *m_targets, *m_effects, win->index(), *this); m_sliders_dirty = true; @@ -335,11 +351,11 @@ int renderer_bgfx::create() memset(m_white, 0xff, sizeof(uint32_t) * 16 * 16); m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white)); - imguiCreate(); - return 0; } + + //============================================================ // renderer_bgfx::record //============================================================ @@ -355,9 +371,9 @@ void renderer_bgfx::record() if (m_avi_writer == nullptr) { - m_avi_writer = new avi_write(win->machine(), m_width[0], m_height[0]); - m_avi_data = new uint8_t[m_width[0] * m_height[0] * 4]; - m_avi_bitmap.allocate(m_width[0], m_height[0]); + m_avi_writer = new avi_write(win->machine(), s_width[0], s_height[0]); + m_avi_data = new uint8_t[s_width[0] * s_height[0] * 4]; + m_avi_bitmap.allocate(s_width[0], s_height[0]); } if (m_avi_writer->recording()) @@ -372,8 +388,8 @@ void renderer_bgfx::record() else { m_avi_writer->record(m_options.bgfx_avi_name()); - m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::BGRA8, m_width[0], m_height[0], TARGET_STYLE_CUSTOM, false, true, 1, 0); - m_avi_texture = bgfx::createTexture2D(m_width[0], m_height[0], false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK); + m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::BGRA8, s_width[0], s_height[0], TARGET_STYLE_CUSTOM, false, true, 1, 0); + m_avi_texture = bgfx::createTexture2D(s_width[0], s_height[0], false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK); if (m_avi_view == nullptr) { @@ -384,12 +400,32 @@ void renderer_bgfx::record() bool renderer_bgfx::init(running_machine &machine) { - const char *bgfx_path = downcast<osd_options &>(machine.options()).bgfx_path(); + osd_options &options = downcast<osd_options &>(machine.options()); + const char *bgfx_path = options.bgfx_path(); osd::directory::ptr directory = osd::directory::open(bgfx_path); if (directory == nullptr) { - osd_printf_verbose("Unable to find the %s folder. Please reinstall it to use the BGFX renderer\n", bgfx_path); + osd_printf_error("Unable to find the BGFX path %s, please install it or fix the bgfx_path setting to use the BGFX renderer.\n", bgfx_path); + return true; + } + + // Verify baseline shaders. + const bool gui_opaque_valid = effect_manager::validate_effect(options, "gui_opaque"); + const bool gui_blend_valid = effect_manager::validate_effect(options, "gui_blend"); + const bool gui_multiply_valid = effect_manager::validate_effect(options, "gui_multiply"); + const bool gui_add_valid = effect_manager::validate_effect(options, "gui_add"); + const bool all_gui_valid = gui_opaque_valid && gui_blend_valid && gui_multiply_valid && gui_add_valid; + + const bool screen_opaque_valid = effect_manager::validate_effect(options, "screen_opaque"); + const bool screen_blend_valid = effect_manager::validate_effect(options, "screen_blend"); + const bool screen_multiply_valid = effect_manager::validate_effect(options, "screen_multiply"); + const bool screen_add_valid = effect_manager::validate_effect(options, "screen_add"); + const bool all_screen_valid = screen_opaque_valid && screen_blend_valid && screen_multiply_valid && screen_add_valid; + + if (!all_gui_valid || !all_screen_valid) + { + osd_printf_error("BGFX: Unable to load required shaders. Please update the %s folder or adjust your bgfx_path setting.\n", options.bgfx_path()); return true; } @@ -399,9 +435,8 @@ bool renderer_bgfx::init(running_machine &machine) void renderer_bgfx::exit() { imguiDestroy(); - bgfx::shutdown(); - s_window_set = false; + s_bgfx_library_initialized = false; } //============================================================ @@ -507,11 +542,11 @@ void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bg vertex(&vertices[4], x[2], y[2], 0, 0xffffffff, u[2], v[2]); vertex(&vertices[5], x[0], y[0], 0, 0xffffffff, u[0], v[0]); - uint32_t texture_flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; + uint32_t texture_flags = 0U; + if (!PRIMFLAG_GET_TEXWRAP(prim->flags)) + texture_flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; if (video_config.filter == 0) - { texture_flags |= BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT; - } uint32_t blend = PRIMFLAG_GET_BLENDMODE(prim->flags); bgfx::setVertexBuffer(0,buffer); @@ -524,15 +559,15 @@ void renderer_bgfx::render_avi_quad() m_avi_view->set_index(s_current_view); m_avi_view->setup(); - bgfx::setViewRect(s_current_view, 0, 0, m_width[0], m_height[0]); + bgfx::setViewRect(s_current_view, 0, 0, s_width[0], s_height[0]); bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0); bgfx::TransientVertexBuffer buffer; bgfx::allocTransientVertexBuffer(&buffer, 6, ScreenVertex::ms_decl); auto* vertices = reinterpret_cast<ScreenVertex*>(buffer.data); - float x[4] = { 0.0f, float(m_width[0]), 0.0f, float(m_width[0]) }; - float y[4] = { 0.0f, 0.0f, float(m_height[0]), float(m_height[0]) }; + float x[4] = { 0.0f, float(s_width[0]), 0.0f, float(s_width[0]) }; + float y[4] = { 0.0f, 0.0f, float(s_height[0]), float(s_height[0]) }; float u[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; float v[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; uint32_t rgba = 0xffffffff; @@ -567,11 +602,11 @@ void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::Transient vertex(&vertices[4], x[2], y[2], 0, rgba, u[2], v[2]); vertex(&vertices[5], x[0], y[0], 0, rgba, u[0], v[0]); - uint32_t texture_flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; + uint32_t texture_flags = 0U; + if (!PRIMFLAG_GET_TEXWRAP(prim->flags)) + texture_flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; if (video_config.filter == 0) - { texture_flags |= BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT; - } const bool is_screen = PRIMFLAG_GET_SCREENTEX(prim->flags); uint16_t tex_width(prim->texture.width); @@ -824,8 +859,8 @@ int renderer_bgfx::draw(int update) } osd_dim wdim = win->get_size(); - m_width[window_index] = wdim.width(); - m_height[window_index] = wdim.height(); + s_width[window_index] = wdim.width(); + s_height[window_index] = wdim.height(); // Set view 0 default viewport. if (window_index == 0) @@ -837,17 +872,18 @@ int renderer_bgfx::draw(int update) uint32_t num_screens = m_chains->update_screen_textures(s_current_view, win->m_primlist->first(), *win.get()); win->m_primlist->release_lock(); - if (num_screens) - { - s_current_view += m_chains->process_screen_chains(s_current_view, *win.get()); - } - bool skip_frame = update_dimensions(); if (skip_frame) { return 0; } + if (num_screens) + { + uint32_t chain_view_count = m_chains->process_screen_chains(s_current_view, *win.get()); + s_current_view += chain_view_count; + } + if (s_current_view > m_max_view) { m_max_view = s_current_view; @@ -906,7 +942,7 @@ int renderer_bgfx::draw(int update) // This dummy draw call is here to make sure that view 0 is cleared // if no other draw calls are submitted to view 0. - bgfx::touch(s_current_view > 0 ? s_current_view - 1 : 0); + //bgfx::touch(s_current_view > 0 ? s_current_view - 1 : 0); // Advance to next frame. Rendering thread will be kicked to // process submitted rendering primitives. @@ -918,7 +954,10 @@ int renderer_bgfx::draw(int update) bgfx::touch(s_current_view); update_recording(); } + } + if (win->index() == osd_common_t::s_window_list.size() - 1) + { bgfx::frame(); } @@ -959,24 +998,16 @@ bool renderer_bgfx::update_dimensions() std::shared_ptr<osd_window> win = assert_window(); const uint32_t window_index = win->index(); - const uint32_t width = m_width[window_index]; - const uint32_t height = m_height[window_index]; + const uint32_t width = s_width[window_index]; + const uint32_t height = s_height[window_index]; - if (window_index == 0) + if (m_dimensions != osd_dim(width, height)) { - if ((m_dimensions != osd_dim(width, height))) - { - bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); - m_dimensions = osd_dim(width, height); - } - } - else - { - if ((m_dimensions != osd_dim(width, height))) - { - bgfx::reset(win->main_window()->get_size().width(), win->main_window()->get_size().height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); - m_dimensions = osd_dim(width, height); + bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); + m_dimensions = osd_dim(width, height); + if (win->index() != 0) + { delete m_framebuffer; #ifdef OSD_WINDOWS m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), width, height); @@ -986,15 +1017,17 @@ bool renderer_bgfx::update_dimensions() m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), width, height); #endif if (m_ortho_view) + { m_ortho_view->set_backbuffer(m_framebuffer); - + } bgfx::setViewFrameBuffer(s_current_view, m_framebuffer->target()); - bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0); - bgfx::setViewMode(s_current_view, bgfx::ViewMode::Sequential); - bgfx::touch(s_current_view); - bgfx::frame(); - return true; } + + bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0); + bgfx::setViewMode(s_current_view, bgfx::ViewMode::Sequential); + bgfx::touch(s_current_view); + bgfx::frame(); + return true; } return false; } @@ -1003,14 +1036,15 @@ void renderer_bgfx::setup_ortho_view() { if (!m_ortho_view) { - m_ortho_view = new bgfx_ortho_view(this, s_current_view, m_framebuffer, m_seen_views); + m_ortho_view = new bgfx_ortho_view(this, 0, m_framebuffer, m_seen_views); } - m_ortho_view->update(); - if (m_ortho_view->get_index() == UINT_MAX) { + if (m_ortho_view->get_index() == UINT_MAX) + { m_ortho_view->set_index(s_current_view); m_ortho_view->setup(); s_current_view++; } + m_ortho_view->update(); } renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen) @@ -1279,10 +1313,10 @@ void renderer_bgfx::set_sliders_dirty() } uint32_t renderer_bgfx::get_window_width(uint32_t index) const { - return m_width[index]; + return s_width[index]; } uint32_t renderer_bgfx::get_window_height(uint32_t index) const { - return m_height[index]; + return s_height[index]; } diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h index e7e648c27d1..6cbf2631b9d 100644 --- a/src/osd/modules/render/drawbgfx.h +++ b/src/osd/modules/render/drawbgfx.h @@ -85,6 +85,8 @@ public: static char const *const WINDOW_PREFIX; private: + void init_bgfx_library(); + void vertex(ScreenVertex* vertex, float x, float y, float z, uint32_t rgba, float u, float v); void render_avi_quad(); void update_recording(); @@ -122,6 +124,7 @@ private: uint32_t get_texture_hash(render_primitive *prim); osd_options& m_options; + bgfx::PlatformData m_platform_data; bgfx_target *m_framebuffer; bgfx_texture *m_texture_cache; @@ -143,8 +146,6 @@ private: std::vector<rectangle_packer::packable_rectangle> m_texinfo; rectangle_packer m_packer; - uint32_t m_width[16]; - uint32_t m_height[16]; uint32_t m_white[16*16]; bgfx_view *m_ortho_view; uint32_t m_max_view; @@ -160,8 +161,10 @@ private: static const uint32_t PACKABLE_SIZE; static const uint32_t WHITE_HASH; - static bool s_window_set; static uint32_t s_current_view; + static bool s_bgfx_library_initialized; + static uint32_t s_width[16]; + static uint32_t s_height[16]; }; #endif // RENDER_BGFX diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp index a279034ef7d..cfc494a2be9 100644 --- a/src/osd/modules/render/drawd3d.cpp +++ b/src/osd/modules/render/drawd3d.cpp @@ -8,10 +8,11 @@ // MAME headers #include "emu.h" +#include "emuopts.h" #include "render.h" - #include "rendutil.h" -#include "emuopts.h" +#include "screen.h" + #include "aviio.h" // MAMEOS headers @@ -1522,15 +1523,10 @@ void renderer_d3d9::batch_vector(const render_primitive &prim) } // compute the effective width based on the direction of the line - float effwidth = prim.width; - if (effwidth < 2.0f) - { - effwidth = 2.0f; - } + float effwidth = std::max(prim.width, 2.0f); // determine the bounds of a quad to draw this line - render_bounds b0, b1; - render_line_to_quad(&prim.bounds, effwidth, effwidth, &b0, &b1); + auto [b0, b1] = render_line_to_quad(prim.bounds, effwidth, effwidth); float lx = b1.x1 - b0.x1; float ly = b1.y1 - b0.y1; @@ -1629,15 +1625,10 @@ void renderer_d3d9::draw_line(const render_primitive &prim) } // compute the effective width based on the direction of the line - float effwidth = prim.width; - if (effwidth < 1.0f) - { - effwidth = 1.0f; - } + float effwidth = std::max(prim.width, 1.0f); // determine the bounds of a quad to draw this line - render_bounds b0, b1; - render_line_to_quad(&prim.bounds, effwidth, 0.0f, &b0, &b1); + auto [b0, b1] = render_line_to_quad(prim.bounds, effwidth, 0.0f); vertex[0].x = b0.x0; vertex[0].y = b0.y0; diff --git a/src/osd/modules/render/drawgdi.h b/src/osd/modules/render/drawgdi.h index 7984998f4bc..0dfc4bf2641 100644 --- a/src/osd/modules/render/drawgdi.h +++ b/src/osd/modules/render/drawgdi.h @@ -42,9 +42,9 @@ public: virtual int create() override; virtual render_primitive_list *get_primitives() override; virtual int draw(const int update) override; - virtual void save() override {}; - virtual void record() override {}; - virtual void toggle_fsfx() override {}; + virtual void save() override {} + virtual void record() override {} + virtual void toggle_fsfx() override {} private: BITMAPINFO m_bminfo; diff --git a/src/osd/modules/render/drawogl.cpp b/src/osd/modules/render/drawogl.cpp index 7cf99ccfb5f..9e200f3817c 100644 --- a/src/osd/modules/render/drawogl.cpp +++ b/src/osd/modules/render/drawogl.cpp @@ -1253,11 +1253,6 @@ int renderer_ogl::draw(const int update) } #else { - const line_aa_step *step = line_aa_4step; - render_bounds b0, b1; - float r, g, b, a; - float effwidth; - // we're not gonna play fancy here. close anything pending and let's go. if (pendingPrimitive!=GL_NO_PRIMITIVE && pendingPrimitive!=curPrimitive) { @@ -1268,12 +1263,10 @@ int renderer_ogl::draw(const int update) set_blendmode(sdl, PRIMFLAG_GET_BLENDMODE(prim.flags)); // compute the effective width based on the direction of the line - effwidth = prim.width(); - if (effwidth < 0.5f) - effwidth = 0.5f; + float effwidth = std::max(prim.width(), 0.5f); // determine the bounds of a quad to draw this line - render_line_to_quad(&prim.bounds, effwidth, 0.0f, &b0, &b1); + auto [b0, b1] = render_line_to_quad(prim.bounds, effwidth, 0.0f); // fix window position b0.x0 += hofs; @@ -1286,7 +1279,7 @@ int renderer_ogl::draw(const int update) b1.y1 += vofs; // iterate over AA steps - for (step = PRIMFLAG_GET_ANTIALIAS(prim.flags) ? line_aa_4step : line_aa_1step; step->weight != 0; step++) + for (const line_aa_step *step = PRIMFLAG_GET_ANTIALIAS(prim.flags) ? line_aa_4step : line_aa_1step; step->weight != 0; step++) { glBegin(GL_TRIANGLE_STRIP); @@ -1303,14 +1296,10 @@ int renderer_ogl::draw(const int update) glVertex2f(b1.x1 + step->xoffs, b1.y1 + step->yoffs); // determine the color of the line - r = (prim.color.r * step->weight); - g = (prim.color.g * step->weight); - b = (prim.color.b * step->weight); - a = (prim.color.a * 255.0f); - if (r > 1.0) r = 1.0; - if (g > 1.0) g = 1.0; - if (b > 1.0) b = 1.0; - if (a > 1.0) a = 1.0; + float r = std::min(prim.color.r * step->weight, 1.0f); + float g = std::min(prim.color.g * step->weight, 1.0f); + float b = std::min(prim.color.b * step->weight, 1.0f); + float a = std::min(prim.color.a * 255.0f, 1.0f); glColor4f(r, g, b, a); // texture = texture_update(window, &prim, 0); diff --git a/src/osd/osdnet.cpp b/src/osd/osdnet.cpp index b90a139731c..97b37366a4d 100644 --- a/src/osd/osdnet.cpp +++ b/src/osd/osdnet.cpp @@ -61,7 +61,7 @@ int osd_netdev::send(uint8_t *buf, int len) return 0; } -void osd_netdev::recv(void *ptr, int param) +void osd_netdev::recv(int param) { uint8_t *buf; int len; diff --git a/src/osd/osdnet.h b/src/osd/osdnet.h index 32e41663dcc..f18d7c5fea7 100644 --- a/src/osd/osdnet.h +++ b/src/osd/osdnet.h @@ -44,7 +44,7 @@ protected: virtual int recv_dev(uint8_t **buf); private: - void recv(void *ptr, int param); + void recv(int param); class device_network_interface *m_dev; emu_timer *m_timer; diff --git a/src/osd/osdsync.cpp b/src/osd/osdsync.cpp index 85950b33093..6c6fec4dedf 100644 --- a/src/osd/osdsync.cpp +++ b/src/osd/osdsync.cpp @@ -85,14 +85,15 @@ static void spin_while_not(const volatile _AtomType * volatile atom, const _Main // osd_num_processors //============================================================ -int osd_get_num_processors() +int osd_get_num_processors(bool heavy_mt) { #if defined(SDLMAME_EMSCRIPTEN) // multithreading is not supported at this time return 1; #else + unsigned int threads = std::thread::hardware_concurrency(); // max out at 4 for now since scaling above that seems to do poorly - return std::min(std::thread::hardware_concurrency(), 4U); + return heavy_mt ? threads : std::min(std::thread::hardware_concurrency(), 4U); #endif } @@ -105,8 +106,7 @@ struct work_thread_info work_thread_info(uint32_t aid, osd_work_queue &aqueue) : queue(aqueue) , handle(nullptr) - , wakeevent(false, false) // auto-reset, not signalled - , active(0) + , wakeevent(true, false) // manual reset, not signalled , id(aid) #if KEEP_STATISTICS , itemsdone(0) @@ -120,7 +120,6 @@ struct work_thread_info osd_work_queue & queue; // pointer back to the queue std::thread * handle; // handle to the thread osd_event wakeevent; // wake event for the thread - std::atomic<int32_t> active; // are we actively processing work? uint32_t id; #if KEEP_STATISTICS @@ -211,7 +210,7 @@ int osd_num_processors = 0; // FUNCTION PROTOTYPES //============================================================ -static int effective_num_processors(); +static int effective_num_processors(bool heavy_mt); static void * worker_thread_entry(void *param); static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread); static bool queue_has_list_items(osd_work_queue *queue); @@ -251,7 +250,7 @@ int thread_adjust_priority(std::thread *thread, int adjust) osd_work_queue *osd_work_queue_alloc(int flags) { int threadnum; - int numprocs = effective_num_processors(); + int numprocs = effective_num_processors(!(flags & WORK_QUEUE_FLAG_HIGH_FREQ)); osd_work_queue *queue; int osdthreadnum = 0; int allocthreadnum; @@ -544,10 +543,9 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call { work_thread_info *thread = queue->thread[threadnum]; - // if this thread is not active, wake him up - if (!thread->active) + // Attempt to wake the thread + if (thread->wakeevent.set()) { - thread->wakeevent.set(); add_to_stat(queue->setevents, 1); // for non-shared, the first one we find is good enough @@ -639,9 +637,9 @@ void osd_work_item_release(osd_work_item *item) // effective_num_processors //============================================================ -static int effective_num_processors() +static int effective_num_processors(bool heavy_mt) { - int physprocs = osd_get_num_processors(); + int physprocs = osd_get_num_processors(heavy_mt); // osd_num_processors == 0 for 'auto' if (osd_num_processors > 0) @@ -692,7 +690,6 @@ static void *worker_thread_entry(void *param) break; // indicate that we are live - thread->active = true; ++queue.livethreads; // process work items @@ -717,7 +714,7 @@ static void *worker_thread_entry(void *param) } // decrement the live thread count - thread->active = false; + thread->wakeevent.reset(); --queue.livethreads; } diff --git a/src/osd/osdsync.h b/src/osd/osdsync.h index 3a286b60afa..cd8a6604c21 100644 --- a/src/osd/osdsync.h +++ b/src/osd/osdsync.h @@ -136,16 +136,17 @@ public: Return value: - None + Whether or not the event was actually signalled (false if the event had already been signalled) Notes: All threads waiting for the event will be signalled. -----------------------------------------------------------------------------*/ - void set() + bool set() { m_mutex.lock(); - if (m_signalled == false) + bool needs_signal = !m_signalled; + if (needs_signal) { m_signalled = true; if (m_autoreset) @@ -154,13 +155,14 @@ public: m_cond.notify_all(); } m_mutex.unlock(); + return needs_signal; } private: std::mutex m_mutex; std::condition_variable m_cond; - std::atomic<int32_t> m_autoreset; - std::atomic<int32_t> m_signalled; + int32_t m_autoreset; + int32_t m_signalled; }; diff --git a/src/osd/sdl/sdlmain.cpp b/src/osd/sdl/sdlmain.cpp index 1a65e48a846..3c57faeddbb 100644 --- a/src/osd/sdl/sdlmain.cpp +++ b/src/osd/sdl/sdlmain.cpp @@ -437,10 +437,21 @@ void sdl_osd_interface::init(running_machine &machine) } stemp = options().video_driver(); - if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) != 0) + if (stemp != nullptr) { - osd_printf_verbose("Setting SDL videodriver '%s' ...\n", stemp); - osd_setenv(SDLENV_VIDEODRIVER, stemp, 1); + if (strcmp(stemp, OSDOPTVAL_AUTO) != 0) + { + osd_printf_verbose("Setting SDL videodriver '%s' ...\n", stemp); + osd_setenv(SDLENV_VIDEODRIVER, stemp, 1); + } + else + { +#if defined(__linux__) + // bgfx does not work with wayland + osd_printf_verbose("Setting SDL videodriver '%s' ...\n", "x11"); + osd_setenv(SDLENV_VIDEODRIVER, "x11", 1); +#endif + } } stemp = options().render_driver(); diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp index 5bb3910d8f9..8212e0a4586 100644 --- a/src/osd/sdl/video.cpp +++ b/src/osd/sdl/video.cpp @@ -191,12 +191,10 @@ void sdl_osd_interface::extract_video_config() stemp = options().video(); if (strcmp(stemp, "auto") == 0) { -#if (defined SDLMAME_WIN32) - stemp = "opengl"; -#elif (defined SDLMAME_MACOSX) - stemp = "bgfx"; -#else +#if (defined SDLMAME_EMSCRIPTEN) stemp = "soft"; +#else + stemp = "bgfx"; #endif } if (strcmp(stemp, SDLOPTVAL_SOFT) == 0) diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp index 29ed4b920eb..0bf11ddfa9a 100644 --- a/src/osd/sdl/window.cpp +++ b/src/osd/sdl/window.cpp @@ -29,6 +29,7 @@ #include "emu.h" #include "emuopts.h" #include "render.h" +#include "screen.h" #include "ui/uimain.h" // OSD headers @@ -91,25 +92,55 @@ bool sdl_osd_interface::window_init() { osd_printf_verbose("Enter sdlwindow_init\n"); - // initialize the drawers + // initialize the renderer + const int fallbacks[VIDEO_MODE_COUNT] = { + -1, // NONE -> no fallback + -1, // No GDI on Linux +#if defined(USE_OPENGL) && USE_OPENGL + VIDEO_MODE_OPENGL, // BGFX -> OpenGL + -1, // OpenGL -> no fallback +#else + VIDEO_MODE_SDL2ACCEL, // BGFX -> SDL2Accel +#endif + -1, // SDL2ACCEL -> no fallback + -1, // No D3D on Linux + -1, // SOFT -> no fallback + }; - switch (video_config.mode) + int current_mode = video_config.mode; + while (current_mode != VIDEO_MODE_NONE) { - case VIDEO_MODE_BGFX: - renderer_bgfx::init(machine()); - break; -#if (USE_OPENGL) - case VIDEO_MODE_OPENGL: - renderer_ogl::init(machine()); - break; + bool error = false; + switch(current_mode) + { + case VIDEO_MODE_BGFX: + error = renderer_bgfx::init(machine()); + break; +#if defined(USE_OPENGL) && USE_OPENGL + case VIDEO_MODE_OPENGL: + renderer_ogl::init(machine()); + break; #endif - case VIDEO_MODE_SDL2ACCEL: - renderer_sdl2::init(machine()); - break; - case VIDEO_MODE_SOFT: - renderer_sdl1::init(machine()); + case VIDEO_MODE_SDL2ACCEL: + renderer_sdl2::init(machine()); + break; + case VIDEO_MODE_SOFT: + renderer_sdl1::init(machine()); + break; + default: + fatalerror("Unknown video mode."); + break; + } + if (error) + { + current_mode = fallbacks[current_mode]; + } + else + { break; + } } + video_config.mode = current_mode; /* We may want to set a number of the hints SDL2 provides. * The code below will document which hints were set. @@ -966,6 +997,10 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad // compute the visible area based on the proposed rectangle target()->compute_visible_area(propwidth, propheight, pixel_aspect, target()->orientation(), viswidth, visheight); + // clamp visable area to the proposed rectangle + viswidth = std::min(viswidth, propwidth); + visheight = std::min(visheight, propheight); + // compute the adjustments we need to make adjwidth = (viswidth + extrawidth) - rect.width(); adjheight = (visheight + extraheight) - rect.height(); @@ -1014,6 +1049,12 @@ osd_dim sdl_window_info::get_min_bounds(int constrain) // get the minimum target size target()->compute_minimum_size(minwidth, minheight); + // check if visible area is bigger + int32_t viswidth, visheight; + target()->compute_visible_area(minwidth, minheight, monitor()->aspect(), target()->orientation(), viswidth, visheight); + minwidth = std::max(viswidth, minwidth); + minheight = std::max(visheight, minheight); + // expand to our minimum dimensions if (minwidth < MIN_WINDOW_DIM) minwidth = MIN_WINDOW_DIM; diff --git a/src/osd/strconv.cpp b/src/osd/strconv.cpp index 4dafeddd398..737cb9fc1dc 100644 --- a/src/osd/strconv.cpp +++ b/src/osd/strconv.cpp @@ -254,6 +254,11 @@ std::string from_wstring(const WCHAR *s) int osd_uchar_from_osdchar(char32_t *uchar, const char *osdchar, size_t count) { + // FIXME: Does not handle charsets that use variable lengths encodings such + // as example GB18030 or UTF-8. + // FIXME: Assumes all characters can be converted into a single wchar_t + // which may not always be the case such as with surrogate pairs. + WCHAR wch; CPINFO cp; @@ -261,7 +266,7 @@ int osd_uchar_from_osdchar(char32_t *uchar, const char *osdchar, size_t count) goto error; // The multibyte char can't be bigger than the max character size - count = std::min(count, size_t(cp.MaxCharSize)); + count = std::min(count, size_t(IsDBCSLeadByte(*osdchar) ? cp.MaxCharSize : 1)); if (MultiByteToWideChar(CP_ACP, 0, osdchar, static_cast<DWORD>(count), &wch, 1) == 0) goto error; diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp index c5166d67a11..e8eaa39256a 100644 --- a/src/osd/windows/window.cpp +++ b/src/osd/windows/window.cpp @@ -8,9 +8,6 @@ #define LOG_TEMP_PAUSE 0 -// Needed for RAW Input -#define WM_INPUT 0x00FF - // standard C headers #include <process.h> @@ -133,12 +130,13 @@ bool windows_osd_interface::window_init() window_thread = GetCurrentThread(); window_threadid = main_threadid; + // initialize the renderer const int fallbacks[VIDEO_MODE_COUNT] = { -1, // NONE -> no fallback VIDEO_MODE_NONE, // GDI -> NONE VIDEO_MODE_D3D, // BGFX -> D3D #if (USE_OPENGL) - VIDEO_MODE_GDI, // OPENGL -> GDI + -1, // OPENGL -> no fallback #endif -1, // No SDL2ACCEL on Windows OSD #if (USE_OPENGL) @@ -154,7 +152,7 @@ bool windows_osd_interface::window_init() { bool error = false; switch(current_mode) - { + { case VIDEO_MODE_NONE: error = renderer_none::init(machine()); break; @@ -304,6 +302,8 @@ win_window_info::win_window_info( , m_targetview(0) , m_targetorient(0) , m_targetvismask(0) + , m_targetscalemode(0) + , m_targetkeepaspect(machine.options().keep_aspect()) , m_lastclicktime(std::chrono::steady_clock::time_point::min()) , m_lastclickx(0) , m_lastclicky(0) @@ -783,12 +783,17 @@ void win_window_info::update() int const targetorient = target()->orientation(); render_layer_config const targetlayerconfig = target()->layer_config(); u32 const targetvismask = target()->visibility_mask(); - if (targetview != m_targetview || targetorient != m_targetorient || targetlayerconfig != m_targetlayerconfig || targetvismask != m_targetvismask) + int const targetscalemode = target()->scale_mode(); + bool const targetkeepaspect = target()->keepaspect(); + if (targetview != m_targetview || targetorient != m_targetorient || targetlayerconfig != m_targetlayerconfig || targetvismask != m_targetvismask || + targetscalemode != m_targetscalemode || targetkeepaspect != m_targetkeepaspect) { m_targetview = targetview; m_targetorient = targetorient; m_targetlayerconfig = targetlayerconfig; m_targetvismask = targetvismask; + m_targetscalemode = targetscalemode; + m_targetkeepaspect = targetkeepaspect; // in window mode, reminimize/maximize if (!fullscreen()) @@ -1105,6 +1110,21 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR return DefWindowProc(wnd, message, wparam, lparam); break; + // input device change: handle RawInput device connection/disconnection + case WM_INPUT_DEVICE_CHANGE: + switch (wparam) + { + case GIDC_ARRIVAL: + downcast<windows_osd_interface&>(window->machine().osd()).handle_input_event(INPUT_EVENT_ARRIVAL, &lparam); + break; + case GIDC_REMOVAL: + downcast<windows_osd_interface&>(window->machine().osd()).handle_input_event(INPUT_EVENT_REMOVAL, &lparam); + break; + default: + return DefWindowProc(wnd, message, wparam, lparam); + } + break; + // input: handle the raw input case WM_INPUT: downcast<windows_osd_interface&>(window->machine().osd()).handle_input_event(INPUT_EVENT_RAWINPUT, &lparam); @@ -1480,6 +1500,10 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad // compute the visible area based on the proposed rectangle target()->compute_visible_area(propwidth, propheight, pixel_aspect, target()->orientation(), viswidth, visheight); + // clamp visable area to the proposed rectangle + viswidth = std::min(viswidth, propwidth); + visheight = std::min(visheight, propheight); + // compute the adjustments we need to make adjwidth = (viswidth + extrawidth) - rect.width(); adjheight = (visheight + extraheight) - rect.height(); @@ -1528,6 +1552,12 @@ osd_dim win_window_info::get_min_bounds(int constrain) // get the minimum target size target()->compute_minimum_size(minwidth, minheight); + // check if visible area is bigger + int32_t viswidth, visheight; + target()->compute_visible_area(minwidth, minheight, monitor()->aspect(), target()->orientation(), viswidth, visheight); + minwidth = std::max(viswidth, minwidth); + minheight = std::max(visheight, minheight); + // expand to our minimum dimensions if (minwidth < MIN_WINDOW_DIMX) minwidth = MIN_WINDOW_DIMX; @@ -1631,6 +1661,10 @@ void win_window_info::update_minmax_state() (rect_height(&bounds) == minbounds.height()); m_ismaximized = (rect_width(&bounds) == maxbounds.width()) || (rect_height(&bounds) == maxbounds.height()); + + // We can't be maximized and minimized simultaneously + if (m_ismaximized) + m_isminimized = FALSE; } else { diff --git a/src/osd/windows/window.h b/src/osd/windows/window.h index 6586420df66..ac7ccf3277d 100644 --- a/src/osd/windows/window.h +++ b/src/osd/windows/window.h @@ -107,6 +107,8 @@ public: int m_targetorient; render_layer_config m_targetlayerconfig; u32 m_targetvismask; + int m_targetscalemode; + bool m_targetkeepaspect; // input info std::chrono::steady_clock::time_point m_lastclicktime; diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp index ba66380f71e..77eeeaf476e 100644 --- a/src/osd/windows/winmain.cpp +++ b/src/osd/windows/winmain.cpp @@ -262,9 +262,9 @@ const options_entry windows_options::s_option_entries[] = { WINOPTION_BLOOM_LEVEL6_WEIGHT, "0.04", OPTION_FLOAT, "bloom level 6 weight (1/4 smaller that level 5 target)" }, { WINOPTION_BLOOM_LEVEL7_WEIGHT, "0.02", OPTION_FLOAT, "bloom level 7 weight (1/4 smaller that level 6 target)" }, { WINOPTION_BLOOM_LEVEL8_WEIGHT, "0.01", OPTION_FLOAT, "bloom level 8 weight (1/4 smaller that level 7 target)" }, - { WINOPTION_LUT_TEXTURE, "", OPTION_STRING, "3D LUT texture filename for screen, PNG format" }, + { WINOPTION_LUT_TEXTURE, "lut-default.png", OPTION_STRING, "3D LUT texture filename for screen, PNG format" }, { WINOPTION_LUT_ENABLE, "0", OPTION_BOOLEAN, "Enables 3D LUT to be applied to screen after post-processing" }, - { WINOPTION_UI_LUT_TEXTURE, "", OPTION_STRING, "3D LUT texture filename of UI, PNG format" }, + { WINOPTION_UI_LUT_TEXTURE, "lut-default.png", OPTION_STRING, "3D LUT texture filename of UI, PNG format" }, { WINOPTION_UI_LUT_ENABLE, "0", OPTION_BOOLEAN, "enable 3D LUT to be applied to UI and artwork after post-processing" }, // full screen options diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index ef1cd1aff4f..7c1689cff9f 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -243,6 +243,8 @@ enum input_event INPUT_EVENT_KEYDOWN, INPUT_EVENT_KEYUP, INPUT_EVENT_RAWINPUT, + INPUT_EVENT_ARRIVAL, + INPUT_EVENT_REMOVAL, INPUT_EVENT_MOUSE_BUTTON }; |