diff options
73 files changed, 3279 insertions, 3768 deletions
diff --git a/scripts/src/osd/modules.lua b/scripts/src/osd/modules.lua index a6f8a7db820..6db305a9ff8 100644 --- a/scripts/src/osd/modules.lua +++ b/scripts/src/osd/modules.lua @@ -59,69 +59,76 @@ function osdmodulesbuild() MAME_DIR .. "src/osd/interface/inputseq.cpp", MAME_DIR .. "src/osd/interface/inputseq.h", MAME_DIR .. "src/osd/modules/debugger/debug_module.h", - MAME_DIR .. "src/osd/modules/font/font_module.h", - MAME_DIR .. "src/osd/modules/midi/midi_module.h", - MAME_DIR .. "src/osd/modules/netdev/netdev_module.h", - MAME_DIR .. "src/osd/modules/sound/sound_module.h", - MAME_DIR .. "src/osd/modules/diagnostics/diagnostics_module.h", - MAME_DIR .. "src/osd/modules/monitor/monitor_module.h", - MAME_DIR .. "src/osd/modules/lib/osdobj_common.cpp", - MAME_DIR .. "src/osd/modules/lib/osdobj_common.h", - MAME_DIR .. "src/osd/modules/diagnostics/none.cpp", - MAME_DIR .. "src/osd/modules/diagnostics/diagnostics_win32.cpp", - MAME_DIR .. "src/osd/modules/debugger/none.cpp", - MAME_DIR .. "src/osd/modules/debugger/debugwin.cpp", - MAME_DIR .. "src/osd/modules/debugger/debugimgui.cpp", MAME_DIR .. "src/osd/modules/debugger/debuggdbstub.cpp", + MAME_DIR .. "src/osd/modules/debugger/debugimgui.cpp", + MAME_DIR .. "src/osd/modules/debugger/debugwin.cpp", + MAME_DIR .. "src/osd/modules/debugger/none.cpp", MAME_DIR .. "src/osd/modules/debugger/xmlconfig.cpp", MAME_DIR .. "src/osd/modules/debugger/xmlconfig.h", - MAME_DIR .. "src/osd/modules/font/font_sdl.cpp", - MAME_DIR .. "src/osd/modules/font/font_windows.cpp", + MAME_DIR .. "src/osd/modules/diagnostics/diagnostics_module.h", + MAME_DIR .. "src/osd/modules/diagnostics/diagnostics_win32.cpp", + MAME_DIR .. "src/osd/modules/diagnostics/none.cpp", MAME_DIR .. "src/osd/modules/font/font_dwrite.cpp", - MAME_DIR .. "src/osd/modules/font/font_osx.cpp", + MAME_DIR .. "src/osd/modules/font/font_module.h", MAME_DIR .. "src/osd/modules/font/font_none.cpp", - MAME_DIR .. "src/osd/modules/netdev/taptun.cpp", - MAME_DIR .. "src/osd/modules/netdev/pcap.cpp", - MAME_DIR .. "src/osd/modules/netdev/none.cpp", - MAME_DIR .. "src/osd/modules/midi/portmidi.cpp", - MAME_DIR .. "src/osd/modules/midi/none.cpp", - MAME_DIR .. "src/osd/modules/sound/js_sound.cpp", - MAME_DIR .. "src/osd/modules/sound/direct_sound.cpp", - MAME_DIR .. "src/osd/modules/sound/pa_sound.cpp", - MAME_DIR .. "src/osd/modules/sound/pulse_sound.cpp", - MAME_DIR .. "src/osd/modules/sound/coreaudio_sound.cpp", - MAME_DIR .. "src/osd/modules/sound/sdl_sound.cpp", - MAME_DIR .. "src/osd/modules/sound/xaudio2_sound.cpp", - MAME_DIR .. "src/osd/modules/sound/none.cpp", - MAME_DIR .. "src/osd/modules/input/input_module.h", + MAME_DIR .. "src/osd/modules/font/font_osx.cpp", + MAME_DIR .. "src/osd/modules/font/font_sdl.cpp", + MAME_DIR .. "src/osd/modules/font/font_windows.cpp", MAME_DIR .. "src/osd/modules/input/input_common.cpp", MAME_DIR .. "src/osd/modules/input/input_common.h", MAME_DIR .. "src/osd/modules/input/input_dinput.cpp", MAME_DIR .. "src/osd/modules/input/input_dinput.h", + MAME_DIR .. "src/osd/modules/input/input_mac.cpp", + MAME_DIR .. "src/osd/modules/input/input_module.h", MAME_DIR .. "src/osd/modules/input/input_none.cpp", MAME_DIR .. "src/osd/modules/input/input_rawinput.cpp", - MAME_DIR .. "src/osd/modules/input/input_win32.cpp", MAME_DIR .. "src/osd/modules/input/input_sdl.cpp", - MAME_DIR .. "src/osd/modules/input/input_x11.cpp", + MAME_DIR .. "src/osd/modules/input/input_win32.cpp", MAME_DIR .. "src/osd/modules/input/input_wincommon.h", MAME_DIR .. "src/osd/modules/input/input_windows.cpp", MAME_DIR .. "src/osd/modules/input/input_windows.h", + MAME_DIR .. "src/osd/modules/input/input_winhybrid.cpp", + MAME_DIR .. "src/osd/modules/input/input_x11.cpp", MAME_DIR .. "src/osd/modules/input/input_xinput.cpp", MAME_DIR .. "src/osd/modules/input/input_xinput.h", - MAME_DIR .. "src/osd/modules/input/input_winhybrid.cpp", - MAME_DIR .. "src/osd/modules/input/input_mac.cpp", - MAME_DIR .. "src/osd/modules/output/output_module.h", - MAME_DIR .. "src/osd/modules/output/none.cpp", + MAME_DIR .. "src/osd/modules/lib/osdobj_common.cpp", + MAME_DIR .. "src/osd/modules/lib/osdobj_common.h", + MAME_DIR .. "src/osd/modules/midi/midi_module.h", + MAME_DIR .. "src/osd/modules/midi/none.cpp", + MAME_DIR .. "src/osd/modules/midi/portmidi.cpp", + MAME_DIR .. "src/osd/modules/monitor/monitor_common.cpp", + MAME_DIR .. "src/osd/modules/monitor/monitor_common.h", + MAME_DIR .. "src/osd/modules/monitor/monitor_dxgi.cpp", + MAME_DIR .. "src/osd/modules/monitor/monitor_mac.cpp", + MAME_DIR .. "src/osd/modules/monitor/monitor_module.h", + MAME_DIR .. "src/osd/modules/monitor/monitor_sdl.cpp", + MAME_DIR .. "src/osd/modules/monitor/monitor_win32.cpp", + MAME_DIR .. "src/osd/modules/netdev/netdev_module.h", + MAME_DIR .. "src/osd/modules/netdev/none.cpp", + MAME_DIR .. "src/osd/modules/netdev/pcap.cpp", + MAME_DIR .. "src/osd/modules/netdev/taptun.cpp", MAME_DIR .. "src/osd/modules/output/console.cpp", MAME_DIR .. "src/osd/modules/output/network.cpp", + MAME_DIR .. "src/osd/modules/output/none.cpp", + MAME_DIR .. "src/osd/modules/output/output_module.h", MAME_DIR .. "src/osd/modules/output/win32_output.cpp", MAME_DIR .. "src/osd/modules/output/win32_output.h", - MAME_DIR .. "src/osd/modules/monitor/monitor_common.h", - MAME_DIR .. "src/osd/modules/monitor/monitor_common.cpp", - MAME_DIR .. "src/osd/modules/monitor/monitor_win32.cpp", - MAME_DIR .. "src/osd/modules/monitor/monitor_dxgi.cpp", - MAME_DIR .. "src/osd/modules/monitor/monitor_sdl.cpp", - MAME_DIR .. "src/osd/modules/monitor/monitor_mac.cpp", + MAME_DIR .. "src/osd/modules/render/blit13.ipp", + MAME_DIR .. "src/osd/modules/render/draw13.cpp", + MAME_DIR .. "src/osd/modules/render/drawgdi.cpp", + MAME_DIR .. "src/osd/modules/render/drawnone.cpp", + MAME_DIR .. "src/osd/modules/render/drawogl.cpp", + MAME_DIR .. "src/osd/modules/render/drawsdl.cpp", + MAME_DIR .. "src/osd/modules/render/render_module.h", + MAME_DIR .. "src/osd/modules/sound/coreaudio_sound.cpp", + MAME_DIR .. "src/osd/modules/sound/direct_sound.cpp", + MAME_DIR .. "src/osd/modules/sound/js_sound.cpp", + MAME_DIR .. "src/osd/modules/sound/none.cpp", + MAME_DIR .. "src/osd/modules/sound/pa_sound.cpp", + MAME_DIR .. "src/osd/modules/sound/pulse_sound.cpp", + MAME_DIR .. "src/osd/modules/sound/sdl_sound.cpp", + MAME_DIR .. "src/osd/modules/sound/sound_module.h", + MAME_DIR .. "src/osd/modules/sound/xaudio2_sound.cpp", } includedirs { MAME_DIR .. "src/osd", @@ -152,7 +159,6 @@ function osdmodulesbuild() } else files { - MAME_DIR .. "src/osd/modules/render/drawogl.cpp", MAME_DIR .. "src/osd/modules/opengl/gl_shader_tool.cpp", MAME_DIR .. "src/osd/modules/opengl/gl_shader_mgr.cpp", MAME_DIR .. "src/osd/modules/opengl/gl_shader_mgr.h", diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua index 4c6a979f952..3aa046b8ab1 100644 --- a/scripts/src/osd/sdl.lua +++ b/scripts/src/osd/sdl.lua @@ -430,7 +430,6 @@ project ("osd_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/osdepend.h", MAME_DIR .. "src/osd/modules/osdwindow.cpp", MAME_DIR .. "src/osd/modules/osdwindow.h", - MAME_DIR .. "src/osd/modules/render/drawsdl.cpp", MAME_DIR .. "src/osd/sdl/osdsdl.cpp", MAME_DIR .. "src/osd/sdl/osdsdl.h", MAME_DIR .. "src/osd/sdl/sdlmain.cpp", @@ -441,10 +440,6 @@ project ("osd_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/sdl/window.cpp", MAME_DIR .. "src/osd/sdl/window.h", } - files { - MAME_DIR .. "src/osd/modules/render/draw13.cpp", - MAME_DIR .. "src/osd/modules/render/blit13.h", - } project ("ocore_" .. _OPTIONS["osd"]) diff --git a/scripts/src/osd/windows.lua b/scripts/src/osd/windows.lua index be91ec26237..ac300261ce8 100644 --- a/scripts/src/osd/windows.lua +++ b/scripts/src/osd/windows.lua @@ -132,10 +132,6 @@ project ("osd_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/modules/render/d3d/d3dhlsl.h", MAME_DIR .. "src/osd/modules/render/drawd3d.cpp", MAME_DIR .. "src/osd/modules/render/drawd3d.h", - MAME_DIR .. "src/osd/modules/render/drawgdi.cpp", - MAME_DIR .. "src/osd/modules/render/drawgdi.h", - MAME_DIR .. "src/osd/modules/render/drawnone.cpp", - MAME_DIR .. "src/osd/modules/render/drawnone.h", MAME_DIR .. "src/osd/windows/video.cpp", MAME_DIR .. "src/osd/windows/video.h", MAME_DIR .. "src/osd/windows/window.cpp", diff --git a/src/osd/mac/video.cpp b/src/osd/mac/video.cpp index e534fbc7fb9..4ae04c4e132 100644 --- a/src/osd/mac/video.cpp +++ b/src/osd/mac/video.cpp @@ -74,10 +74,12 @@ bool mac_osd_interface::video_init() get_resolution(options().resolution(), options().resolution(index), &conf, true); // create window ... - std::shared_ptr<mac_window_info> win = std::make_shared<mac_window_info>(machine(), index, m_monitor_module->pick_monitor(reinterpret_cast<osd_options &>(options()), index), &conf); + auto win = std::make_unique<mac_window_info>(machine(), *m_render, index, m_monitor_module->pick_monitor(reinterpret_cast<osd_options &>(options()), index), &conf); if (win->window_init()) return false; + + s_window_list.emplace_back(std::move(win)); } return true; @@ -104,7 +106,7 @@ void mac_osd_interface::update(bool skip_redraw) if (!skip_redraw) { // profiler_mark(PROFILER_BLIT); - for (auto window : osd_common_t::s_window_list) + for (auto const &window : osd_common_t::window_list()) window->update(); // profiler_mark(PROFILER_END); } @@ -135,11 +137,11 @@ static void check_osd_inputs(running_machine &machine) // check for toggling fullscreen mode if (machine.ui_input().pressed(IPT_OSD_1)) { - for (auto curwin : osd_common_t::s_window_list) - std::static_pointer_cast<mac_window_info>(curwin)->toggle_full_screen(); + for (auto const &curwin : osd_common_t::window_list()) + dynamic_cast<mac_window_info &>(*curwin).toggle_full_screen(); } - auto window = osd_common_t::s_window_list.front(); + auto const &window = osd_common_t::window_list().front(); //FIXME: on a per window basis if (machine.ui_input().pressed(IPT_OSD_5)) @@ -149,10 +151,10 @@ static void check_osd_inputs(running_machine &machine) } if (machine.ui_input().pressed(IPT_OSD_6)) - std::static_pointer_cast<mac_window_info>(window)->modify_prescale(-1); + dynamic_cast<mac_window_info &>(*window).modify_prescale(-1); if (machine.ui_input().pressed(IPT_OSD_7)) - std::static_pointer_cast<mac_window_info>(window)->modify_prescale(1); + dynamic_cast<mac_window_info &>(*window).modify_prescale(1); if (machine.ui_input().pressed(IPT_OSD_8)) window->renderer().record(); @@ -164,8 +166,6 @@ static void check_osd_inputs(running_machine &machine) void mac_osd_interface::extract_video_config() { - const char *stemp; - // global options: extract the data video_config.windowed = options().window(); video_config.prescale = options().prescale(); @@ -176,37 +176,6 @@ void mac_osd_interface::extract_video_config() if (machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) video_config.windowed = true; - // default to working video please - video_config.novideo = 0; - - // d3d options: extract the data - stemp = options().video(); - if (strcmp(stemp, "auto") == 0) - { - stemp = "opengl"; - } - - if (strcmp(stemp, OSDOPTVAL_NONE) == 0) - { - video_config.mode = VIDEO_MODE_SOFT; - video_config.novideo = 1; - - if (!emulator_info::standalone() && options().seconds_to_run() == 0) - osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n"); - } - - else if (strcmp(stemp, MACOPTVAL_OPENGL) == 0) - video_config.mode = VIDEO_MODE_OPENGL; - else if (strcmp(stemp, MACOPTVAL_BGFX) == 0) - { - video_config.mode = VIDEO_MODE_BGFX; - } - else - { - osd_printf_warning("Invalid video value %s; reverting to OpenGL\n", stemp); - video_config.mode = VIDEO_MODE_OPENGL; - } - video_config.switchres = options().switch_res(); video_config.waitvsync = options().wait_vsync(); video_config.syncrefresh = options().sync_refresh(); @@ -222,57 +191,6 @@ void mac_osd_interface::extract_video_config() video_config.prescale = 1; } - // default to working video please - video_config.forcepow2texture = options().gl_force_pow2_texture(); - video_config.allowtexturerect = !(options().gl_no_texture_rect()); - video_config.vbo = options().gl_vbo(); - video_config.pbo = options().gl_pbo(); - video_config.glsl = options().gl_glsl(); - if ( video_config.glsl ) - { - int i; - video_config.glsl_filter = options().glsl_filter(); - video_config.glsl_shader_mamebm_num=0; - for(i=0; i<GLSL_SHADER_MAX; i++) - { - stemp = options().shader_mame(i); - if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0) - { - video_config.glsl_shader_mamebm[i] = (char *) malloc(strlen(stemp)+1); - strcpy(video_config.glsl_shader_mamebm[i], stemp); - video_config.glsl_shader_mamebm_num++; - } else { - video_config.glsl_shader_mamebm[i] = nullptr; - } - } - video_config.glsl_shader_scrn_num=0; - for(i=0; i<GLSL_SHADER_MAX; i++) - { - stemp = options().shader_screen(i); - if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0) - { - video_config.glsl_shader_scrn[i] = (char *) malloc(strlen(stemp)+1); - strcpy(video_config.glsl_shader_scrn[i], stemp); - video_config.glsl_shader_scrn_num++; - } else { - video_config.glsl_shader_scrn[i] = nullptr; - } - } - } else { - int i; - video_config.glsl_filter = 0; - video_config.glsl_shader_mamebm_num=0; - for(i=0; i<GLSL_SHADER_MAX; i++) - { - video_config.glsl_shader_mamebm[i] = nullptr; - } - video_config.glsl_shader_scrn_num=0; - for(i=0; i<GLSL_SHADER_MAX; i++) - { - video_config.glsl_shader_scrn[i] = nullptr; - } - } - // misc options: sanity check values // global options: sanity check values diff --git a/src/osd/mac/window.cpp b/src/osd/mac/window.cpp index ea2adbb631f..f8d95a40205 100644 --- a/src/osd/mac/window.cpp +++ b/src/osd/mac/window.cpp @@ -27,8 +27,6 @@ #include "window.h" #include "osdmac.h" -#include "modules/render/drawbgfx.h" -#include "modules/render/drawogl.h" #include "modules/monitor/monitor_common.h" //============================================================ @@ -115,7 +113,7 @@ bool mac_osd_interface::window_init() void mac_osd_interface::update_slider_list() { - for (auto window : osd_common_t::s_window_list) + for (auto const &window : osd_common_t::window_list()) { // check if any window has dirty sliders if (window->renderer().sliders_dirty()) @@ -130,7 +128,7 @@ void mac_osd_interface::build_slider_list() { m_sliders.clear(); - for (auto window : osd_common_t::s_window_list) + for (auto const &window : osd_common_t::window_list()) { std::vector<ui::menu_item> window_sliders = window->renderer().get_slider_list(); m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end()); @@ -149,23 +147,11 @@ void mac_osd_interface::window_exit() // free all the windows while (!osd_common_t::s_window_list.empty()) { - auto window = osd_common_t::s_window_list.front(); - - // Part of destroy removes the window from the list + auto window = std::move(osd_common_t::s_window_list.back()); + s_window_list.pop_back(); window->destroy(); } - switch(video_config.mode) - { - case VIDEO_MODE_BGFX: - renderer_bgfx::exit(); - break; - case VIDEO_MODE_OPENGL: - renderer_ogl::exit(); - break; - default: - break; - } osd_printf_verbose("Leave macwindow_exit\n"); } @@ -256,7 +242,7 @@ void mac_window_info::toggle_full_screen() downcast<mac_osd_interface &>(machine().osd()).release_keys(); - set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this())); + renderer_create(); // toggle the window mode set_fullscreen(!fullscreen()); @@ -338,7 +324,7 @@ int mac_window_info::window_init() create_target(); - set_renderer(osd_renderer::make_for_type(video_config.mode, static_cast<osd_window*>(this)->shared_from_this())); + renderer_create(); result = complete_create(); @@ -586,24 +572,6 @@ int mac_window_info::complete_create() set_platform_window(window); - // set main window - if (index() > 0) - { - for (auto w : osd_common_t::s_window_list) - { - if (w->index() == 0) - { - set_main_window(std::dynamic_pointer_cast<osd_window>(w)); - break; - } - } - } - else - { - // We must be the main window - set_main_window(shared_from_this()); - } - // update monitor resolution after mode change to ensure proper pixel aspect monitor()->refresh(); if (fullscreen() && video_config.switchres) @@ -909,10 +877,11 @@ osd_dim mac_window_info::get_max_bounds(int constrain) mac_window_info::mac_window_info( running_machine &a_machine, + render_module &renderprovider, int index, std::shared_ptr<osd_monitor_info> a_monitor, const osd_window_config *config) - : osd_window_t(a_machine, index, a_monitor, *config) + : osd_window_t(a_machine, renderprovider, index, a_monitor, *config) , m_startmaximized(0) // Following three are used by input code to defer resizes , m_minimum_dim(0, 0) diff --git a/src/osd/mac/window.h b/src/osd/mac/window.h index e93257aa132..0c08784667d 100644 --- a/src/osd/mac/window.h +++ b/src/osd/mac/window.h @@ -8,8 +8,10 @@ // //============================================================ -#ifndef __MACWINDOW__ -#define __MACWINDOW__ +#ifndef MAME_OSD_MAC_WINDOW_H +#define MAME_OSD_MAC_WINDOW_H + +#pragma once #include "osdmac.h" #include "osdsync.h" @@ -90,25 +92,4 @@ private: void measure_fps(int update); }; -struct osd_draw_callbacks -{ - osd_renderer *(*create)(osd_window *window); -}; - -//============================================================ -// PROTOTYPES -//============================================================ - -//============================================================ -// PROTOTYPES - drawogl.c -//============================================================ - -int drawogl_init(running_machine &machine, osd_draw_callbacks *callbacks); - -//============================================================ -// PROTOTYPES - drawbgfx.c -//============================================================ - -int drawbgfx_init(running_machine &machine, osd_draw_callbacks *callbacks); - -#endif /* __MACWINDOW__ */ +#endif // MAME_OSD_MAC_WINDOW_H diff --git a/src/osd/modules/debugger/debugwin.cpp b/src/osd/modules/debugger/debugwin.cpp index 756aa7a5dd8..2793452dbe6 100644 --- a/src/osd/modules/debugger/debugwin.cpp +++ b/src/osd/modules/debugger/debugwin.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// debugwin.c - Win32 debug window handling +// debugwin.cpp - Win32 debug window handling // //============================================================ @@ -156,7 +156,7 @@ void debugger_windows::wait_for_debugger(device_t &device, bool firststop) // set the starting position for new auxiliary windows HMONITOR const nearest_monitor = MonitorFromWindow( - std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(), + dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(), MONITOR_DEFAULTTONEAREST); if (nearest_monitor) { @@ -321,7 +321,7 @@ void debugger_windows::show_all() void debugger_windows::hide_all() { - SetForegroundWindow(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window()); + SetForegroundWindow(dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window()); for (auto &info : m_window_list) info->hide(); } diff --git a/src/osd/modules/debugger/win/debugwininfo.cpp b/src/osd/modules/debugger/win/debugwininfo.cpp index 473236fcd8d..8c3275a7549 100644 --- a/src/osd/modules/debugger/win/debugwininfo.cpp +++ b/src/osd/modules/debugger/win/debugwininfo.cpp @@ -47,7 +47,7 @@ debugwin_info::debugwin_info(debugger_windows_interface &debugger, bool is_main_ m_wnd = win_create_window_ex_utf8( DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE, 0, 0, 100, 100, - std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(), + dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(), create_standard_menubar(), GetModuleHandleUni(), this); diff --git a/src/osd/modules/font/font_module.h b/src/osd/modules/font/font_module.h index 81ffaca74e5..7fe04e32628 100644 --- a/src/osd/modules/font/font_module.h +++ b/src/osd/modules/font/font_module.h @@ -24,7 +24,7 @@ class font_module { public: - virtual ~font_module() { } + virtual ~font_module() = default; /** attempt to allocate a font instance */ virtual osd_font::ptr font_alloc() = 0; diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp index 93b1f233000..31a36fc841a 100644 --- a/src/osd/modules/input/input_dinput.cpp +++ b/src/osd/modules/input/input_dinput.cpp @@ -625,11 +625,11 @@ std::pair<Microsoft::WRL::ComPtr<IDirectInputDevice8>, LPCDIDATAFORMAT> dinput_a HWND window_handle; DWORD di_cooperative_level; #if defined(OSD_WINDOWS) - auto const window = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front()); - bool const standalone_window = window && !window->attached_mode(); + auto const &window = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()); + bool const standalone_window = !window.attached_mode(); #elif defined(SDLMAME_WIN32) - auto const window = std::static_pointer_cast<sdl_window_info>(osd_common_t::s_window_list.front()); - bool const standalone_window = bool(window); + auto const &window = dynamic_cast<sdl_window_info &>(*osd_common_t::window_list().front()); + bool const standalone_window = true; #endif if (!standalone_window) { @@ -640,12 +640,13 @@ std::pair<Microsoft::WRL::ComPtr<IDirectInputDevice8>, LPCDIDATAFORMAT> dinput_a else { #if defined(OSD_WINDOWS) - window_handle = window->platform_window(); + window_handle = window.platform_window(); #elif defined(SDLMAME_WIN32) - auto const sdlwindow = window->platform_window(); + auto const sdlwindow = window.platform_window(); SDL_SysWMinfo info; SDL_VERSION(&info.version); - SDL_GetWindowWMInfo(sdlwindow, &info); + if (!SDL_GetWindowWMInfo(sdlwindow, &info)) + return std::make_pair(nullptr, nullptr); window_handle = info.info.win.window; #endif switch (cooperative_level) diff --git a/src/osd/modules/input/input_rawinput.cpp b/src/osd/modules/input/input_rawinput.cpp index 804f4ae53cd..910e1873a76 100644 --- a/src/osd/modules/input/input_rawinput.cpp +++ b/src/osd/modules/input/input_rawinput.cpp @@ -595,7 +595,7 @@ public: registration.dwFlags = RIDEV_DEVNOTIFY; if (background_input()) registration.dwFlags |= RIDEV_INPUTSINK; - registration.hwndTarget = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(); + registration.hwndTarget = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(); // register the device RegisterRawInputDevices(®istration, 1, sizeof(registration)); diff --git a/src/osd/modules/input/input_win32.cpp b/src/osd/modules/input/input_win32.cpp index 92281f1cf49..a98d928ba5a 100644 --- a/src/osd/modules/input/input_win32.cpp +++ b/src/osd/modules/input/input_win32.cpp @@ -154,7 +154,9 @@ public: m_mouse.lY = (cursor_info.ptScreenPos.y - m_win32_mouse.last_point.y) * INPUT_RELATIVE_PER_PIXEL; RECT window_pos = {0}; - GetWindowRect(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(), &window_pos); + GetWindowRect( + dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(), + &window_pos); // We reset the cursor position to the middle of the window each frame m_win32_mouse.last_point.x = window_pos.left + (window_pos.right - window_pos.left) / 2; @@ -326,10 +328,10 @@ public: // get the cursor position and transform into final results POINT mousepos; GetCursorPos(&mousepos); - if (!osd_common_t::s_window_list.empty()) + if (!osd_common_t::window_list().empty()) { // get the position relative to the window - HWND const hwnd = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(); + HWND const hwnd = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(); RECT client_rect; GetClientRect(hwnd, &client_rect); ScreenToClient(hwnd, &mousepos); @@ -390,7 +392,7 @@ protected: if (args.keydown) { // get the position relative to the window - HWND const hwnd = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(); + HWND const hwnd = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(); RECT client_rect; GetClientRect(hwnd, &client_rect); diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index de6c0a4f2fd..92eacddc739 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -10,12 +10,14 @@ #include "osdobj_common.h" +#include "modules/osdwindow.h" #include "modules/debugger/debug_module.h" #include "modules/font/font_module.h" #include "modules/input/input_module.h" #include "modules/midi/midi_module.h" #include "modules/monitor/monitor_module.h" #include "modules/netdev/netdev_module.h" +#include "modules/render/render_module.h" #include "modules/sound/sound_module.h" #include "osdnet.h" @@ -66,7 +68,6 @@ const options_entry osd_options::s_option_entries[] = { OSDOPTION_BENCH, "0", core_options::option_type::INTEGER, "benchmark for the given number of emulated seconds; implies -video none -sound none -nothrottle" }, { nullptr, nullptr, core_options::option_type::HEADER, "OSD VIDEO OPTIONS" }, -// OS X can be trusted to have working hardware OpenGL, so default to it on for the best user experience { OSDOPTION_VIDEO, OSDOPTVAL_AUTO, core_options::option_type::STRING, "video output method: " }, { OSDOPTION_NUMSCREENS "(1-4)", "1", core_options::option_type::INTEGER, "number of output screens/windows to create; usually, you want just one" }, { OSDOPTION_WINDOW ";w", "0", core_options::option_type::BOOLEAN, "enable window mode; otherwise, full screen mode is assumed" }, @@ -181,7 +182,7 @@ const options_entry osd_options::s_option_entries[] = { OSDOPTION_BGFX_LUT, "lut-default.png", core_options::option_type::STRING, "LUT texture name" }, { OSDOPTION_BGFX_AVI_NAME, OSDOPTVAL_AUTO, core_options::option_type::PATH, "filename for BGFX output logging" }, - // End of list + // End of list { nullptr } }; @@ -192,7 +193,7 @@ osd_options::osd_options() } // Window list -std::list<std::shared_ptr<osd_window>> osd_common_t::s_window_list; +std::list<std::unique_ptr<osd_window> > osd_common_t::s_window_list; //------------------------------------------------- // osd_interface - constructor @@ -237,6 +238,26 @@ void osd_common_t::register_options() REGISTER_MODULE(m_mod_man, FONT_SDL); REGISTER_MODULE(m_mod_man, FONT_NONE); +#if defined(SDLMAME_EMSCRIPTEN) + REGISTER_MODULE(m_mod_man, RENDERER_SDL1); // don't bother trying to use video acceleration in browsers +#endif +#if defined(OSD_WINDOWS) + REGISTER_MODULE(m_mod_man, RENDERER_D3D); // this is only built for OSD=windows, there's no dummy stub +#endif +#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) + REGISTER_MODULE(m_mod_man, RENDERER_BGFX); // try BGFX before GDI on windows to get DirectX 10/11 acceleration +#endif + REGISTER_MODULE(m_mod_man, RENDERER_GDI); // GDI ahead of OpenGL as there's a chance Windows has no OpenGL + REGISTER_MODULE(m_mod_man, RENDERER_OPENGL); +#if !defined(OSD_WINDOWS) && !defined(SDLMAME_WIN32) + REGISTER_MODULE(m_mod_man, RENDERER_BGFX); // try BGFX after OpenGL on other operating systems for now +#endif + REGISTER_MODULE(m_mod_man, RENDERER_SDL2); +#if !defined(SDLMAME_EMSCRIPTEN) + REGISTER_MODULE(m_mod_man, RENDERER_SDL1); +#endif + REGISTER_MODULE(m_mod_man, RENDERER_NONE); + REGISTER_MODULE(m_mod_man, SOUND_DSOUND); REGISTER_MODULE(m_mod_man, SOUND_XAUDIO2); REGISTER_MODULE(m_mod_man, SOUND_COREAUDIO); @@ -306,23 +327,18 @@ void osd_common_t::register_options() // after initialization we know which modules are supported - - update_option(OSD_MONITOR_PROVIDER, m_mod_man.get_module_names(OSD_MONITOR_PROVIDER)); update_option(OSD_FONT_PROVIDER, m_mod_man.get_module_names(OSD_FONT_PROVIDER)); + update_option(OSD_RENDERER_PROVIDER, m_mod_man.get_module_names(OSD_RENDERER_PROVIDER)); + update_option(OSD_SOUND_PROVIDER, m_mod_man.get_module_names(OSD_SOUND_PROVIDER)); + update_option(OSD_MONITOR_PROVIDER, m_mod_man.get_module_names(OSD_MONITOR_PROVIDER)); update_option(OSD_KEYBOARDINPUT_PROVIDER, m_mod_man.get_module_names(OSD_KEYBOARDINPUT_PROVIDER)); update_option(OSD_MOUSEINPUT_PROVIDER, m_mod_man.get_module_names(OSD_MOUSEINPUT_PROVIDER)); update_option(OSD_LIGHTGUNINPUT_PROVIDER, m_mod_man.get_module_names(OSD_LIGHTGUNINPUT_PROVIDER)); update_option(OSD_JOYSTICKINPUT_PROVIDER, m_mod_man.get_module_names(OSD_JOYSTICKINPUT_PROVIDER)); - update_option(OSD_SOUND_PROVIDER, m_mod_man.get_module_names(OSD_SOUND_PROVIDER)); update_option(OSD_MIDI_PROVIDER, m_mod_man.get_module_names(OSD_MIDI_PROVIDER)); update_option(OSD_NETDEV_PROVIDER, m_mod_man.get_module_names(OSD_NETDEV_PROVIDER)); update_option(OSD_DEBUG_PROVIDER, m_mod_man.get_module_names(OSD_DEBUG_PROVIDER)); update_option(OSD_OUTPUT_PROVIDER, m_mod_man.get_module_names(OSD_OUTPUT_PROVIDER)); - - // Register video options and update options - video_options_add("none", nullptr); - video_register(); - update_option(OSDOPTION_VIDEO, m_video_names); } void osd_common_t::update_option(const std::string &key, std::vector<std::string_view> const &values) @@ -575,28 +591,18 @@ bool osd_common_t::execute_command(const char *command) { if (strcmp(command, OSDCOMMAND_LIST_NETWORK_ADAPTERS) == 0) { - osd_module *om = select_module_options(options(), OSD_NETDEV_PROVIDER); - - if (om->probe()) - { - om->init(*this, options()); - osd_list_network_adapters(); - om->exit(); - } + osd_module &om = select_module_options<osd_module>(OSD_NETDEV_PROVIDER); + osd_list_network_adapters(); + om.exit(); return true; } else if (strcmp(command, OSDCOMMAND_LIST_MIDI_DEVICES) == 0) { - osd_module *om = select_module_options(options(), OSD_MIDI_PROVIDER); - auto *pm = select_module_options<midi_module *>(options(), OSD_MIDI_PROVIDER); + osd_module &om = select_module_options<osd_module>(OSD_MIDI_PROVIDER); + dynamic_cast<midi_module &>(om).list_midi_devices(); + om.exit(); - if (om->probe()) - { - om->init(*this, options()); - pm->list_midi_devices(); - om->exit(); - } return true; } @@ -612,10 +618,10 @@ static void output_notifier_callback(const char *outname, int32_t value, void *p void osd_common_t::init_subsystems() { // monitors have to be initialized before video init - m_monitor_module = select_module_options<monitor_module *>(options(), OSD_MONITOR_PROVIDER); - assert(m_monitor_module != nullptr); - m_monitor_module->init(*this, options()); + m_monitor_module = &select_module_options<monitor_module>(OSD_MONITOR_PROVIDER); + // various modules depend on having a window handle + m_render = &select_module_options<render_module>(OSD_RENDERER_PROVIDER); if (!video_init()) { video_exit(); @@ -625,28 +631,23 @@ void osd_common_t::init_subsystems() exit(-1); } - m_keyboard_input = select_module_options<input_module *>(options(), OSD_KEYBOARDINPUT_PROVIDER); - m_mouse_input = select_module_options<input_module *>(options(), OSD_MOUSEINPUT_PROVIDER); - m_lightgun_input = select_module_options<input_module *>(options(), OSD_LIGHTGUNINPUT_PROVIDER); - m_joystick_input = select_module_options<input_module *>(options(), OSD_JOYSTICKINPUT_PROVIDER); + m_keyboard_input = &select_module_options<input_module>(OSD_KEYBOARDINPUT_PROVIDER); + m_mouse_input = &select_module_options<input_module>(OSD_MOUSEINPUT_PROVIDER); + m_lightgun_input = &select_module_options<input_module>(OSD_LIGHTGUNINPUT_PROVIDER); + m_joystick_input = &select_module_options<input_module>(OSD_JOYSTICKINPUT_PROVIDER); - m_font_module = select_module_options<font_module *>(options(), OSD_FONT_PROVIDER); - m_sound = select_module_options<sound_module *>(options(), OSD_SOUND_PROVIDER); - m_sound->m_sample_rate = options().sample_rate(); - m_sound->m_audio_latency = options().audio_latency(); + m_font_module = &select_module_options<font_module>(OSD_FONT_PROVIDER); + m_sound = &select_module_options<sound_module>(OSD_SOUND_PROVIDER); - m_debugger = select_module_options<debug_module *>(options(), OSD_DEBUG_PROVIDER); + m_debugger = &select_module_options<debug_module>(OSD_DEBUG_PROVIDER); - select_module_options<netdev_module *>(options(), OSD_NETDEV_PROVIDER); + select_module_options<netdev_module>(OSD_NETDEV_PROVIDER); - m_midi = select_module_options<midi_module *>(options(), OSD_MIDI_PROVIDER); + m_midi = &select_module_options<midi_module>(OSD_MIDI_PROVIDER); - m_output = select_module_options<output_module *>(options(), OSD_OUTPUT_PROVIDER); - m_output->set_machine(&machine()); + m_output = &select_module_options<output_module>(OSD_OUTPUT_PROVIDER); machine().output().set_global_notifier(output_notifier_callback, this); - m_mod_man.init(*this, options()); - input_init(); } @@ -665,10 +666,6 @@ bool osd_common_t::no_sound() return (strcmp(options().sound(),"none")==0) ? true : false; } -void osd_common_t::video_register() -{ -} - bool osd_common_t::input_init() { m_keyboard_input->input_init(machine()); @@ -693,17 +690,15 @@ void osd_common_t::window_exit() void osd_common_t::osd_exit() { + // destroy the renderers before shutting down their parent module + for (auto const &window : s_window_list) + window->renderer_reset(); + m_mod_man.exit(); exit_subsystems(); } -void osd_common_t::video_options_add(const char *name, void *type) -{ - //m_video_options.add(name, type, false); - m_video_names.push_back(name); -} - osd_font::ptr osd_common_t::font_alloc() { return m_font_module->font_alloc(); diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h index d90435a884e..33013d43025 100644 --- a/src/osd/modules/lib/osdobj_common.h +++ b/src/osd/modules/lib/osdobj_common.h @@ -190,15 +190,16 @@ public: // ======================> osd_interface -class font_module; -class sound_module; class debug_module; -class midi_module; +class font_module; class input_module; -class output_module; +class midi_module; class monitor_module; class osd_watchdog; class osd_window; +class output_module; +class render_module; +class sound_module; // description of the currently-running machine class osd_common_t : public osd_interface, osd_output @@ -250,7 +251,6 @@ public: virtual void init_subsystems(); virtual bool video_init(); - virtual void video_register(); virtual bool window_init(); virtual void exit_subsystems(); @@ -259,8 +259,6 @@ public: virtual void osd_exit(); - virtual void video_options_add(const char *name, void *type); - virtual osd_options &options() { return m_options; } // osd_output interface ... @@ -273,7 +271,7 @@ public: virtual void process_events() = 0; virtual bool has_focus() const = 0; - static std::list<std::shared_ptr<osd_window> > s_window_list; + static const std::list<std::unique_ptr<osd_window> > &window_list() { return s_window_list; } protected: virtual bool input_init(); @@ -281,6 +279,8 @@ protected: virtual void build_slider_list() { } virtual void update_slider_list() { } + static std::list<std::unique_ptr<osd_window> > s_window_list; + private: // internal state running_machine * m_machine; @@ -293,26 +293,24 @@ private: void update_option(const std::string &key, std::vector<std::string_view> const &values); // FIXME: should be elsewhere - osd_module *select_module_options(const core_options &opts, const std::string &opt_name) + template<class C> + C &select_module_options(const std::string &opt_name) { - std::string opt_val = opts.exists(opt_name) ? opts.value(opt_name) : ""; - if (opt_val.compare("auto")==0) + std::string opt_val = options().exists(opt_name) ? options().value(opt_name) : ""; + if (opt_val == "auto") + { opt_val = ""; + } else if (!m_mod_man.type_has_name(opt_name.c_str(), opt_val.c_str())) { osd_printf_warning("Value %s not supported for option %s - falling back to auto\n", opt_val, opt_name); opt_val = ""; } - return m_mod_man.select_module(opt_name.c_str(), opt_val.c_str()); - } - - template<class C> - C select_module_options(const core_options &opts, const std::string &opt_name) - { - return dynamic_cast<C>(select_module_options(opts, opt_name)); + return m_mod_man.select_module<C>(*this, options(), opt_name.c_str(), opt_val.c_str()); } protected: + render_module* m_render; sound_module* m_sound; debug_module* m_debugger; midi_module* m_midi; @@ -326,7 +324,6 @@ protected: std::vector<ui::menu_item> m_sliders; private: - std::vector<std::string_view> m_video_names; std::unordered_map<std::string, std::string> m_option_descs; }; diff --git a/src/osd/modules/osdmodule.cpp b/src/osd/modules/osdmodule.cpp index 8e3d2f0e3c8..0fb43d4331a 100644 --- a/src/osd/modules/osdmodule.cpp +++ b/src/osd/modules/osdmodule.cpp @@ -7,6 +7,8 @@ #include "modules/osdmodule.h" +#include "emucore.h" + #include "osdcore.h" #include <algorithm> @@ -48,20 +50,62 @@ osd_module *osd_module_manager::get_module_generic(const char *type, const char return nullptr; } -osd_module *osd_module_manager::select_module(const char *type, const char *name) +osd_module &osd_module_manager::select_module(osd_interface &osd, const osd_options &options, const char *type, const char *name) { - osd_module *m = get_module_generic(type, name); + // see if a module of this type has already been already selected + for (osd_module &existing : m_selected) + { + if (existing.type() == type) + { + osd_printf_warning( + "Attempt to select %s module %s after selecting module %s\n", + type, + (name && *name) ? name : "<default>", + existing.name()); + return existing; + } + } - // FIXME: check if already exists! + // try to start the selected module + osd_module *const m = get_module_generic(type, name); if (m) - m_selected.emplace_back(*m); - return m; -} + { + //osd_printf_verbose("Attempting to initialize %s module %s\n", type, m->name()); + if (!m->init(osd, options)) + { + m_selected.emplace_back(*m); + return *m; + } + osd_printf_verbose("Initializing %s module %s failed\n", type, m->name()); + } + else + { + osd_printf_verbose("Could not find %s module %s\n", type, name ? name : "<default>"); + } -void osd_module_manager::init(osd_interface &osd, const osd_options &options) -{ - for (osd_module &m : m_selected) - m.init(osd, options); + // walk down the list until something works + for (auto const &fallback : m_modules) + { + if ((fallback->type() == type) && (fallback.get() != m)) + { + osd_printf_verbose("Attempting to initialize %s module %s\n", type, fallback->name()); + if (!fallback->init(osd, options)) + { + osd_printf_warning( + m + ? "Initializing %s module %s failed, falling back to %s\n" + : "Could not find %s module %s, falling back to %s\n", + type, + m ? m->name() : (name && *name) ? name : "<default>", + fallback->name()); + m_selected.emplace_back(*fallback); + return *fallback; + } + } + } + + // can't deal with absence of a module, and at least the "none" module should have worked + throw emu_fatalerror("All %s modules failed to initialize", type); } void osd_module_manager::exit() diff --git a/src/osd/modules/osdmodule.h b/src/osd/modules/osdmodule.h index 04373dc531f..b690f874706 100644 --- a/src/osd/modules/osdmodule.h +++ b/src/osd/modules/osdmodule.h @@ -78,17 +78,15 @@ public: osd_module *get_module_generic(const char *type, const char *name); template<class C> - C select_module(const char *type, const char *name = "") + C &select_module(osd_interface &osd, const osd_options &options, const char *type, const char *name = "") { - return dynamic_cast<C>(select_module(type, name)); + return dynamic_cast<C &>(select_module(osd, options, type, name)); } - osd_module *select_module(const char *type, const char *name = ""); + osd_module &select_module(osd_interface &osd, const osd_options &options, const char *type, const char *name = ""); std::vector<std::string_view> get_module_names(const char *type) const; - void init(osd_interface &osd, const osd_options &options); - void exit(); private: diff --git a/src/osd/modules/osdwindow.cpp b/src/osd/modules/osdwindow.cpp index 928c3f2c76b..3b2c92c39ea 100644 --- a/src/osd/modules/osdwindow.cpp +++ b/src/osd/modules/osdwindow.cpp @@ -12,25 +12,19 @@ // osd/modules #include "lib/osdobj_common.h" #include "monitor/monitor_module.h" - -#include "render/drawnone.h" -#include "render/drawbgfx.h" -#if (USE_OPENGL) -#include "render/drawogl.h" -#endif -#if defined(OSD_WINDOWS) -#include "render/drawgdi.h" -#include "render/drawd3d.h" -#elif defined(OSD_SDL) -#include "render/draw13.h" -#include "render/drawsdl.h" -#endif +#include "render/render_module.h" // emu #include "main.h" +#include "render.h" -osd_window::osd_window(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config &config) : +osd_window::osd_window( + running_machine &machine, + render_module &renderprovider, + int index, + const std::shared_ptr<osd_monitor_info> &monitor, + const osd_window_config &config) : #ifdef OSD_WINDOWS m_dc(nullptr), m_resize_state(0), #endif @@ -41,22 +35,26 @@ osd_window::osd_window(running_machine &machine, int index, std::shared_ptr<osd_ m_fullscreen(false), m_prescale(1), m_machine(machine), + m_renderprovider(renderprovider), m_monitor(std::move(monitor)), m_renderer(nullptr), - m_main(nullptr), m_title( util::string_format( (video_config.numscreens > 1) ? "%3$s [%4$s] screen %5$d - %1$s %2$s (%6$s%7$sP%8$d)" : "%3$s [%4$s] - %1$s %2$s (%6$s%7$sP%8$d)", - emulator_info::get_appname(), - emulator_info::get_bare_build_version(), - machine.system().type.fullname(), - machine.system().name, - index, - (sizeof(int) == sizeof(void *)) ? "I" : "", - (sizeof(long) == sizeof(void *)) ? "L" : (sizeof(long long) == sizeof(void *)) ? "LL" : "", - sizeof(void *) * 8)) + emulator_info::get_appname(), + emulator_info::get_bare_build_version(), + machine.system().type.fullname(), + machine.system().name, + index, + (sizeof(int) == sizeof(void *)) ? "I" : "", + (sizeof(long) == sizeof(void *)) ? "L" : (sizeof(long long) == sizeof(void *)) ? "LL" : "", + sizeof(void *) * 8)) +{ +} + +osd_window::~osd_window() { } @@ -82,36 +80,6 @@ bool osd_window::keepaspect() const return false; } -std::unique_ptr<osd_renderer> osd_renderer::make_for_type(int mode, std::shared_ptr<osd_window> window, int extra_flags) -{ - switch(mode) - { -#if defined(OSD_WINDOWS) - case VIDEO_MODE_NONE: - return std::make_unique<renderer_none>(window); -#endif - case VIDEO_MODE_BGFX: - return std::make_unique<renderer_bgfx>(window); -#if (USE_OPENGL) - case VIDEO_MODE_OPENGL: - return std::make_unique<renderer_ogl>(window); -#endif -#if defined(OSD_WINDOWS) - case VIDEO_MODE_GDI: - return std::make_unique<renderer_gdi>(window); - case VIDEO_MODE_D3D: - return std::make_unique<renderer_d3d9>(window); -#elif defined(OSD_SDL) - case VIDEO_MODE_SDL2ACCEL: - return std::make_unique<renderer_sdl2>(window, extra_flags); - case VIDEO_MODE_SOFT: - return std::make_unique<renderer_sdl1>(window, extra_flags); -#endif - default: - return nullptr; - } -} - std::shared_ptr<osd_monitor_info> osd_window::monitor_from_rect(const osd_rect *proposed) const { std::shared_ptr<osd_monitor_info> monitor; @@ -128,9 +96,6 @@ std::shared_ptr<osd_monitor_info> osd_window::monitor_from_rect(const osd_rect * void osd_window::create_target() { - // add us to the list - osd_common_t::s_window_list.push_back(shared_from_this()); - // load the layout m_target = m_machine.render().target_alloc(); @@ -139,6 +104,21 @@ void osd_window::create_target() set_starting_view(m_index, options.view(), options.view(m_index)); } +bool osd_window::renderer_interactive() const +{ + return m_renderprovider.is_interactive(); +} + +bool osd_window::renderer_sdl_needs_opengl() const +{ + return m_renderprovider.sdl_needs_opengl(); +} + +void osd_window::renderer_create() +{ + m_renderer = m_renderprovider.create(*this); +} + void osd_window::set_starting_view(int index, const char *defview, const char *view) { // choose non-auto over auto @@ -154,9 +134,6 @@ void osd_window::set_starting_view(int index, const char *defview, const char *v void osd_window::destroy() { - // remove us from the list - osd_common_t::s_window_list.remove(shared_from_this()); - // free the textures etc complete_destroy(); diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h index 9bf7db4e77c..13baf050cbb 100644 --- a/src/osd/modules/osdwindow.h +++ b/src/osd/modules/osdwindow.h @@ -6,13 +6,19 @@ // //============================================================ -#ifndef __OSDWINDOW__ -#define __OSDWINDOW__ +#ifndef MAME_OSD_MODULES_OSDWINDOW_H +#define MAME_OSD_MODULES_OSDWINDOW_H + +#pragma once #include "emucore.h" #include "osdhelper.h" #include "../frontend/mame/ui/menuitem.h" +#include <memory> +#include <string> +#include <vector> + // standard windows headers #ifdef OSD_WINDOWS #include <windows.h> @@ -24,23 +30,12 @@ // TYPE DEFINITIONS //============================================================ -class osd_options; +class osd_monitor_info; +class render_module; class render_primitive_list; -enum -{ - VIDEO_MODE_NONE = 0, - VIDEO_MODE_GDI, - VIDEO_MODE_BGFX, -#if defined(USE_OPENGL) && USE_OPENGL - VIDEO_MODE_OPENGL, -#endif - VIDEO_MODE_SDL2ACCEL, - VIDEO_MODE_D3D, - VIDEO_MODE_SOFT, +class osd_renderer; - VIDEO_MODE_COUNT -}; class osd_window_config { @@ -54,15 +49,11 @@ public: int refresh; // decoded refresh }; -class osd_renderer; -class osd_monitor_info; -class osd_window : public std::enable_shared_from_this<osd_window> +class osd_window { public: - osd_window(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config &config); - - virtual ~osd_window() { } + virtual ~osd_window(); render_target *target() const { return m_target; } int fullscreen() const { return m_fullscreen; } @@ -71,11 +62,7 @@ public: bool has_renderer() const { return m_renderer != nullptr; } osd_renderer &renderer() const { return *m_renderer; } - void set_renderer(std::unique_ptr<osd_renderer> renderer) - { - m_renderer = std::move(renderer); - } - void renderer_reset() { m_renderer.reset(); } + void renderer_reset() { m_renderer.reset(); } // public because OSD object calls it directly during teardown int index() const { return m_index; } int prescale() const { return m_prescale; } @@ -91,9 +78,6 @@ public: osd_monitor_info *monitor() const { return m_monitor.get(); } std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect *proposed) const; - std::shared_ptr<osd_window> main_window() const { return m_main; } - void set_main_window(std::shared_ptr<osd_window> main) { m_main = main; } - void create_target(); void destroy(); @@ -109,6 +93,18 @@ public: virtual void update() = 0; virtual void complete_destroy() = 0; +protected: + osd_window( + running_machine &machine, + render_module &renderprovider, + int index, + const std::shared_ptr<osd_monitor_info> &monitor, + const osd_window_config &config); + + bool renderer_interactive() const; + bool renderer_sdl_needs_opengl() const; + void renderer_create(); + private: void set_starting_view(int index, const char *defview, const char *view); @@ -127,33 +123,32 @@ private: protected: bool m_fullscreen; int m_prescale; + private: - running_machine &m_machine; - std::shared_ptr<osd_monitor_info> m_monitor; - std::unique_ptr<osd_renderer> m_renderer; - std::shared_ptr<osd_window> m_main; - const std::string m_title; + running_machine &m_machine; + render_module &m_renderprovider; + std::shared_ptr<osd_monitor_info> m_monitor; + std::unique_ptr<osd_renderer> m_renderer; + const std::string m_title; }; template <class TWindowHandle> class osd_window_t : public osd_window { -private: - TWindowHandle m_platform_window; public: - osd_window_t(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config &config) - : osd_window(machine, index, std::move(monitor), config), - m_platform_window(nullptr) - { - } - TWindowHandle platform_window() const { return m_platform_window; } +protected: + using osd_window::osd_window; + void set_platform_window(TWindowHandle window) { assert(window == nullptr || m_platform_window == nullptr); m_platform_window = window; } + +private: + TWindowHandle m_platform_window = nullptr; }; @@ -163,31 +158,13 @@ public: /* Generic flags */ static const int FLAG_NONE = 0x0000; - static const int FLAG_NEEDS_OPENGL = 0x0001; - static const int FLAG_HAS_VECTOR_SCREEN = 0x0002; - - /* SDL 1.2 flags */ - static const int FLAG_NEEDS_DOUBLEBUF = 0x0100; - static const int FLAG_NEEDS_ASYNCBLIT = 0x0200; + static const int FLAG_HAS_VECTOR_SCREEN = 0x0001; - osd_renderer(std::shared_ptr<osd_window> window, const int flags) - : m_sliders_dirty(false), m_window(window), m_flags(flags) - { } + osd_renderer(osd_window &window) : m_sliders_dirty(false), m_window(window), m_flags(0) { } virtual ~osd_renderer() { } - std::shared_ptr<osd_window> assert_window() const - { - auto win = m_window.lock(); - if (!win) - throw emu_fatalerror("osd_renderer::assert_window: Window weak_ptr is not available!"); - return win; - } - - std::shared_ptr<osd_window> try_getwindow() const - { - return m_window.lock(); - } + osd_window &window() const { return m_window; } bool has_flags(const int flag) const { return ((m_flags & flag)) == flag; } void set_flags(int aflag) { m_flags |= aflag; } @@ -209,8 +186,6 @@ public: virtual void toggle_fsfx() { } virtual bool sliders_dirty() { return m_sliders_dirty; } - static std::unique_ptr<osd_renderer> make_for_type(int mode, std::shared_ptr<osd_window> window, int extra_flags = FLAG_NONE); - protected: virtual void build_slider_list() { } @@ -220,7 +195,7 @@ protected: std::vector<ui::menu_item> m_sliders; private: - std::weak_ptr<osd_window> m_window; + osd_window &m_window; int m_flags; }; @@ -232,10 +207,6 @@ private: #define MAX_VIDEO_WINDOWS (4) -#define VIDEO_SCALE_MODE_NONE (0) - -#define GLSL_SHADER_MAX 10 - //============================================================ // TYPE DEFINITIONS @@ -249,35 +220,19 @@ struct osd_video_config int numscreens; // number of screens // hardware options - int mode; // output mode int waitvsync; // spin until vsync int syncrefresh; // sync only to refresh rate int switchres; // switch resolutions // d3d, accel, opengl int filter; // enable filtering - //int filter; // enable filtering, disabled if glsl_filter>0 - - // OpenGL options - int glsl; - int glsl_filter; // glsl filtering, >0 disables filter - char * glsl_shader_mamebm[GLSL_SHADER_MAX]; // custom glsl shader set, mame bitmap - int glsl_shader_mamebm_num; // custom glsl shader set number, mame bitmap - char * glsl_shader_scrn[GLSL_SHADER_MAX]; // custom glsl shader set, screen bitmap - int glsl_shader_scrn_num; // custom glsl shader number, screen bitmap - int pbo; - int vbo; - int allowtexturerect; // allow GL_ARB_texture_rectangle, default: no - int forcepow2texture; // force power of two textures, default: no - - // dd, d3d + + // d3d int triplebuf; // triple buffer //============================================================ // SDL - options //============================================================ - int novideo; // don't draw, for pure CPU benchmarking - int centerh; int centerv; @@ -289,9 +244,6 @@ struct osd_video_config // X11 options int restrictonemonitor; // in fullscreen, confine to Xinerama monitor 0 - - // YUV options - int scale_mode; }; //============================================================ @@ -300,4 +252,4 @@ struct osd_video_config extern osd_video_config video_config; -#endif /* __OSDWINDOW__ */ +#endif // MAME_OSD_MODULES_OSDWINDOW_H diff --git a/src/osd/modules/output/network.cpp b/src/osd/modules/output/network.cpp index 5f575682c07..0b3729df340 100644 --- a/src/osd/modules/output/network.cpp +++ b/src/osd/modules/output/network.cpp @@ -10,6 +10,7 @@ #include "output_module.h" +#include "modules/lib/osdobj_common.h" #include "modules/osdmodule.h" #include "emu.h" @@ -25,6 +26,7 @@ #include <set> #include <thread> + namespace osd { namespace { @@ -193,8 +195,7 @@ public: output_network() : osd_module(OSD_OUTPUT_PROVIDER, "network"), output_module(), - m_io_context(nullptr), - m_server(nullptr) + m_machine(nullptr) { } @@ -204,6 +205,7 @@ public: virtual int init(osd_interface &osd, const osd_options &options) override { + m_machine = &downcast<osd_common_t &>(osd).machine(); m_working_thread = std::thread([] (output_network* self) { self->process_output(); }, this); return 0; } @@ -214,8 +216,9 @@ public: notify("mame_stop", 1); m_io_context->stop(); m_working_thread.join(); - delete m_server; - delete m_io_context; + m_server.reset(); + m_io_context.reset(); + m_machine = nullptr; } // output_module @@ -230,15 +233,18 @@ public: // implementation void process_output() { - m_io_context = new asio::io_context(); - m_server = new output_network_server(*m_io_context, 8000, machine()); + m_io_context.reset(new asio::io_context); + m_server.reset(new output_network_server(*m_io_context, 8000, machine())); m_io_context->run(); } private: + running_machine &machine() { return *m_machine; } + std::thread m_working_thread; - asio::io_context *m_io_context; - output_network_server *m_server; + std::unique_ptr<asio::io_context> m_io_context; + std::unique_ptr<output_network_server> m_server; + running_machine *m_machine; }; } // anonymous namespace diff --git a/src/osd/modules/output/output_module.h b/src/osd/modules/output/output_module.h index 81655c77824..ae86cfe9084 100644 --- a/src/osd/modules/output/output_module.h +++ b/src/osd/modules/output/output_module.h @@ -26,17 +26,9 @@ public: static inline constexpr unsigned IM_MAME_PAUSE = 0; static inline constexpr unsigned IM_MAME_SAVESTATE = 1; - output_module(): m_machine(nullptr) { } - virtual ~output_module() = default; virtual void notify(const char *outname, int32_t value) = 0; - - void set_machine(running_machine *machine) { m_machine = machine; } - running_machine &machine() const { return *m_machine; } - -private: - running_machine *m_machine; }; #endif // MAME_OSD_OUTPUT_OUTPUT_MODULE_H diff --git a/src/osd/modules/output/win32_output.cpp b/src/osd/modules/output/win32_output.cpp index f7814d68dab..0d2d355b577 100644 --- a/src/osd/modules/output/win32_output.cpp +++ b/src/osd/modules/output/win32_output.cpp @@ -14,12 +14,12 @@ #include "win32_output.h" -// MAME headers -#include "emu.h" - #include "winmain.h" #include "winutil.h" +// MAME headers +#include "emu.h" + // standard windows headers #include <windows.h> @@ -71,7 +71,11 @@ class output_win32 : public osd_module, public output_module { public: output_win32() - : osd_module(OSD_OUTPUT_PROVIDER, "windows"), output_module(), m_output_hwnd(nullptr), m_clientlist(nullptr) + : osd_module(OSD_OUTPUT_PROVIDER, "windows") + , output_module() + , m_output_hwnd(nullptr) + , m_clientlist(nullptr) + , m_machine(nullptr) { } virtual ~output_win32() { } @@ -80,21 +84,23 @@ public: virtual void exit() override; // output_module - virtual void notify(const char *outname, int32_t value) override; - int create_window_class(); + running_machine &machine() { return *m_machine; } + LRESULT register_client(HWND hwnd, LPARAM id); LRESULT unregister_client(HWND hwnd, LPARAM id); LRESULT send_id_string(HWND hwnd, LPARAM id); private: + int create_window_class(); // our HWND HWND m_output_hwnd; // client list registered_client * m_clientlist; + running_machine * m_machine; }; @@ -104,6 +110,8 @@ private: int output_win32::init(osd_interface &osd, const osd_options &options) { + m_machine = &downcast<osd_common_t &>(osd).machine(); + int result; // reset globals diff --git a/src/osd/modules/render/aviwrite.h b/src/osd/modules/render/aviwrite.h index 015dcab4acf..4bf08b769db 100644 --- a/src/osd/modules/render/aviwrite.h +++ b/src/osd/modules/render/aviwrite.h @@ -6,15 +6,22 @@ // //============================================================ +#ifndef MAME_RENDER_AVIWRITE_H +#define MAME_RENDER_AVIWRITE_H + #pragma once -#ifndef __RENDER_AVIWRITE__ -#define __RENDER_AVIWRITE__ +#include "eminline.h" // attotime.h needs this - add it to attotime.h on the next emu.h update + +// emu +#include "attotime.h" +// lib/util #include "aviio.h" #include <string_view> + class running_machine; class avi_write @@ -49,4 +56,4 @@ private: attotime m_next_frame_time; }; -#endif // __RENDER_AVIWRITE__ +#endif // MAME_RENDER_AVIWRITE_H diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp index 6559c346f46..156b46464dd 100644 --- a/src/osd/modules/render/bgfx/chainmanager.cpp +++ b/src/osd/modules/render/bgfx/chainmanager.cpp @@ -44,9 +44,6 @@ using namespace rapidjson; -int32_t chain_manager::s_old_chain_selections[16] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -bool chain_manager::s_reinit_cookie = false; - chain_manager::screen_prim::screen_prim(render_primitive *prim) { m_prim = prim; @@ -61,8 +58,16 @@ chain_manager::screen_prim::screen_prim(render_primitive *prim) m_flags = prim->flags; } -chain_manager::chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, - slider_dirty_notifier& slider_notifier, uint16_t user_prescale, uint16_t max_prescale_size) +chain_manager::chain_manager( + running_machine& machine, + const osd_options& options, + texture_manager& textures, + target_manager& targets, + effect_manager& effects, + uint32_t window_index, + slider_dirty_notifier& slider_notifier, + uint16_t user_prescale, + uint16_t max_prescale_size) : m_machine(machine) , m_options(options) , m_textures(textures) @@ -79,23 +84,10 @@ chain_manager::chain_manager(running_machine& machine, osd_options& options, tex refresh_available_chains(); parse_chain_selections(options.bgfx_screen_chains()); init_texture_converters(); - - if (s_reinit_cookie) - { - for (uint32_t i = 0; i < std::size(s_old_chain_selections); i++) - { - set_current_chain(i, s_old_chain_selections[i]); - } - } } chain_manager::~chain_manager() { - for (uint32_t i = 0; i < std::size(s_old_chain_selections); i++) - { - s_old_chain_selections[i] = i < m_current_chain.size() ? m_current_chain[i] : -1; - } - s_reinit_cookie = true; destroy_chains(); } diff --git a/src/osd/modules/render/bgfx/chainmanager.h b/src/osd/modules/render/bgfx/chainmanager.h index e63fa9d6db5..eb30e6cc835 100644 --- a/src/osd/modules/render/bgfx/chainmanager.h +++ b/src/osd/modules/render/bgfx/chainmanager.h @@ -70,7 +70,7 @@ public: uint32_t m_flags = 0; }; - chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, + chain_manager(running_machine& machine, const osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, slider_dirty_notifier& slider_notifier, uint16_t user_prescale, uint16_t max_prescale_size); ~chain_manager(); @@ -79,7 +79,7 @@ public: // Getters running_machine& machine() const { return m_machine; } - osd_options& options() const { return m_options; } + const osd_options& options() const { return m_options; } texture_manager& textures() const { return m_textures; } target_manager& targets() const { return m_targets; } effect_manager& effects() const { return m_effects; } @@ -123,7 +123,7 @@ private: void process_screen_quad(uint32_t view, uint32_t screen, screen_prim &prim, osd_window& window); running_machine& m_machine; - osd_options& m_options; + const osd_options& m_options; texture_manager& m_textures; target_manager& m_targets; effect_manager& m_effects; @@ -146,9 +146,6 @@ private: std::vector<screen_prim> m_screen_prims; std::vector<uint8_t> m_palette_temp; - static int32_t s_old_chain_selections[16]; - static bool s_reinit_cookie; - static inline constexpr uint32_t CHAIN_NONE = 0; }; diff --git a/src/osd/modules/render/bgfx/effect.cpp b/src/osd/modules/render/bgfx/effect.cpp index a7f69e326f9..18b43cca9bf 100644 --- a/src/osd/modules/render/bgfx/effect.cpp +++ b/src/osd/modules/render/bgfx/effect.cpp @@ -13,40 +13,40 @@ #include "modules/osdmodule.h" #include "osdcore.h" -bgfx_effect::bgfx_effect(std::string name, uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<bgfx_uniform*> uniforms) - : m_name(name) +#include <utility> + + +bgfx_effect::bgfx_effect(std::string &&name, uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<std::unique_ptr<bgfx_uniform> > &uniforms) + : m_name(std::move(name)) , m_state(state) { m_program_handle = bgfx::createProgram(vertex_shader, fragment_shader, false); - for (int i = 0; i < uniforms.size(); i++) + for (auto &uniform : uniforms) { - if (m_uniforms[uniforms[i]->name()] != nullptr) + const auto existing = m_uniforms.find(uniform->name()); + if (existing != m_uniforms.end()) { - osd_printf_verbose("Uniform %s appears to be duplicated in one or more effects, please double-check the effect JSON files.\n", uniforms[i]->name()); - delete uniforms[i]; + osd_printf_verbose("Uniform %s appears to be duplicated in one or more effects, please double-check the effect JSON files.\n", uniform->name()); + uniform.reset(); continue; } - uniforms[i]->create(); - m_uniforms[uniforms[i]->name()] = uniforms[i]; + uniform->create(); + m_uniforms.emplace(uniform->name(), std::move(uniform)); } } bgfx_effect::~bgfx_effect() { - for (std::pair<std::string, bgfx_uniform*> uniform : m_uniforms) - { - delete uniform.second; - } m_uniforms.clear(); bgfx::destroy(m_program_handle); } void bgfx_effect::submit(int view, uint64_t blend) { - for (std::pair<std::string, bgfx_uniform*> uniform_pair : m_uniforms) + for (auto &[name, uniform] : m_uniforms) { - (uniform_pair.second)->upload(); + uniform->upload(); } const uint64_t final_state = (blend != ~0ULL) ? ((m_state & ~BGFX_STATE_BLEND_MASK) | blend) : m_state; @@ -55,8 +55,8 @@ void bgfx_effect::submit(int view, uint64_t blend) bgfx::submit(view, m_program_handle); } -bgfx_uniform* bgfx_effect::uniform(std::string name) +bgfx_uniform* bgfx_effect::uniform(const std::string &name) { - auto iter = m_uniforms.find(name); - return iter != m_uniforms.end() ? iter->second : nullptr; + const auto iter = m_uniforms.find(name); + return (iter != m_uniforms.end()) ? iter->second.get() : nullptr; } diff --git a/src/osd/modules/render/bgfx/effect.h b/src/osd/modules/render/bgfx/effect.h index 6dd88b3585c..07646e6302e 100644 --- a/src/osd/modules/render/bgfx/effect.h +++ b/src/osd/modules/render/bgfx/effect.h @@ -6,34 +6,36 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_EFFECT_H +#define MAME_RENDER_BGFX_EFFECT_H -#ifndef __DRAWBGFX_EFFECT__ -#define __DRAWBGFX_EFFECT__ +#pragma once #include <bgfx/bgfx.h> -#include <vector> #include <map> +#include <memory> #include <string> +#include <vector> + class bgfx_uniform; class bgfx_effect { public: - bgfx_effect(std::string name, uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<bgfx_uniform*> uniforms); + bgfx_effect(std::string &&name, uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<std::unique_ptr<bgfx_uniform> > &uniforms); ~bgfx_effect(); void submit(int view, uint64_t blend = ~0ULL); - bgfx_uniform *uniform(std::string name); - bool is_valid() { return m_program_handle.idx != bgfx::kInvalidHandle; } + bgfx_uniform *uniform(const std::string &name); + bool is_valid() const { return m_program_handle.idx != bgfx::kInvalidHandle; } private: std::string m_name; uint64_t m_state; bgfx::ProgramHandle m_program_handle; - std::map<std::string, bgfx_uniform*> m_uniforms; + std::map<std::string, std::unique_ptr<bgfx_uniform> > m_uniforms; }; -#endif // __DRAWBGFX_EFFECT__ +#endif // MAME_RENDER_BGFX_EFFECT_H diff --git a/src/osd/modules/render/bgfx/effectmanager.cpp b/src/osd/modules/render/bgfx/effectmanager.cpp index 18991b3807e..e5e5d1698f6 100644 --- a/src/osd/modules/render/bgfx/effectmanager.cpp +++ b/src/osd/modules/render/bgfx/effectmanager.cpp @@ -11,8 +11,11 @@ #include "effectmanager.h" -#include "effectreader.h" #include "effect.h" +#include "effectreader.h" +#include "shadermanager.h" + +#include "path.h" #include "osdfile.h" #include "modules/lib/osdobj_common.h" @@ -25,16 +28,18 @@ #include <bgfx/bgfx.h> -static bool prepare_effect_document(std::string &name, osd_options &options, rapidjson::Document &document) +#include <utility> + + +static bool prepare_effect_document(const std::string &name, const 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)) { - full_name = full_name + ".json"; + full_name += ".json"; } - std::string path = util::string_format("%s" PATH_SEPARATOR "effects" PATH_SEPARATOR, options.bgfx_path()); - path += full_name; + const std::string path = util::path_concat(options.bgfx_path(), "effects", full_name); bx::FileReader reader; if (!bx::open(&reader, path.c_str())) @@ -43,49 +48,55 @@ static bool prepare_effect_document(std::string &name, osd_options &options, rap return false; } + const int32_t size = bx::getSize(&reader); + std::unique_ptr<char []> data(new (std::nothrow) char [size + 1]); + if (!data) + { + osd_printf_error("Out of memory reading effect file %s\n", path); + bx::close(&reader); + return false; + } + bx::ErrorAssert err; - int32_t size (bx::getSize(&reader)); - char* data = new char[size + 1]; - bx::read(&reader, reinterpret_cast<void*>(data), size, &err); + bx::read(&reader, reinterpret_cast<void*>(data.get()), size, &err); bx::close(&reader); data[size] = 0; - document.Parse<rapidjson::kParseCommentsFlag>(data); - - delete [] data; + document.Parse<rapidjson::kParseCommentsFlag>(data.get()); + data.reset(); if (document.HasParseError()) { std::string error(rapidjson::GetParseError_En(document.GetParseError())); - osd_printf_error("Unable to parse effect %s. Errors returned:\n", path); - osd_printf_error("%s\n", error); + osd_printf_error("Unable to parse effect %s. Errors returned:\n%s\n", path, error); return false; } return true; } + +// keep constructor and destructor out-of-line so the header works with forward declarations + +effect_manager::effect_manager(shader_manager& shaders) : m_shaders(shaders) +{ +} + effect_manager::~effect_manager() { - for (std::pair<std::string, bgfx_effect*> effect : m_effects) - { - delete effect.second; - } - m_effects.clear(); + // the map will automatically dispose of the effects } -bgfx_effect* effect_manager::get_or_load_effect(osd_options &options, std::string name) +bgfx_effect* effect_manager::get_or_load_effect(const osd_options &options, const std::string &name) { - std::map<std::string, bgfx_effect*>::iterator iter = m_effects.find(name); + const auto iter = m_effects.find(name); if (iter != m_effects.end()) - { - return iter->second; - } + return iter->second.get(); return load_effect(options, name); } -bgfx_effect* effect_manager::load_effect(osd_options &options, std::string name) +bgfx_effect* effect_manager::load_effect(const osd_options &options, const std::string &name) { rapidjson::Document document; if (!prepare_effect_document(name, options, document)) @@ -93,20 +104,18 @@ bgfx_effect* effect_manager::load_effect(osd_options &options, std::string name) return nullptr; } - bgfx_effect* effect = effect_reader::read_from_value(name, document, "Effect '" + name + "': ", options, m_shaders); + std::unique_ptr<bgfx_effect> effect = effect_reader::read_from_value(name, document, "Effect '" + name + "': ", options, m_shaders); - if (effect == nullptr) + if (!effect) { osd_printf_error("Unable to load effect %s\n", name); return nullptr; } - m_effects[name] = effect; - - return effect; + return m_effects.emplace(name, std::move(effect)).first->second.get(); } -bool effect_manager::validate_effect(osd_options &options, std::string name) +bool effect_manager::validate_effect(const osd_options &options, const std::string &name) { rapidjson::Document document; if (!prepare_effect_document(name, options, document)) diff --git a/src/osd/modules/render/bgfx/effectmanager.h b/src/osd/modules/render/bgfx/effectmanager.h index 5d8bf3f5c93..697d468dc5c 100644 --- a/src/osd/modules/render/bgfx/effectmanager.h +++ b/src/osd/modules/render/bgfx/effectmanager.h @@ -9,34 +9,35 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_EFFECTMANAGER_H +#define MAME_RENDER_BGFX_EFFECTMANAGER_H -#ifndef __DRAWBGFX_EFFECT_MANAGER__ -#define __DRAWBGFX_EFFECT_MANAGER__ +#pragma once #include <map> +#include <memory> #include <string> -#include <bgfx/bgfx.h> - -#include "shadermanager.h" class bgfx_effect; +class osd_options; +class shader_manager; -class effect_manager { +class effect_manager +{ public: - effect_manager(shader_manager& shaders) : m_shaders(shaders) { } + effect_manager(shader_manager& shaders); ~effect_manager(); // Getters - bgfx_effect* get_or_load_effect(osd_options &options, std::string name); - static bool validate_effect(osd_options &options, std::string name); + bgfx_effect* get_or_load_effect(const osd_options &options, const std::string &name); + static bool validate_effect(const osd_options &options, const std::string &name); private: - bgfx_effect* load_effect(osd_options& options, std::string name); + bgfx_effect* load_effect(const osd_options &options, const std::string &name); - shader_manager& m_shaders; - std::map<std::string, bgfx_effect*> m_effects; + shader_manager &m_shaders; + std::map<std::string, std::unique_ptr<bgfx_effect> > m_effects; }; -#endif // __DRAWBGFX_EFFECT_MANAGER__ +#endif // MAME_RENDER_BGFX_EFFECTMANAGER_H diff --git a/src/osd/modules/render/bgfx/effectreader.cpp b/src/osd/modules/render/bgfx/effectreader.cpp index 9840fb58dfd..befdc598537 100644 --- a/src/osd/modules/render/bgfx/effectreader.cpp +++ b/src/osd/modules/render/bgfx/effectreader.cpp @@ -8,80 +8,79 @@ #include "effectreader.h" -#include "effect.h" #include "blendreader.h" -#include "depthreader.h" #include "cullreader.h" -#include "writereader.h" +#include "depthreader.h" +#include "effect.h" #include "shadermanager.h" -#include "uniformreader.h" #include "uniform.h" +#include "uniformreader.h" +#include "writereader.h" -bgfx_effect *effect_reader::read_from_value(std::string name, const Value& value, const std::string &prefix, osd_options &options, shader_manager& shaders) +#include <utility> + + +std::unique_ptr<bgfx_effect> effect_reader::read_from_value( + const std::string &name, + const Value &value, + const std::string &prefix, + const osd_options &options, + shader_manager &shaders) { 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; + std::vector<std::unique_ptr<bgfx_uniform> > uniforms; if (!get_base_effect_data(value, prefix, flags, vertex_name, fragment_name, uniforms)) { return nullptr; } + bgfx::ShaderHandle vertex_shader = BGFX_INVALID_HANDLE; + bgfx::ShaderHandle fragment_shader = BGFX_INVALID_HANDLE; + 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(name, flags, vertex_shader, fragment_shader, uniforms); - if (effect->is_valid()) - { - return effect; - } - - delete effect; + std::unique_ptr<bgfx_effect> effect(new bgfx_effect(std::string(name), flags, vertex_shader, fragment_shader, uniforms)); + if (!effect->is_valid()) + return nullptr; - return nullptr; + return effect; } -bool effect_reader::validate_value(const Value& value, const std::string &prefix, osd_options &options) +bool effect_reader::validate_value(const Value& value, const std::string &prefix, const 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; + std::vector<std::unique_ptr<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, const std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name, - std::vector<bgfx_uniform *> &uniforms) +bool effect_reader::get_base_effect_data( + const Value& value, + const std::string &prefix, + uint64_t &flags, + std::string &vertex_name, + std::string &fragment_name, + std::vector<std::unique_ptr<bgfx_uniform> > &uniforms) { if (!validate_parameters(value, prefix)) { @@ -101,12 +100,12 @@ bool effect_reader::get_base_effect_data(const Value& value, const std::string & 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) + "]: "); - if (uniform == nullptr) + auto uniform = uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: "); + if (!uniform) { return false; } - uniforms.push_back(uniform); + uniforms.emplace_back(std::move(uniform)); } vertex_name = value["vertex"].GetString(); @@ -127,8 +126,14 @@ bool effect_reader::get_base_effect_data(const Value& value, const std::string & 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) +bool effect_reader::get_shader_data( + const Value &value, + const 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) @@ -145,14 +150,6 @@ bool effect_reader::get_shader_data(const Value& value, osd_options &options, sh 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, const std::string &prefix) { if (!READER_CHECK(value.HasMember("depth"), "%sMust have object value 'depth' (what are our Z-buffer settings?)\n", prefix)) return false; diff --git a/src/osd/modules/render/bgfx/effectreader.h b/src/osd/modules/render/bgfx/effectreader.h index 5819de60b01..db590e5eeb3 100644 --- a/src/osd/modules/render/bgfx/effectreader.h +++ b/src/osd/modules/render/bgfx/effectreader.h @@ -15,26 +15,28 @@ #include <bgfx/bgfx.h> +#include <memory> #include <string> #include <vector> + class bgfx_effect; class bgfx_uniform; class osd_options; class shader_manager; + class effect_reader : public state_reader { public: - static bgfx_effect *read_from_value(std::string name, const Value& value, const std::string &prefix, osd_options &options, shader_manager& shaders); - static bool validate_value(const Value& value, const std::string &prefix, osd_options &options); + static std::unique_ptr<bgfx_effect> read_from_value(const std::string &name, const Value& value, const std::string &prefix, const osd_options &options, shader_manager& shaders); + static bool validate_value(const Value& value, const std::string &prefix, const osd_options &options); private: static bool get_base_effect_data(const Value& value, const 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::vector<std::unique_ptr<bgfx_uniform> > &uniforms); + static bool get_shader_data(const Value& value, const 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, const std::string &prefix); }; diff --git a/src/osd/modules/render/bgfx/shadermanager.cpp b/src/osd/modules/render/bgfx/shadermanager.cpp index 7d4ca4ea259..763a744e4aa 100644 --- a/src/osd/modules/render/bgfx/shadermanager.cpp +++ b/src/osd/modules/render/bgfx/shadermanager.cpp @@ -16,11 +16,10 @@ #include "osdfile.h" #include "modules/lib/osdobj_common.h" +#include <bx/file.h> #include <bx/math.h> #include <bx/readerwriter.h> -#include <bx/file.h> -#include <bgfx/bgfx.h> shader_manager::~shader_manager() { @@ -31,7 +30,7 @@ shader_manager::~shader_manager() m_shaders.clear(); } -bgfx::ShaderHandle shader_manager::get_or_load_shader(osd_options &options, const std::string &name) +bgfx::ShaderHandle shader_manager::get_or_load_shader(const osd_options &options, const std::string &name) { std::map<std::string, bgfx::ShaderHandle>::iterator iter = m_shaders.find(name); if (iter != m_shaders.end()) @@ -48,7 +47,7 @@ bgfx::ShaderHandle shader_manager::get_or_load_shader(osd_options &options, cons return handle; } -bgfx::ShaderHandle shader_manager::load_shader(osd_options &options, const std::string &name) +bgfx::ShaderHandle shader_manager::load_shader(const osd_options &options, const std::string &name) { std::string shader_path = make_path_string(options, name); const bgfx::Memory* mem = load_mem(shader_path + name + ".bin"); @@ -60,7 +59,7 @@ bgfx::ShaderHandle shader_manager::load_shader(osd_options &options, const std:: return BGFX_INVALID_HANDLE; } -bool shader_manager::is_shader_present(osd_options &options, const std::string &name) +bool shader_manager::is_shader_present(const osd_options &options, const std::string &name) { std::string shader_path = make_path_string(options, name); std::string file_name = shader_path + name + ".bin"; @@ -80,7 +79,7 @@ bool shader_manager::is_shader_present(osd_options &options, const std::string & return false; } -std::string shader_manager::make_path_string(osd_options &options, const std::string &name) +std::string shader_manager::make_path_string(const osd_options &options, const std::string &name) { std::string shader_path(options.bgfx_path()); shader_path += PATH_SEPARATOR "shaders" PATH_SEPARATOR; diff --git a/src/osd/modules/render/bgfx/shadermanager.h b/src/osd/modules/render/bgfx/shadermanager.h index 604fbd7e3ac..12ac739d35a 100644 --- a/src/osd/modules/render/bgfx/shadermanager.h +++ b/src/osd/modules/render/bgfx/shadermanager.h @@ -22,21 +22,23 @@ class osd_options; -class shader_manager { + +class shader_manager +{ public: shader_manager() { } ~shader_manager(); // Getters - bgfx::ShaderHandle get_or_load_shader(osd_options &options, const std::string &name); - static bgfx::ShaderHandle load_shader(osd_options &options, const std::string &name); - static bool is_shader_present(osd_options &options, const std::string &name); + bgfx::ShaderHandle get_or_load_shader(const osd_options &options, const std::string &name); + static bgfx::ShaderHandle load_shader(const osd_options &options, const std::string &name); + static bool is_shader_present(const osd_options &options, const std::string &name); private: - static std::string make_path_string(osd_options &options, const std::string &name); + static std::string make_path_string(const osd_options &options, const std::string &name); static const bgfx::Memory* load_mem(const std::string &name); - std::map<std::string, bgfx::ShaderHandle> m_shaders; + std::map<std::string, bgfx::ShaderHandle> m_shaders; }; #endif // MAME_RENDER_BGFX_SHADERMANAGER_H diff --git a/src/osd/modules/render/bgfx/uniformreader.cpp b/src/osd/modules/render/bgfx/uniformreader.cpp index 002e6b3959a..d1eab8098c7 100644 --- a/src/osd/modules/render/bgfx/uniformreader.cpp +++ b/src/osd/modules/render/bgfx/uniformreader.cpp @@ -10,6 +10,9 @@ #include "uniform.h" +#include <cstdlib> + + const uniform_reader::string_to_enum uniform_reader::TYPE_NAMES[uniform_reader::TYPE_COUNT] = { { "int", bgfx::UniformType::Sampler }, { "vec4", bgfx::UniformType::Vec4 }, @@ -17,7 +20,7 @@ const uniform_reader::string_to_enum uniform_reader::TYPE_NAMES[uniform_reader:: { "mat4", bgfx::UniformType::Mat4 } }; -bgfx_uniform* uniform_reader::read_from_value(const Value& value, const std::string &prefix) +std::unique_ptr<bgfx_uniform> uniform_reader::read_from_value(const Value& value, const std::string &prefix) { if (!validate_parameters(value, prefix)) { @@ -31,23 +34,18 @@ bgfx_uniform* uniform_reader::read_from_value(const Value& value, const std::str const Value& value_array = value["values"]; const size_t array_size = value_array.Size() * sizeof(float); - const size_t alloc_size = (type_size > array_size) ? type_size : array_size; - auto* data = reinterpret_cast<float*>(new char[alloc_size]); + auto* data = reinterpret_cast<float*>(std::malloc(std::max(type_size, array_size))); unsigned int index = 0; for (; index < type_size / 4 && index < value_array.Size(); index++) - { data[index] = float(value_array[index].GetDouble()); - } for (; index < type_size / 4; index++) - { data[index] = 0.0f; - } - bgfx_uniform* uniform = new bgfx_uniform(name, type); - uniform->set((void*)data, type_size); - delete [] data; + auto uniform = std::make_unique<bgfx_uniform>(name, type); + uniform->set(data, type_size); + std::free(data); return uniform; } diff --git a/src/osd/modules/render/bgfx/uniformreader.h b/src/osd/modules/render/bgfx/uniformreader.h index e35fa4cfad0..ebb3a485d63 100644 --- a/src/osd/modules/render/bgfx/uniformreader.h +++ b/src/osd/modules/render/bgfx/uniformreader.h @@ -13,12 +13,16 @@ #include "statereader.h" +#include <memory> +#include <string> + + class bgfx_uniform; class uniform_reader : public state_reader { public: - static bgfx_uniform* read_from_value(const Value& value, const std::string &prefix); + static std::unique_ptr<bgfx_uniform> read_from_value(const Value& value, const std::string &prefix); private: static bool validate_parameters(const Value& value, const std::string &prefix); diff --git a/src/osd/modules/render/bgfx/view.cpp b/src/osd/modules/render/bgfx/view.cpp index 6935e19bca7..3a731fc71f8 100644 --- a/src/osd/modules/render/bgfx/view.cpp +++ b/src/osd/modules/render/bgfx/view.cpp @@ -13,9 +13,7 @@ #include "target.h" void bgfx_view::update() { - std::shared_ptr<osd_window> win = m_renderer->assert_window(); - - const uint32_t window_index = win->index(); + const uint32_t window_index = m_renderer->window().index(); const uint32_t width = m_renderer->get_window_width(window_index); const uint32_t height = m_renderer->get_window_height(window_index); diff --git a/src/osd/modules/render/bgfx/view.h b/src/osd/modules/render/bgfx/view.h index 577663ea525..b257eb12ea4 100644 --- a/src/osd/modules/render/bgfx/view.h +++ b/src/osd/modules/render/bgfx/view.h @@ -4,12 +4,14 @@ #pragma once #include "window.h" + #include <climits> class renderer_bgfx; class bgfx_target; -class bgfx_view { +class bgfx_view +{ public: bgfx_view(renderer_bgfx *renderer, uint32_t index, bgfx_target *backbuffer, std::vector<uint32_t> &seen_views) : m_renderer(renderer) diff --git a/src/osd/modules/render/blit13.h b/src/osd/modules/render/blit13.ipp index 1ac485bab8d..1ac485bab8d 100644 --- a/src/osd/modules/render/blit13.h +++ b/src/osd/modules/render/blit13.ipp diff --git a/src/osd/modules/render/d3d/d3dcomm.h b/src/osd/modules/render/d3d/d3dcomm.h index 2d7548a242a..846d9dac791 100644 --- a/src/osd/modules/render/d3d/d3dcomm.h +++ b/src/osd/modules/render/d3d/d3dcomm.h @@ -6,8 +6,22 @@ // //============================================================ -#ifndef __WIN_D3DCOMM__ -#define __WIN_D3DCOMM__ +#ifndef MAME_RENDER_D3D_D3DCOMM_H +#define MAME_RENDER_D3D_D3DCOMM_H + +#pragma once + +// lib/util +#include "bitmap.h" + +#include <windows.h> +#include <d3d9.h> +#include <wrl/client.h> + +#include <cstring> +#include <memory> +#include <vector> + //============================================================ // CONSTANTS @@ -60,10 +74,7 @@ public: class d3d_texture_manager { public: - d3d_texture_manager(): m_renderer(nullptr), m_yuv_format(), m_texture_caps(0), m_texture_max_aspect(0), m_texture_max_width(0), m_texture_max_height(0), m_default_texture(nullptr) - { } - - d3d_texture_manager(renderer_d3d9 *d3d); + d3d_texture_manager(renderer_d3d9 &d3d, IDirect3D9 *d3dobj); void update_textures(); @@ -82,12 +93,12 @@ public: texture_info * get_default_texture() const { return m_default_texture; } - renderer_d3d9 * get_d3d() const { return m_renderer; } + renderer_d3d9 & get_d3d() const { return m_renderer; } - std::vector<std::unique_ptr<texture_info>> m_texture_list; // list of active textures + std::vector<std::unique_ptr<texture_info> > m_texture_list; // list of active textures private: - renderer_d3d9 * m_renderer; + renderer_d3d9 & m_renderer; D3DFORMAT m_yuv_format; // format to use for YUV textures DWORD m_texture_caps; // textureCaps field @@ -104,7 +115,7 @@ private: class texture_info { public: - texture_info(d3d_texture_manager *manager, const render_texinfo *texsource, int prescale, uint32_t flags); + texture_info(d3d_texture_manager &manager, const render_texinfo *texsource, int prescale, uint32_t flags); ~texture_info(); render_texinfo & get_texinfo() { return m_texinfo; } @@ -125,15 +136,16 @@ public: int get_cur_frame() const { return m_cur_frame; } - IDirect3DTexture9 * get_tex() const { return m_d3dtex; } - IDirect3DSurface9 * get_surface() const { return m_d3dsurface; } - IDirect3DTexture9 * get_finaltex() const { return m_d3dfinaltex; } + IDirect3DTexture9 * get_finaltex() const { return m_d3dfinaltex.Get(); } vec2f & get_uvstart() { return m_start; } vec2f & get_uvstop() { return m_stop; } vec2f & get_rawdims() { return m_rawdims; } private: + using IDirect3DTexture9Ptr = Microsoft::WRL::ComPtr<IDirect3DTexture9>; + using IDirect3DSurface9Ptr = Microsoft::WRL::ComPtr<IDirect3DSurface9>; + void prescale(); void compute_size(int texwidth, int texheight); void compute_size_subroutine(int texwidth, int texheight, int* p_width, int* p_height); @@ -145,23 +157,23 @@ private: inline void copyline_yuy16_to_uyvy(uint16_t *dst, const uint16_t *src, int width, const rgb_t *palette); inline void copyline_yuy16_to_argb(uint32_t *dst, const uint16_t *src, int width, const rgb_t *palette); - d3d_texture_manager * m_texture_manager; // texture manager pointer + d3d_texture_manager & m_texture_manager; // texture manager pointer - renderer_d3d9 * m_renderer; // renderer pointer + renderer_d3d9 & m_renderer; // renderer pointer - uint32_t m_hash; // hash value for the texture - uint32_t m_flags; // rendering flags + const uint32_t m_hash; // hash value for the texture + const uint32_t m_flags; // rendering flags render_texinfo m_texinfo; // copy of the texture info + const int m_type; // what type of texture are we? vec2f m_start; // beggining UV coordinates vec2f m_stop; // ending UV coordinates vec2f m_rawdims; // raw dims of the texture - int m_type; // what type of texture are we? int m_xprescale, m_yprescale; // X/Y prescale factor int m_xborderpix, m_yborderpix; // X/Y border pixels int m_cur_frame; // what is our current frame? - IDirect3DTexture9 * m_d3dtex; // Direct3D texture pointer - IDirect3DSurface9 * m_d3dsurface; // Direct3D offscreen plain surface pointer - IDirect3DTexture9 * m_d3dfinaltex; // Direct3D final (post-scaled) texture + IDirect3DTexture9Ptr m_d3dtex; // Direct3D texture pointer + IDirect3DSurface9Ptr m_d3dsurface; // Direct3D offscreen plain surface pointer + IDirect3DTexture9Ptr m_d3dfinaltex; // Direct3D final (post-scaled) texture }; /* poly_info holds information about a single polygon/d3d primitive */ @@ -227,24 +239,14 @@ class d3d_render_target { public: // construction/destruction - d3d_render_target(): target_width(0), target_height(0), width(0), height(0), screen_index(0), bloom_count(0) + d3d_render_target() + : target_width(0) + , target_height(0) + , width(0) + , height(0) + , screen_index(0) + , bloom_count(0) { - for (int index = 0; index < MAX_BLOOM_COUNT; index++) - { - bloom_texture[index] = nullptr; - bloom_surface[index] = nullptr; - } - - for (int index = 0; index < 2; index++) - { - source_texture[index] = nullptr; - source_surface[index] = nullptr; - target_texture[index] = nullptr; - target_surface[index] = nullptr; - } - - cache_texture = nullptr; - cache_surface = nullptr; } ~d3d_render_target(); @@ -262,20 +264,20 @@ public: int screen_index; - IDirect3DSurface9 *target_surface[2]; - IDirect3DTexture9 *target_texture[2]; - IDirect3DSurface9 *source_surface[2]; - IDirect3DTexture9 *source_texture[2]; + Microsoft::WRL::ComPtr<IDirect3DSurface9> target_surface[2]; + Microsoft::WRL::ComPtr<IDirect3DTexture9> target_texture[2]; + Microsoft::WRL::ComPtr<IDirect3DSurface9> source_surface[2]; + Microsoft::WRL::ComPtr<IDirect3DTexture9> source_texture[2]; - IDirect3DSurface9 *cache_surface; - IDirect3DTexture9 *cache_texture; + Microsoft::WRL::ComPtr<IDirect3DSurface9> cache_surface; + Microsoft::WRL::ComPtr<IDirect3DTexture9> cache_texture; - IDirect3DSurface9 *bloom_surface[MAX_BLOOM_COUNT]; - IDirect3DTexture9 *bloom_texture[MAX_BLOOM_COUNT]; + Microsoft::WRL::ComPtr<IDirect3DSurface9> bloom_surface[MAX_BLOOM_COUNT]; + Microsoft::WRL::ComPtr<IDirect3DTexture9> bloom_texture[MAX_BLOOM_COUNT]; float bloom_dims[MAX_BLOOM_COUNT][2]; int bloom_count; }; -#endif +#endif // MAME_RENDER_D3D_D3DCOMM_H diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 8c59649f64a..85313f3e9ec 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -50,8 +50,6 @@ class movie_recorder public: movie_recorder(running_machine& machine, renderer_d3d9 *d3d, int width, int height) : m_initialized(false), m_d3d(d3d), m_width(width), m_height(height) - , m_sys_texture(nullptr), m_sys_surface(nullptr) - , m_vid_texture(nullptr), m_vid_surface(nullptr) { HRESULT result; @@ -82,17 +80,6 @@ public: ~movie_recorder() { - if (m_sys_texture != nullptr) - m_sys_texture->Release(); - - if (m_sys_surface != nullptr) - m_sys_surface->Release(); - - if (m_vid_texture != nullptr) - m_vid_texture->Release(); - - if (m_vid_surface != nullptr) - m_vid_surface->Release(); } void record(const char *name) @@ -109,7 +96,7 @@ public: return; // copy the frame from video memory, where it is not accessible, to system memory - HRESULT result = m_d3d->get_device()->GetRenderTargetData(m_vid_surface, m_sys_surface); + HRESULT result = m_d3d->get_device()->GetRenderTargetData(m_vid_surface.Get(), m_sys_surface.Get()); if (FAILED(result)) return; @@ -144,7 +131,7 @@ public: m_avi_writer->audio_frame(buffer, samples_this_frame); } - IDirect3DSurface9 * target_surface() { return m_vid_surface; } + IDirect3DSurface9 * target_surface() { return m_vid_surface.Get(); } private: bool m_initialized; @@ -156,10 +143,10 @@ private: bitmap_rgb32 m_frame; int m_width; int m_height; - IDirect3DTexture9 * m_sys_texture; // texture in system memory - IDirect3DSurface9 * m_sys_surface; // surface in system memory - IDirect3DTexture9 * m_vid_texture; // texture in video memory - IDirect3DSurface9 * m_vid_surface; // surface in video memory + Microsoft::WRL::ComPtr<IDirect3DTexture9> m_sys_texture; // texture in system memory + Microsoft::WRL::ComPtr<IDirect3DSurface9> m_sys_surface; // surface in system memory + Microsoft::WRL::ComPtr<IDirect3DTexture9> m_vid_texture; // texture in video memory + Microsoft::WRL::ComPtr<IDirect3DSurface9> m_vid_surface; // surface in video memory }; @@ -168,7 +155,6 @@ private: //============================================================ shaders::shaders() : - d3dintf(nullptr), machine(nullptr), d3d(nullptr), post_fx_enable(false), @@ -182,37 +168,12 @@ shaders::shaders() : lut_texture(nullptr), ui_lut_texture(nullptr), options(nullptr), - black_surface(nullptr), - black_texture(nullptr), recording_movie(false), render_snap(false), - snap_copy_target(nullptr), - snap_copy_texture(nullptr), - snap_target(nullptr), - snap_texture(nullptr), snap_width(0), snap_height(0), initialized(false), - backbuffer(nullptr), curr_effect(nullptr), - default_effect(nullptr), - ui_effect(nullptr), - ui_wrap_effect(nullptr), - vector_buffer_effect(nullptr), - prescale_effect(nullptr), - prescale_point_effect(nullptr), - post_effect(nullptr), - distortion_effect(nullptr), - scanline_effect(nullptr), - focus_effect(nullptr), - phosphor_effect(nullptr), - deconverge_effect(nullptr), - color_effect(nullptr), - ntsc_effect(nullptr), - bloom_effect(nullptr), - downsample_effect(nullptr), - vector_effect(nullptr), - chroma_effect(nullptr), diffuse_texture(nullptr), curr_texture(nullptr), curr_render_target(nullptr), @@ -229,12 +190,7 @@ shaders::shaders() : shaders::~shaders() { - for (slider* slider : internal_sliders) - { - delete slider; - } - - if (options != nullptr) + if (options && (&last_options != options)) { delete options; options = nullptr; @@ -251,11 +207,9 @@ void shaders::save_snapshot() if (!enabled()) return; - auto win = d3d->assert_window(); - int width = snap_width; int height = snap_height; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(width, height); } @@ -296,8 +250,7 @@ void shaders::record_movie() return; } - auto win = d3d->assert_window(); - osd_dim wdim = win->get_size(); + osd_dim wdim = d3d->window().get_size(); recorder = std::make_unique<movie_recorder>(*machine, d3d, wdim.width(), wdim.height()); recorder->record(downcast<windows_options &>(machine->options()).d3d_hlsl_write()); @@ -330,11 +283,9 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) if (!enabled()) return; - auto win = d3d->assert_window(); - int width = snap_width; int height = snap_height; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(width, height); } @@ -344,7 +295,7 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) return; // copy the texture - HRESULT result = d3d->get_device()->GetRenderTargetData(surface, snap_copy_target); + HRESULT result = d3d->get_device()->GetRenderTargetData(surface, snap_copy_target.Get()); if (FAILED(result)) return; @@ -385,29 +336,10 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during texture UnlockRect call\n", result); - if (snap_texture != nullptr) - { - snap_texture->Release(); - snap_texture = nullptr; - } - - if (snap_target != nullptr) - { - snap_target->Release(); - snap_target = nullptr; - } - - if (snap_copy_texture != nullptr) - { - snap_copy_texture->Release(); - snap_copy_texture = nullptr; - } - - if (snap_copy_target != nullptr) - { - snap_copy_target->Release(); - snap_copy_target = nullptr; - } + snap_texture.Reset(); + snap_target.Reset(); + snap_copy_texture.Reset(); + snap_copy_target.Reset(); } @@ -473,7 +405,7 @@ void shaders::set_filter(bool filter_screens) // shaders::init //============================================================ -bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer) +bool shaders::init(IDirect3D9 *d3dobj, running_machine *machine, renderer_d3d9 *renderer) { osd_printf_verbose("Direct3D: Initialize HLSL\n"); @@ -505,9 +437,7 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r return false; } - d3dintf->post_fx_available = true; - - this->d3dintf = d3dintf; + this->d3dobj = d3dobj; this->machine = machine; this->d3d = renderer; @@ -518,19 +448,18 @@ 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 = new hlsl_options; - this->options->params_init = false; - - // copy last options if initialized if (last_options.params_init) { + // copy last options if initialized osd_printf_verbose("Direct3D: First restore options\n"); options = &last_options; } - - // read options if not initialized - if (!options->params_init) + else { + // read options if not initialized + options = new hlsl_options; + options->params_init = false; + strncpy(options->shadow_mask_texture, winoptions.screen_shadow_mask_texture(), sizeof(options->shadow_mask_texture)); options->shadow_mask_tile_mode = winoptions.screen_shadow_mask_tile_mode(); options->shadow_mask_alpha = winoptions.screen_shadow_mask_alpha(); @@ -612,6 +541,7 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r osd_printf_verbose("Direct3D: First store options\n"); last_options = *options; + delete options; options = &last_options; } @@ -786,7 +716,7 @@ int shaders::create_resources() return 1; } black_texture->GetSurfaceLevel(0, &black_surface); - result = d3d->get_device()->SetRenderTarget(0, black_surface); + result = d3d->get_device()->SetRenderTarget(0, black_surface.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); @@ -794,7 +724,7 @@ int shaders::create_resources() if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result); - result = d3d->get_device()->SetRenderTarget(0, backbuffer); + result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); @@ -819,7 +749,7 @@ int shaders::create_resources() texture.seqid = 0; // now create it (no prescale, no wrap) - auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); shadow_texture = tex.get(); d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } @@ -842,7 +772,7 @@ int shaders::create_resources() texture.seqid = 0; // now create it (no prescale, no wrap) - auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); lut_texture = tex.get(); d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } @@ -865,83 +795,66 @@ int shaders::create_resources() texture.seqid = 0; // now create it (no prescale, no wrap) - auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); ui_lut_texture = tex.get(); d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } const char *fx_dir = downcast<windows_options &>(machine->options()).screen_post_fx_dir(); - default_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir); - ui_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir); - ui_wrap_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir); - vector_buffer_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir); - post_effect = new effect(this, d3d->get_device(), "post.fx", fx_dir); - distortion_effect = new effect(this, d3d->get_device(), "distortion.fx", fx_dir); - prescale_effect = new effect(this, d3d->get_device(), "prescale.fx", fx_dir); - prescale_point_effect = new effect(this, d3d->get_device(), "prescale.fx", fx_dir); - phosphor_effect = new effect(this, d3d->get_device(), "phosphor.fx", fx_dir); - focus_effect = new effect(this, d3d->get_device(), "focus.fx", fx_dir); - scanline_effect = new effect(this, d3d->get_device(), "scanline.fx", fx_dir); - deconverge_effect = new effect(this, d3d->get_device(), "deconverge.fx", fx_dir); - color_effect = new effect(this, d3d->get_device(), "color.fx", fx_dir); - ntsc_effect = new effect(this, d3d->get_device(), "ntsc.fx", fx_dir); - bloom_effect = new effect(this, d3d->get_device(), "bloom.fx", fx_dir); - downsample_effect = new effect(this, d3d->get_device(), "downsample.fx", fx_dir); - vector_effect = new effect(this, d3d->get_device(), "vector.fx", fx_dir); - chroma_effect = new effect(this, d3d->get_device(), "chroma.fx", fx_dir); - - if (!default_effect->is_valid() || - !ui_effect->is_valid() || - !ui_wrap_effect->is_valid() || - !vector_buffer_effect->is_valid() || - !post_effect->is_valid() || - !distortion_effect->is_valid() || - !prescale_effect->is_valid() || - !prescale_point_effect->is_valid() || - !phosphor_effect->is_valid() || - !focus_effect->is_valid() || - !scanline_effect->is_valid() || - !deconverge_effect->is_valid() || - !color_effect->is_valid() || - !ntsc_effect->is_valid() || - !bloom_effect->is_valid() || - !downsample_effect->is_valid() || - !vector_effect->is_valid() || - !chroma_effect->is_valid()) - { - return 1; - } + default_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir); + ui_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir); + ui_wrap_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir); + vector_buffer_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir); + post_effect = std::make_unique<effect>(this, d3d->get_device(), "post.fx", fx_dir); + distortion_effect = std::make_unique<effect>(this, d3d->get_device(), "distortion.fx", fx_dir); + prescale_effect = std::make_unique<effect>(this, d3d->get_device(), "prescale.fx", fx_dir); + prescale_point_effect = std::make_unique<effect>(this, d3d->get_device(), "prescale.fx", fx_dir); + phosphor_effect = std::make_unique<effect>(this, d3d->get_device(), "phosphor.fx", fx_dir); + focus_effect = std::make_unique<effect>(this, d3d->get_device(), "focus.fx", fx_dir); + scanline_effect = std::make_unique<effect>(this, d3d->get_device(), "scanline.fx", fx_dir); + deconverge_effect = std::make_unique<effect>(this, d3d->get_device(), "deconverge.fx", fx_dir); + color_effect = std::make_unique<effect>(this, d3d->get_device(), "color.fx", fx_dir); + ntsc_effect = std::make_unique<effect>(this, d3d->get_device(), "ntsc.fx", fx_dir); + bloom_effect = std::make_unique<effect>(this, d3d->get_device(), "bloom.fx", fx_dir); + downsample_effect = std::make_unique<effect>(this, d3d->get_device(), "downsample.fx", fx_dir); + vector_effect = std::make_unique<effect>(this, d3d->get_device(), "vector.fx", fx_dir); + chroma_effect = std::make_unique<effect>(this, d3d->get_device(), "chroma.fx", fx_dir); std::array<effect*, 18> effects = { - default_effect, - ui_effect, - ui_wrap_effect, - vector_buffer_effect, - post_effect, - distortion_effect, - prescale_effect, - prescale_point_effect, - phosphor_effect, - focus_effect, - scanline_effect, - deconverge_effect, - color_effect, - ntsc_effect, - bloom_effect, - downsample_effect, - vector_effect, - chroma_effect - }; - - for (int i = 0; i < effects.size(); i++) - { - effects[i]->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS); - effects[i]->add_uniform("TargetScale", uniform::UT_FLOAT, uniform::CU_TARGET_SCALE); - effects[i]->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); - effects[i]->add_uniform("ScreenCount", uniform::UT_INT, uniform::CU_SCREEN_COUNT); - effects[i]->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY); - effects[i]->add_uniform("VectorScreen", uniform::UT_BOOL, uniform::CU_VECTOR_SCREEN); + default_effect.get(), + ui_effect.get(), + ui_wrap_effect.get(), + vector_buffer_effect.get(), + post_effect.get(), + distortion_effect.get(), + prescale_effect.get(), + prescale_point_effect.get(), + phosphor_effect.get(), + focus_effect.get(), + scanline_effect.get(), + deconverge_effect.get(), + color_effect.get(), + ntsc_effect.get(), + bloom_effect.get(), + downsample_effect.get(), + vector_effect.get(), + chroma_effect.get() }; + + for (effect *eff : effects) + { + if (!eff->is_valid()) + return 1; + } + + for (effect *eff : effects) + { + eff->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS); + eff->add_uniform("TargetScale", uniform::UT_FLOAT, uniform::CU_TARGET_SCALE); + eff->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); + eff->add_uniform("ScreenCount", uniform::UT_INT, uniform::CU_SCREEN_COUNT); + eff->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY); + eff->add_uniform("VectorScreen", uniform::UT_BOOL, uniform::CU_VECTOR_SCREEN); } ntsc_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); @@ -1038,17 +951,14 @@ int shaders::create_resources() void shaders::begin_draw() { - double t; - if (!enabled()) - { return; - } curr_target = 0; - curr_effect = default_effect; + curr_effect = default_effect.get(); + // Update for delta_time - t = machine->time().as_double(); + const double t = machine->time().as_double(); delta_t = t - acc_t; acc_t = t; @@ -1072,7 +982,7 @@ void shaders::begin_draw() vector_effect->set_technique("DefaultTechnique"); chroma_effect->set_technique("DefaultTechnique"); - HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer); + HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get()); if (FAILED(result)) { osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); @@ -1176,15 +1086,15 @@ int shaders::ntsc_pass(d3d_render_target *rt, int source_index, poly_info *poly, // initial "Diffuse" texture is set in shaders::set_texture() - set_curr_effect(ntsc_effect); + set_curr_effect(ntsc_effect.get()); curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); curr_effect->update_uniforms(); curr_effect->set_float("SignalOffset", signal_offset); next_index = rt->next_index(next_index); - blit(rt->source_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->source_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); - color_effect->set_texture("Diffuse", rt->source_texture[next_index]); + color_effect->set_texture("Diffuse", rt->source_texture[next_index].Get()); return next_index; } @@ -1233,7 +1143,7 @@ int shaders::color_convolution_pass(d3d_render_target *rt, int source_index, pol { int next_index = source_index; - set_curr_effect(color_effect); + set_curr_effect(color_effect.get()); // initial "Diffuse" texture is set in shaders::ntsc_pass() if NTSC processing is enabled if (!options->yiq_enable) @@ -1247,7 +1157,7 @@ int shaders::color_convolution_pass(d3d_render_target *rt, int source_index, pol curr_effect->set_vector("PrimTint", 3, prim_tint); next_index = rt->next_index(next_index); - blit(rt->source_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->source_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1256,12 +1166,12 @@ int shaders::prescale_pass(d3d_render_target *rt, int source_index, poly_info *p { int next_index = source_index; - set_curr_effect(filter_screens ? prescale_effect : prescale_point_effect); + set_curr_effect(filter_screens ? prescale_effect.get() : prescale_point_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->source_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->source_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1279,12 +1189,12 @@ int shaders::deconverge_pass(d3d_render_target *rt, int source_index, poly_info return next_index; } - set_curr_effect(deconverge_effect); + set_curr_effect(deconverge_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1297,7 +1207,6 @@ int shaders::scanline_pass(d3d_render_target *rt, int source_index, poly_info *p //if (options->scanline_alpha == 0.0f) //return next_index; - auto win = d3d->assert_window(); screen_device_enumerator screen_iterator(machine->root_device()); screen_device *screen = screen_iterator.byindex(target_to_screen[curr_target]); render_container &screen_container = screen->container(); @@ -1308,16 +1217,16 @@ int shaders::scanline_pass(d3d_render_target *rt, int source_index, poly_info *p float screen_scale[] = { xscale, yscale }; float screen_offset[] = { xoffset, yoffset }; - set_curr_effect(scanline_effect); + set_curr_effect(scanline_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); curr_effect->set_vector("ScreenScale", 2, screen_scale); curr_effect->set_vector("ScreenOffset", 2, screen_offset); curr_effect->set_float("ScanlineOffset", curr_texture->get_cur_frame() == 0 ? 0.0f : options->scanline_jitter); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1331,12 +1240,12 @@ int shaders::defocus_pass(d3d_render_target *rt, int source_index, poly_info *po return next_index; } - set_curr_effect(focus_effect); + set_curr_effect(focus_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1352,23 +1261,23 @@ int shaders::phosphor_pass(d3d_render_target *rt, int source_index, poly_info *p } // Shader needs time between last update - set_curr_effect(phosphor_effect); + set_curr_effect(phosphor_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); - curr_effect->set_texture("LastPass", rt->cache_texture); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); + curr_effect->set_texture("LastPass", rt->cache_texture.Get()); curr_effect->set_bool("Passthrough", false); curr_effect->set_float("DeltaTime", delta_time()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); // Pass along our phosphor'd screen curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); - curr_effect->set_texture("LastPass", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); + curr_effect->set_texture("LastPass", rt->target_texture[next_index].Get()); curr_effect->set_bool("Passthrough", true); - blit(rt->cache_surface, false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->cache_surface.Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1377,8 +1286,6 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly, { int next_index = source_index; - auto win = d3d->assert_window(); - screen_device_enumerator screen_iterator(machine->root_device()); screen_device *screen = screen_iterator.byindex(target_to_screen[curr_target]); render_container &screen_container = screen->container(); @@ -1399,11 +1306,11 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly, float(back_color_rgb.g()) / 255.0f, float(back_color_rgb.b()) / 255.0f }; - set_curr_effect(post_effect); + set_curr_effect(post_effect.get()); curr_effect->update_uniforms(); curr_effect->set_texture("ShadowTexture", shadow_texture == nullptr ? nullptr : shadow_texture->get_finaltex()); curr_effect->set_int("ShadowTileMode", options->shadow_mask_tile_mode); - curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]); + curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get()); curr_effect->set_vector("BackColor", 3, back_color); curr_effect->set_vector("ScreenScale", 2, screen_scale); curr_effect->set_vector("ScreenOffset", 2, screen_offset); @@ -1412,7 +1319,7 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly, curr_effect->set_bool("PrepareBloom", prepare_bloom); next_index = rt->next_index(next_index); - blit(prepare_bloom ? rt->source_surface[next_index] : rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(prepare_bloom ? rt->source_surface[next_index].Get() : rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1421,11 +1328,11 @@ int shaders::chroma_pass(d3d_render_target *rt, int source_index, poly_info *pol { int next_index = source_index; - set_curr_effect(chroma_effect); + set_curr_effect(chroma_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1439,7 +1346,7 @@ int shaders::downsample_pass(d3d_render_target *rt, int source_index, poly_info return next_index; } - set_curr_effect(downsample_effect); + set_curr_effect(downsample_effect.get()); curr_effect->update_uniforms(); for (int bloom_index = 0; bloom_index < rt->bloom_count; bloom_index++) @@ -1447,10 +1354,10 @@ int shaders::downsample_pass(d3d_render_target *rt, int source_index, poly_info curr_effect->set_vector("TargetDims", 2, rt->bloom_dims[bloom_index]); curr_effect->set_texture("DiffuseTexture", bloom_index == 0 - ? rt->source_texture[next_index] - : rt->bloom_texture[bloom_index - 1]); + ? rt->source_texture[next_index].Get() + : rt->bloom_texture[bloom_index - 1].Get()); - blit(rt->bloom_surface[bloom_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->bloom_surface[bloom_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); } return next_index; @@ -1466,7 +1373,7 @@ int shaders::bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly return next_index; } - set_curr_effect(bloom_effect); + set_curr_effect(bloom_effect.get()); curr_effect->update_uniforms(); curr_effect->set_float("Level0Weight", options->bloom_level0_weight); @@ -1483,22 +1390,22 @@ int shaders::bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly curr_effect->set_float("BloomScale", options->bloom_scale); curr_effect->set_vector("BloomOverdrive", 3, options->bloom_overdrive); - curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]); + curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get()); char name[14] = "BloomTexture*"; for (int index = 1; index < rt->bloom_count; index++) { name[12] = 'A' + index - 1; - curr_effect->set_texture(name, rt->bloom_texture[index - 1]); + curr_effect->set_texture(name, rt->bloom_texture[index - 1].Get()); } for (int index = rt->bloom_count; index < MAX_BLOOM_COUNT; index++) { name[12] = 'A' + index - 1; - curr_effect->set_texture(name, black_texture); + curr_effect->set_texture(name, black_texture.Get()); } next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1519,12 +1426,12 @@ int shaders::distortion_pass(d3d_render_target *rt, int source_index, poly_info return next_index; } - set_curr_effect(distortion_effect); + set_curr_effect(distortion_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]); + curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1533,14 +1440,14 @@ int shaders::vector_pass(d3d_render_target *rt, int source_index, poly_info *pol { int next_index = source_index; - set_curr_effect(vector_effect); + set_curr_effect(vector_effect.get()); curr_effect->update_uniforms(); curr_effect->set_float("LengthRatio", options->vector_length_ratio); curr_effect->set_float("LengthScale", options->vector_length_scale); curr_effect->set_float("BeamSmooth", options->vector_beam_smooth); // we need to clear the vector render target here - blit(rt->target_surface[next_index], true, poly->type(), vertnum, poly->count()); + blit(rt->target_surface[next_index].Get(), true, poly->type(), vertnum, poly->count()); return next_index; } @@ -1549,16 +1456,16 @@ int shaders::vector_buffer_pass(d3d_render_target *rt, int source_index, poly_in { int next_index = source_index; - set_curr_effect(vector_buffer_effect); + set_curr_effect(vector_buffer_effect.get()); curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); curr_effect->set_texture("LutTexture", lut_texture == nullptr ? nullptr : lut_texture->get_finaltex()); // we need to clear the vector render target here next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), true, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1569,14 +1476,14 @@ int shaders::screen_pass(d3d_render_target *rt, int source_index, poly_info *pol d3d->set_blendmode(PRIMFLAG_GET_BLENDMODE(poly->flags())); - set_curr_effect(default_effect); + set_curr_effect(default_effect.get()); curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); curr_effect->set_texture("LutTexture", lut_texture == nullptr ? nullptr : lut_texture->get_finaltex()); - blit(backbuffer, false, poly->type(), vertnum, poly->count()); + blit(backbuffer.Get(), false, poly->type(), vertnum, poly->count()); if (recording_movie) { @@ -1588,9 +1495,9 @@ int shaders::screen_pass(d3d_render_target *rt, int source_index, poly_info *pol if (render_snap) { // we need to clear the snap render target here - blit(snap_target, true, poly->type(), vertnum, poly->count()); + blit(snap_target.Get(), true, poly->type(), vertnum, poly->count()); - render_snapshot(snap_target); + render_snapshot(snap_target.Get()); render_snap = false; } @@ -1602,7 +1509,7 @@ void shaders::ui_pass(poly_info *poly, int vertnum) { d3d->set_blendmode(PRIMFLAG_GET_BLENDMODE(poly->flags())); - set_curr_effect(PRIMFLAG_GET_TEXWRAP(poly->flags()) ? ui_wrap_effect : ui_effect); + set_curr_effect(PRIMFLAG_GET_TEXWRAP(poly->flags()) ? ui_wrap_effect.get() : ui_effect.get()); curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); curr_effect->update_uniforms(); @@ -1626,8 +1533,6 @@ void shaders::render_quad(poly_info *poly, int vertnum) curr_texture = poly->texture(); curr_poly = poly; - auto win = d3d->assert_window(); - if (PRIMFLAG_GET_SCREENTEX(poly->flags())) { if (curr_texture == nullptr) @@ -1687,7 +1592,7 @@ void shaders::render_quad(poly_info *poly, int vertnum) int source_width = int(poly->prim_width() + 0.5f); int source_height = int(poly->prim_height() + 0.5f); - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(source_width, source_height); } @@ -1704,7 +1609,7 @@ void shaders::render_quad(poly_info *poly, int vertnum) next_index = vector_pass(rt, next_index, poly, vertnum); - HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer); + HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get()); if (FAILED(result)) { osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); @@ -1718,7 +1623,7 @@ void shaders::render_quad(poly_info *poly, int vertnum) int source_width = int(poly->prim_width() + 0.5f); int source_height = int(poly->prim_height() + 0.5f); - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(source_width, source_height); } @@ -1783,7 +1688,7 @@ void shaders::end_draw() return; } - backbuffer->Release(); + backbuffer->Release(); // TODO: where's the matching AddRef that requires this explicit Release? } @@ -1798,8 +1703,6 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, int width return nullptr; } - auto win = d3d->assert_window(); - int source_width = width; int source_height = height; int source_screen = screen; @@ -1807,7 +1710,7 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, int width int target_height = int(prim->get_full_quad_height() + 0.5f); target_width *= oversampling_enable ? 2 : 1; target_height *= oversampling_enable ? 2 : 1; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(target_width, target_height); } @@ -1838,8 +1741,6 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim, int screen return nullptr; } - auto win = d3d->assert_window(); - int source_width = int(prim->get_quad_width() + 0.5f); int source_height = int(prim->get_quad_height() + 0.5f); int source_screen = screen; @@ -1847,7 +1748,7 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim, int screen int target_height = int(prim->get_full_quad_height() + 0.5f); target_width *= oversampling_enable ? 2 : 1; target_height *= oversampling_enable ? 2 : 1; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(source_width, source_height); std::swap(target_width, target_height); @@ -1879,8 +1780,6 @@ bool shaders::create_vector_target(render_primitive *prim, int screen) return false; } - auto win = d3d->assert_window(); - int source_width = int(prim->get_quad_width() + 0.5f); int source_height = int(prim->get_quad_height() + 0.5f); int source_screen = screen; @@ -1888,7 +1787,7 @@ bool shaders::create_vector_target(render_primitive *prim, int screen) int target_height = int(prim->get_full_quad_height() + 0.5f); target_width *= oversampling_enable ? 2 : 1; target_height *= oversampling_enable ? 2 : 1; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(source_width, source_height); std::swap(target_width, target_height); @@ -1934,8 +1833,6 @@ bool shaders::create_texture_target(render_primitive *prim, int width, int heigh return false; } - auto win = d3d->assert_window(); - int source_width = width; int source_height = height; int source_screen = screen; @@ -1943,7 +1840,7 @@ bool shaders::create_texture_target(render_primitive *prim, int width, int heigh int target_height = int(prim->get_full_quad_height() + 0.5f); target_width *= oversampling_enable ? 2 : 1; target_height *= oversampling_enable ? 2 : 1; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { // source texture is already swapped std::swap(target_width, target_height); @@ -1981,58 +1878,29 @@ void shaders::delete_resources() m_render_target_list.clear(); - delete downsample_effect; - delete bloom_effect; - delete vector_effect; - delete default_effect; - delete ui_effect; - delete vector_buffer_effect; - delete post_effect; - delete distortion_effect; - delete prescale_effect; - delete prescale_point_effect; - delete phosphor_effect; - delete focus_effect; - delete scanline_effect; - delete deconverge_effect; - delete color_effect; - delete ntsc_effect; - delete chroma_effect; - - downsample_effect = nullptr; - bloom_effect = nullptr; - vector_effect = nullptr; - default_effect = nullptr; - ui_effect = nullptr; - vector_buffer_effect = nullptr; - post_effect = nullptr; - distortion_effect = nullptr; - prescale_effect = nullptr; - prescale_point_effect = nullptr; - phosphor_effect = nullptr; - focus_effect = nullptr; - scanline_effect = nullptr; - deconverge_effect = nullptr; - color_effect = nullptr; - ntsc_effect = nullptr; - chroma_effect = nullptr; - - if (backbuffer) - { - backbuffer->Release(); - backbuffer = nullptr; - } - - if (black_surface) - { - black_surface->Release(); - black_surface = nullptr; - } - if (black_texture) - { - black_texture->Release(); - black_texture = nullptr; - } + downsample_effect.reset(); + bloom_effect.reset(); + vector_effect.reset(); + default_effect.reset(); + ui_effect.reset(); + ui_wrap_effect.reset(); + vector_buffer_effect.reset(); + post_effect.reset(); + distortion_effect.reset(); + prescale_effect.reset(); + prescale_point_effect.reset(); + phosphor_effect.reset(); + focus_effect.reset(); + scanline_effect.reset(); + deconverge_effect.reset(); + color_effect.reset(); + ntsc_effect.reset(); + chroma_effect.reset(); + + backbuffer.Reset(); + + black_surface.Reset(); + black_texture.Reset(); shadow_bitmap.reset(); lut_bitmap.reset(); @@ -2396,10 +2264,6 @@ void shaders::init_slider_list() m_sliders.clear(); m_core_sliders.clear(); - for (slider* slider : internal_sliders) - { - delete slider; - } internal_sliders.clear(); const screen_device *first_screen = screen_device_enumerator(machine->root_device()).first(); @@ -2432,28 +2296,27 @@ void shaders::init_slider_list() for (int j = 0; j < count; j++) { - auto* slider_arg = new slider(desc, get_slider_option(desc->id, j), &options->params_dirty); - internal_sliders.push_back(slider_arg); + slider &slider_arg = *internal_sliders.emplace_back(std::make_unique<slider>(desc, get_slider_option(desc->id, j), &options->params_dirty)); std::string name = desc->name; switch (desc->slider_type) { case SLIDER_VEC2: { - std::string names[2] = { " X", " Y" }; - name = name + names[j]; + char const *const names[2] = { " X", " Y" }; + name += names[j]; break; } case SLIDER_COLOR: { - std::string names[3] = { " Red", " Green", " Blue" }; - name = name + names[j]; + char const *const names[3] = { " Red", " Green", " Blue" }; + name += names[j]; break; } default: break; } - std::unique_ptr<slider_state> core_slider = slider_alloc(std::move(name), desc->minval, desc->defval, desc->maxval, desc->step, slider_arg); + std::unique_ptr<slider_state> core_slider = slider_alloc(std::move(name), desc->minval, desc->defval, desc->maxval, desc->step, &slider_arg); ui::menu_item item(ui::menu_item_type::SLIDER, core_slider.get()); item.set_text(core_slider->description); @@ -2488,8 +2351,7 @@ void uniform::update() hlsl_options *options = shadersys->options; renderer_d3d9 *d3d = shadersys->d3d; - auto win = d3d->assert_window(); - const screen_device *first_screen = screen_device_enumerator(win->machine().root_device()).first(); + const screen_device *first_screen = screen_device_enumerator(d3d->window().machine().root_device()).first(); bool vector_screen = first_screen != nullptr && @@ -2505,7 +2367,7 @@ void uniform::update() } case CU_SCREEN_COUNT: { - int screen_count = win->target()->current_view().visible_screen_count(); + int screen_count = d3d->window().target()->current_view().visible_screen_count(); m_shader->set_int("ScreenCount", screen_count); break; } @@ -2568,7 +2430,7 @@ void uniform::update() case CU_SWAP_XY: { - m_shader->set_bool("SwapXY", win->swap_xy()); + m_shader->set_bool("SwapXY", d3d->window().swap_xy()); break; } case CU_VECTOR_SCREEN: diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h index aa990e3c30c..f06deca2a57 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.h +++ b/src/osd/modules/render/d3d/d3dhlsl.h @@ -13,8 +13,11 @@ #include "../frontend/mame/ui/slider.h" #include "modules/lib/osdlib.h" -#include <vector> +#include <wrl/client.h> + #include <map> +#include <memory> +#include <vector> //============================================================ // TYPE DEFINITIONS @@ -308,9 +311,9 @@ public: shaders(); ~shaders(); - bool init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer); + bool init(IDirect3D9 *d3dobj, running_machine *machine, renderer_d3d9 *renderer); - bool enabled() { return post_fx_enable && d3dintf->post_fx_available; } + bool enabled() { return post_fx_enable && d3d->post_fx_available(); } void toggle() { post_fx_enable = initialized && !post_fx_enable; } void begin_frame(render_primitive_list *primlist); @@ -348,6 +351,10 @@ public: void *get_slider_option(int id, int index = 0); private: + using IDirect3D9Ptr = Microsoft::WRL::ComPtr<IDirect3D9>; + using IDirect3DTexture9Ptr = Microsoft::WRL::ComPtr<IDirect3DTexture9>; + using IDirect3DSurface9Ptr = Microsoft::WRL::ComPtr<IDirect3DSurface9>; + void set_curr_effect(effect *curr_effect); void blit(IDirect3DSurface9 *dst, bool clear_dst, D3DPRIMITIVETYPE prim_type, uint32_t prim_index, uint32_t prim_count); @@ -376,7 +383,7 @@ private: int screen_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum); void ui_pass(poly_info *poly, int vertnum); - d3d_base * d3dintf; // D3D interface + IDirect3D9Ptr d3dobj; // D3D interface running_machine * machine; renderer_d3d9 * d3d; // D3D renderer @@ -398,43 +405,43 @@ private: texture_info * ui_lut_texture; hlsl_options * options; // current options - IDirect3DSurface9 * black_surface; // black dummy surface - IDirect3DTexture9 * black_texture; // black dummy texture + IDirect3DSurface9Ptr black_surface; // black dummy surface + IDirect3DTexture9Ptr black_texture; // black dummy texture bool recording_movie; // ongoing movie recording std::unique_ptr<movie_recorder> recorder; // HLSL post-render movie recorder bool render_snap; // whether or not to take HLSL post-render snapshot - IDirect3DSurface9 * snap_copy_target; // snapshot destination surface in system memory - IDirect3DTexture9 * snap_copy_texture; // snapshot destination surface in system memory - IDirect3DSurface9 * snap_target; // snapshot upscaled surface - IDirect3DTexture9 * snap_texture; // snapshot upscaled texture + IDirect3DSurface9Ptr snap_copy_target; // snapshot destination surface in system memory + IDirect3DTexture9Ptr snap_copy_texture; // snapshot destination surface in system memory + IDirect3DSurface9Ptr snap_target; // snapshot upscaled surface + IDirect3DTexture9Ptr snap_texture; // snapshot upscaled texture int snap_width; // snapshot width int snap_height; // snapshot height bool initialized; // whether or not we're initialized // HLSL effects - IDirect3DSurface9 * backbuffer; // pointer to our device's backbuffer + IDirect3DSurface9Ptr backbuffer; // pointer to our device's backbuffer effect * curr_effect; // pointer to the currently active effect object - effect * default_effect; // pointer to the primary-effect object - effect * ui_effect; // pointer to the UI-element effect object - effect * ui_wrap_effect; // pointer to the UI-element effect object with texture wrapping - effect * vector_buffer_effect; // pointer to the vector-buffering effect object - effect * prescale_effect; // pointer to the prescale-effect object - effect * prescale_point_effect; // pointer to the prescale-effect object with point filtering - effect * post_effect; // pointer to the post-effect object - effect * distortion_effect; // pointer to the distortion-effect object - effect * scanline_effect; - effect * focus_effect; // pointer to the focus-effect object - effect * phosphor_effect; // pointer to the phosphor-effect object - effect * deconverge_effect; // pointer to the deconvergence-effect object - effect * color_effect; // pointer to the color-effect object - effect * ntsc_effect; // pointer to the NTSC effect object - effect * bloom_effect; // pointer to the bloom composite effect - effect * downsample_effect; // pointer to the bloom downsample effect - effect * vector_effect; // pointer to the vector-effect object - effect * chroma_effect; + std::unique_ptr<effect> default_effect; // pointer to the primary-effect object + std::unique_ptr<effect> ui_effect; // pointer to the UI-element effect object + std::unique_ptr<effect> ui_wrap_effect; // pointer to the UI-element effect object with texture wrapping + std::unique_ptr<effect> vector_buffer_effect; // pointer to the vector-buffering effect object + std::unique_ptr<effect> prescale_effect; // pointer to the prescale-effect object + std::unique_ptr<effect> prescale_point_effect; // pointer to the prescale-effect object with point filtering + std::unique_ptr<effect> post_effect; // pointer to the post-effect object + std::unique_ptr<effect> distortion_effect; // pointer to the distortion-effect object + std::unique_ptr<effect> scanline_effect; + std::unique_ptr<effect> focus_effect; // pointer to the focus-effect object + std::unique_ptr<effect> phosphor_effect; // pointer to the phosphor-effect object + std::unique_ptr<effect> deconverge_effect; // pointer to the deconvergence-effect object + std::unique_ptr<effect> color_effect; // pointer to the color-effect object + std::unique_ptr<effect> ntsc_effect; // pointer to the NTSC effect object + std::unique_ptr<effect> bloom_effect; // pointer to the bloom composite effect + std::unique_ptr<effect> downsample_effect; // pointer to the bloom downsample effect + std::unique_ptr<effect> vector_effect; // pointer to the vector-effect object + std::unique_ptr<effect> chroma_effect; texture_info * diffuse_texture; bool filter_screens; @@ -444,9 +451,9 @@ private: std::vector<std::unique_ptr<d3d_render_target>> m_render_target_list; - std::vector<slider*> internal_sliders; + std::vector<std::unique_ptr<slider> > internal_sliders; std::vector<ui::menu_item> m_sliders; - std::vector<std::unique_ptr<slider_state>> m_core_sliders; + std::vector<std::unique_ptr<slider_state> > m_core_sliders; static slider_desc s_sliders[]; static hlsl_options last_options; // last used options diff --git a/src/osd/modules/render/draw13.cpp b/src/osd/modules/render/draw13.cpp index 29310ea3f2e..9b426c6c4f2 100644 --- a/src/osd/modules/render/draw13.cpp +++ b/src/osd/modules/render/draw13.cpp @@ -2,7 +2,7 @@ // copyright-holders: Couriersud, Olivier Galibert, R. Belmont //============================================================ // -// draw13.c - SDL 2.0 drawing implementation +// draw13.cpp - SDL 2.0 drawing implementation // // SDLMAME by Olivier Galibert and R. Belmont // @@ -10,8 +10,11 @@ // //============================================================ -#include "emu.h" -#include "draw13.h" +#include "render_module.h" + +#include "modules/osdmodule.h" + +#if defined(OSD_SDL) // OSD headers #include "sdlopts.h" @@ -20,9 +23,190 @@ // lib/util #include "options.h" +// emu +#include "emucore.h" +#include "render.h" + +// standard SDL headers +#include <SDL2/SDL.h> + // standard C headers +#include <algorithm> #include <cmath> #include <cstdio> +#include <iterator> + + +namespace osd { + +namespace { + +struct quad_setup_data +{ + quad_setup_data() = default; + + void compute(const render_primitive &prim, const int prescale); + + int32_t dudx = 0, dvdx = 0, dudy = 0, dvdy = 0; + int32_t startu = 0, startv = 0; + int32_t rotwidth = 0, rotheight = 0; +}; + +//============================================================ +// Textures +//============================================================ + +class renderer_sdl2; +struct copy_info_t; + +/* texture_info holds information about a texture */ +class texture_info +{ + friend class simple_list<texture_info>; +public: + texture_info(renderer_sdl2 *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const uint32_t flags); + ~texture_info(); + + void set_data(const render_texinfo &texsource, const uint32_t flags); + void render_quad(const render_primitive &prim, const int x, const int y); + bool matches(const render_primitive &prim, const quad_setup_data &setup); + + copy_info_t const *compute_size_type(); + + void *m_pixels; // pixels for the texture + int m_pitch; + + copy_info_t const *m_copyinfo; + quad_setup_data m_setup; + + osd_ticks_t m_last_access; + + int raw_width() const { return m_texinfo.width; } + int raw_height() const { return m_texinfo.height; } + + texture_info *next() { return m_next; } + const render_texinfo &texinfo() const { return m_texinfo; } + render_texinfo &texinfo() { return m_texinfo; } + + HashT hash() const { return m_hash; } + uint32_t flags() const { return m_flags; } + // FIXME: + bool is_pixels_owned() const; + +private: + void set_coloralphamode(SDL_Texture *texture_id, const render_color *color); + + Uint32 m_sdl_access; + renderer_sdl2 * m_renderer; + render_texinfo m_texinfo; // copy of the texture info + HashT m_hash; // hash value for the texture (must be >= pointer size) + uint32_t m_flags; // rendering flags + + SDL_Texture * m_texture_id; + bool m_is_rotated; + + int m_format; // texture format + SDL_BlendMode m_sdl_blendmode; + + texture_info * m_next; // next texture in the list +}; + +// inline functions and macros +#include "blit13.ipp" + +//============================================================ +// TEXCOPY FUNCS +//============================================================ + +enum SDL_TEXFORMAT_E +{ + SDL_TEXFORMAT_ARGB32 = 0, + SDL_TEXFORMAT_RGB32, + SDL_TEXFORMAT_RGB32_PALETTED, + SDL_TEXFORMAT_YUY16, + SDL_TEXFORMAT_YUY16_PALETTED, + SDL_TEXFORMAT_PALETTE16, + SDL_TEXFORMAT_RGB15, + SDL_TEXFORMAT_RGB15_PALETTED, + SDL_TEXFORMAT_PALETTE16A, + SDL_TEXFORMAT_PALETTE16_ARGB1555, + SDL_TEXFORMAT_RGB15_ARGB1555, + SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555, + SDL_TEXFORMAT_LAST = SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555 +}; + +struct copy_info_t +{ + int src_fmt; + Uint32 dst_fmt; + const blit_base *blitter; + Uint32 bm_mask; + const char *srcname; + const char *dstname; + /* Statistics */ + mutable uint64_t pixel_count; + mutable int64_t time; + mutable int samples; + mutable int perf; + /* list */ + copy_info_t *next; +}; + +/* renderer_sdl2 is the information about SDL for the current screen */ +class renderer_sdl2 : public osd_renderer +{ +public: + renderer_sdl2( + osd_window &window, + copy_info_t const *const (&blit_info)[SDL_TEXFORMAT_LAST + 1]); + + virtual ~renderer_sdl2() + { + destroy_all_textures(); + SDL_DestroyRenderer(m_sdl_renderer); + m_sdl_renderer = nullptr; + } + + virtual int create() override; + virtual int draw(const int update) override; + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; + virtual render_primitive_list *get_primitives() override; + + int RendererSupportsFormat(Uint32 format, Uint32 access, const char *sformat); + + SDL_Renderer *m_sdl_renderer; + copy_info_t const *const (&m_blit_info)[SDL_TEXFORMAT_LAST + 1]; + +private: + void render_quad(texture_info *texture, const render_primitive &prim, const int x, const int y); + + texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup); + texture_info *texture_update(const render_primitive &prim); + + void destroy_all_textures(); + + int32_t m_blittimer; + + simple_list<texture_info> m_texlist; // list of active textures + + float m_last_hofs; + float m_last_vofs; + + int m_width; + int m_height; + + osd_dim m_blit_dim; + + struct + { + Uint32 format; + int status; + } fmt_support[30]; + + // Stats + int64_t m_last_blit_time; + int64_t m_last_blit_pixels; +}; //============================================================ @@ -57,9 +241,12 @@ static inline bool is_transparent(const float &a) // CONSTRUCTOR & DESTRUCTOR //============================================================ -renderer_sdl2::renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags) - : osd_renderer(window, FLAG_NEEDS_OPENGL | extra_flags) +renderer_sdl2::renderer_sdl2( + osd_window &window, + copy_info_t const *const (&blit_info)[SDL_TEXFORMAT_LAST + 1]) + : osd_renderer(window) , m_sdl_renderer(nullptr) + , m_blit_info(blit_info) , m_blittimer(0) , m_last_hofs(0) , m_last_vofs(0) @@ -74,112 +261,8 @@ renderer_sdl2::renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags fmt_support[i].format = 0; fmt_support[i].status = 0; } - - if (!s_blit_info_initialized) - { - /* On OSX, calling this from drawsdl2_init will - * prohibit fullscreen toggling. It is than not possible - * to toggle from fullscreen to window mode. - */ - expand_copy_info(s_blit_info_default); - s_blit_info_initialized = true; - } } - -//============================================================ -// STATIC VARIABLES -//============================================================ - -#define BM_ALL (UINT32_MAX) -//( SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD) - -#define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0} -#define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} -#define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} - -const copy_info_t renderer_sdl2::s_blit_info_default[] = -{ - /* no rotation */ - ENTRY(ARGB32, ARGB8888, argb32_argb32), - ENTRY_LR(ARGB32, RGB888, argb32_rgb32), - /* Entry primarily for directfb */ - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD), - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD), - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE), - - ENTRY(RGB32, ARGB8888, rgb32_argb32), - ENTRY(RGB32, RGB888, rgb32_rgb32), - - ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32), - ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32), - - ENTRY(YUY16, UYVY, yuv16_uyvy), - ENTRY(YUY16, YUY2, yuv16_yuy2), - ENTRY(YUY16, YVYU, yuv16_yvyu), - ENTRY(YUY16, ARGB8888, yuv16_argb32), - ENTRY(YUY16, RGB888, yuv16_argb32), - - ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy), - ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2), - ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu), - ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32), - ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32), - - ENTRY(PALETTE16, ARGB8888, pal16_argb32), - ENTRY(PALETTE16, RGB888, pal16_argb32), - - ENTRY(RGB15, RGB555, rgb15_rgb555), - ENTRY(RGB15, ARGB1555, rgb15_argb1555), - ENTRY(RGB15, ARGB8888, rgb15_argb32), - ENTRY(RGB15, RGB888, rgb15_argb32), - - ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32), - ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32), - - ENTRY(PALETTE16A, ARGB8888, pal16a_argb32), - ENTRY(PALETTE16A, RGB888, pal16a_rgb32), - - /* rotation */ - ENTRY(ARGB32, ARGB8888, rot_argb32_argb32), - ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32), - /* Entry primarily for directfb */ - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD), - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD), - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE), - - ENTRY(RGB32, ARGB8888, rot_rgb32_argb32), - ENTRY(RGB32, RGB888, rot_argb32_argb32), - - ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32), - ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32), - - ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot), - ENTRY(YUY16, RGB888, rot_yuv16_argb32rot), - - ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot), - ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot), - - ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32), - ENTRY(PALETTE16, RGB888, rot_pal16_argb32), - - ENTRY(RGB15, RGB555, rot_rgb15_argb1555), - ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555), - ENTRY(RGB15, ARGB8888, rot_rgb15_argb32), - ENTRY(RGB15, RGB888, rot_rgb15_argb32), - - ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32), - ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32), - - ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32), - ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32), - -{ -1 }, -}; - -copy_info_t* renderer_sdl2::s_blit_info[SDL_TEXFORMAT_LAST+1] = { nullptr }; -bool renderer_sdl2::s_blit_info_initialized = false; - //============================================================ // INLINES //============================================================ @@ -274,7 +357,7 @@ void renderer_sdl2::render_quad(texture_info *texture, const render_primitive &p if (texture) { - copy_info_t *copyinfo = texture->m_copyinfo; + copy_info_t const *copyinfo = texture->m_copyinfo; copyinfo->time -= osd_ticks(); texture->render_quad(prim, x, y); copyinfo->time += osd_ticks(); @@ -326,59 +409,6 @@ int renderer_sdl2::RendererSupportsFormat(Uint32 format, Uint32 access, const ch return 0; } -//============================================================ -// drawsdl_init -//============================================================ - -void renderer_sdl2::add_list(copy_info_t **head, const copy_info_t *element, Uint32 bm) -{ - copy_info_t *newci = new copy_info_t; - *newci = *element; - - newci->bm_mask = bm; - newci->next = *head; - *head = newci; -} - -void renderer_sdl2::expand_copy_info(const copy_info_t *list) -{ - for (const copy_info_t *bi = list; bi->src_fmt != -1; bi++) - { - if (bi->bm_mask == BM_ALL) - { - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_NONE); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_ADD); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_MOD); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_BLEND); - } - else - { - add_list(&s_blit_info[bi->src_fmt], bi, bi->bm_mask); - } - } -} - -// FIXME: machine only used to access options. -void renderer_sdl2::init(running_machine &machine) -{ - osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n"); - -#if USE_OPENGL - // Load the GL library now - else MT will fail - const char *stemp = downcast<sdl_options &>(machine.options()).gl_lib(); -#else - const char *stemp = nullptr; -#endif - if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) == 0) - stemp = nullptr; - - // No fatalerror here since not all video drivers support GL ! - if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==nullptr - osd_printf_warning("Warning: Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); - else - osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); -} - //============================================================ // sdl_info::create @@ -431,12 +461,10 @@ int renderer_sdl2::create() SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); } - auto win = assert_window(); - if (video_config.waitvsync) - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); else - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_ACCELERATED); if (!m_sdl_renderer) { @@ -480,15 +508,11 @@ int renderer_sdl2::xy_to_render_target(int x, int y, int *xt, int *yt) void renderer_sdl2::destroy_all_textures() { - auto win = assert_window(); - if (win == nullptr) - return; - - if(win->m_primlist) + if (window().m_primlist) { - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); m_texlist.reset(); - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); } else m_texlist.reset(); @@ -504,13 +528,7 @@ int renderer_sdl2::draw(int update) float vofs, hofs; int blit_pixels = 0; - if (video_config.novideo) - { - return 0; - } - - auto win = assert_window(); - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) { @@ -557,10 +575,10 @@ int renderer_sdl2::draw(int update) m_last_hofs = hofs; m_last_vofs = vofs; - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // now draw - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { Uint8 sr, sg, sb, sa; @@ -590,7 +608,7 @@ int renderer_sdl2::draw(int update) } } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); m_last_blit_pixels = blit_pixels; m_last_blit_time = -osd_ticks(); @@ -609,22 +627,23 @@ int renderer_sdl2::draw(int update) // texture_compute_size and type //============================================================ -copy_info_t *texture_info::compute_size_type() +copy_info_t const *texture_info::compute_size_type() { - copy_info_t *result = nullptr; + copy_info_t const *result = nullptr; int maxperf = 0; - for (copy_info_t *bi = renderer_sdl2::s_blit_info[m_format]; bi != nullptr; bi = bi->next) + for (copy_info_t const *bi = m_renderer->m_blit_info[m_format]; bi != nullptr; bi = bi->next) { - if ((m_is_rotated == bi->blitter->m_is_rot) - && (m_sdl_blendmode == bi->bm_mask)) + if ((m_is_rotated == bi->blitter->m_is_rot) && (m_sdl_blendmode == bi->bm_mask)) { if (m_renderer->RendererSupportsFormat(bi->dst_fmt, m_sdl_access, bi->dstname)) { - int perf = bi->perf; + int const perf = bi->perf; if (perf == 0) + { return bi; - else if (perf > (maxperf * 102) / 100) + } + else if (perf > ((maxperf * 102) / 100)) { result = bi; maxperf = perf; @@ -636,15 +655,14 @@ copy_info_t *texture_info::compute_size_type() if (result) return result; - /* try last resort handlers */ - for (copy_info_t *bi = renderer_sdl2::s_blit_info[m_format]; bi != nullptr; bi = bi->next) + // try last resort handlers + for (copy_info_t const *bi = m_renderer->m_blit_info[m_format]; bi != nullptr; bi = bi->next) { - if ((m_is_rotated == bi->blitter->m_is_rot) - && (m_sdl_blendmode == bi->bm_mask)) + if ((m_is_rotated == bi->blitter->m_is_rot) && (m_sdl_blendmode == bi->bm_mask)) if (m_renderer->RendererSupportsFormat(bi->dst_fmt, m_sdl_access, bi->dstname)) return bi; } - //FIXME: crash implement a -do nothing handler */ + //FIXME: crash implement a -do nothing handler return nullptr; } @@ -897,32 +915,6 @@ texture_info *renderer_sdl2::texture_find(const render_primitive &prim, const qu } //============================================================ -// exit -//============================================================ - -void renderer_sdl2::exit() -{ - if (s_blit_info_initialized) - { - for (int i = 0; i <= SDL_TEXFORMAT_LAST; i++) - { - for (copy_info_t *bi = s_blit_info[i]; bi != nullptr; ) - { - if (bi->pixel_count) - osd_printf_verbose("%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", bi->srcname, bi->dstname, - bi->blitter->m_is_rot ? "rot" : "norot", bi->bm_mask, bi->samples, - (int) bi->perf); - copy_info_t *freeme = bi; - bi = bi->next; - delete freeme; - } - s_blit_info[i] = nullptr; - } - s_blit_info_initialized = false; - } -} - -//============================================================ // texture_update //============================================================ @@ -931,8 +923,7 @@ texture_info * renderer_sdl2::texture_update(const render_primitive &prim) quad_setup_data setup; texture_info *texture; - auto win = assert_window(); - setup.compute(prim, win->prescale()); + setup.compute(prim, window().prescale()); texture = texture_find(prim, setup); @@ -959,16 +950,251 @@ texture_info * renderer_sdl2::texture_update(const render_primitive &prim) render_primitive_list *renderer_sdl2::get_primitives() { - auto win = assert_window(); - if (win == nullptr) - return nullptr; - - osd_dim nd = win->get_size(); + osd_dim nd = window().get_size(); if (nd != m_blit_dim) { m_blit_dim = nd; notify_changed(); } - win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); +} + + +class video_sdl2 : public osd_module, public render_module +{ +public: + video_sdl2() + : osd_module(OSD_RENDERER_PROVIDER, "accel") + , m_blit_info_initialized(false) + , m_gllib_loaded(false) + { + std::fill(std::begin(m_blit_info), std::end(m_blit_info), nullptr); + } + ~video_sdl2() + { + free_copy_info(); + } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override { free_copy_info(); } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE | FLAG_SDL_NEEDS_OPENGL; } + +private: + static inline constexpr Uint32 BM_ALL = UINT32_MAX; // SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD + + void expand_copy_info(); + void free_copy_info(); + + static void add_list(copy_info_t *&head, copy_info_t const &element, Uint32 bm); + + copy_info_t *m_blit_info[SDL_TEXFORMAT_LAST + 1]; + bool m_blit_info_initialized; + bool m_gllib_loaded; + + static copy_info_t const s_blit_info_default[]; +}; + +int video_sdl2::init(osd_interface &osd, osd_options const &options) +{ + osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n"); + + // Load the GL library now - else MT will fail + char const *libname = nullptr; +#if USE_OPENGL + libname = dynamic_cast<sdl_options const &>(options).gl_lib(); + if (libname && (!*libname || !std::strcmp(libname, OSDOPTVAL_AUTO))) + libname = nullptr; +#endif + + if (!m_gllib_loaded) + { + // No fatalerror here since not all video drivers support GL! + if (SDL_GL_LoadLibrary(libname) != 0) + { + osd_printf_error("Unable to load OpenGL shared library: %s\n", libname ? libname : "<default>"); + m_gllib_loaded = true; + } + else + { + osd_printf_verbose("Loaded OpenGL shared library: %s\n", libname ? libname : "<default>"); + } + } + + return 0; +} + +std::unique_ptr<osd_renderer> video_sdl2::create(osd_window &window) +{ + if (!m_blit_info_initialized) + { + // On macOS, calling this from drawsdl2_init will prohibit fullscreen toggling. + // It is than not possible to toggle from fullscreen to window mode. + expand_copy_info(); + m_blit_info_initialized = true; + } + + return std::make_unique<renderer_sdl2>(window, m_blit_info); } + +void video_sdl2::expand_copy_info() +{ + for (const copy_info_t *bi = s_blit_info_default; bi->src_fmt != -1; bi++) + { + if (bi->bm_mask == BM_ALL) + { + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_NONE); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_ADD); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_MOD); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_BLEND); + } + else + { + add_list(m_blit_info[bi->src_fmt], *bi, bi->bm_mask); + } + } +} + +void video_sdl2::free_copy_info() +{ + if (m_blit_info_initialized) + { + for (int i = 0; i <= SDL_TEXFORMAT_LAST; i++) + { + for (copy_info_t *bi = m_blit_info[i]; bi != nullptr; ) + { + if (bi->pixel_count) + { + osd_printf_verbose( + "%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", + bi->srcname, + bi->dstname, + bi->blitter->m_is_rot ? "rot" : "norot", + bi->bm_mask, + bi->samples, + bi->perf); + } + copy_info_t *freeme = bi; + bi = bi->next; + delete freeme; + } + m_blit_info[i] = nullptr; + } + m_blit_info_initialized = false; + } +} + +void video_sdl2::add_list(copy_info_t *&head, copy_info_t const &element, Uint32 bm) +{ + copy_info_t *const newci = new copy_info_t(element); + + newci->bm_mask = bm; + newci->next = head; + head = newci; +} + + +//============================================================ +// STATIC VARIABLES +//============================================================ + +#define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0} +#define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} +#define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} + +copy_info_t const video_sdl2::s_blit_info_default[] = +{ + /* no rotation */ + ENTRY(ARGB32, ARGB8888, argb32_argb32), + ENTRY_LR(ARGB32, RGB888, argb32_rgb32), + /* Entry primarily for directfb */ + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD), + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD), + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE), + + ENTRY(RGB32, ARGB8888, rgb32_argb32), + ENTRY(RGB32, RGB888, rgb32_rgb32), + + ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32), + ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32), + + ENTRY(YUY16, UYVY, yuv16_uyvy), + ENTRY(YUY16, YUY2, yuv16_yuy2), + ENTRY(YUY16, YVYU, yuv16_yvyu), + ENTRY(YUY16, ARGB8888, yuv16_argb32), + ENTRY(YUY16, RGB888, yuv16_argb32), + + ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy), + ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2), + ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu), + ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32), + ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32), + + ENTRY(PALETTE16, ARGB8888, pal16_argb32), + ENTRY(PALETTE16, RGB888, pal16_argb32), + + ENTRY(RGB15, RGB555, rgb15_rgb555), + ENTRY(RGB15, ARGB1555, rgb15_argb1555), + ENTRY(RGB15, ARGB8888, rgb15_argb32), + ENTRY(RGB15, RGB888, rgb15_argb32), + + ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32), + ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32), + + ENTRY(PALETTE16A, ARGB8888, pal16a_argb32), + ENTRY(PALETTE16A, RGB888, pal16a_rgb32), + + /* rotation */ + ENTRY(ARGB32, ARGB8888, rot_argb32_argb32), + ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32), + /* Entry primarily for directfb */ + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD), + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD), + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE), + + ENTRY(RGB32, ARGB8888, rot_rgb32_argb32), + ENTRY(RGB32, RGB888, rot_argb32_argb32), + + ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32), + ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32), + + ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot), + ENTRY(YUY16, RGB888, rot_yuv16_argb32rot), + + ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot), + ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot), + + ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32), + ENTRY(PALETTE16, RGB888, rot_pal16_argb32), + + ENTRY(RGB15, RGB555, rot_rgb15_argb1555), + ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555), + ENTRY(RGB15, ARGB8888, rot_rgb15_argb32), + ENTRY(RGB15, RGB888, rot_rgb15_argb32), + + ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32), + ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32), + + ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32), + ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32), + + { -1 }, +}; + +} // anonymous namespace + +} // namespace osd + + +#else // defined(OSD_SDL) + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_sdl2, OSD_RENDERER_PROVIDER, "accel") } } + +#endif // defined(OSD_SDL) + + +MODULE_DEFINITION(RENDERER_SDL2, osd::video_sdl2) diff --git a/src/osd/modules/render/draw13.h b/src/osd/modules/render/draw13.h deleted file mode 100644 index 4015acca416..00000000000 --- a/src/osd/modules/render/draw13.h +++ /dev/null @@ -1,215 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Couriersud, Olivier Galibert, R. Belmont -//============================================================ -// -// draw13.h - SDL 2.0 drawing implementation -// -// SDLMAME by Olivier Galibert and R. Belmont -// -//============================================================ - -#ifndef MAME_OSD_MODULES_RENDER_DRAW13_H -#define MAME_OSD_MODULES_RENDER_DRAW13_H - -#pragma once - -// OSD headers -#ifndef OSD_WINDOWS -#include "window.h" -#else -#include "../windows/window.h" -typedef uint64_t HashT; -#endif - -// standard SDL headers -#include <SDL2/SDL.h> - -#include "emucore.h" -#include "render.h" - -struct quad_setup_data -{ - quad_setup_data() - : dudx(0) - , dvdx(0) - , dudy(0) - , dvdy(0) - , startu(0) - , startv(0) - , rotwidth(0) - , rotheight(0) - { - } - - void compute(const render_primitive &prim, const int prescale); - - int32_t dudx, dvdx, dudy, dvdy; - int32_t startu, startv; - int32_t rotwidth, rotheight; -}; - -//============================================================ -// Textures -//============================================================ - -class renderer_sdl2; -struct copy_info_t; - -/* texture_info holds information about a texture */ -class texture_info -{ - friend class simple_list<texture_info>; -public: - texture_info(renderer_sdl2 *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const uint32_t flags); - ~texture_info(); - - void set_data(const render_texinfo &texsource, const uint32_t flags); - void render_quad(const render_primitive &prim, const int x, const int y); - bool matches(const render_primitive &prim, const quad_setup_data &setup); - - copy_info_t *compute_size_type(); - - void *m_pixels; // pixels for the texture - int m_pitch; - - copy_info_t *m_copyinfo; - quad_setup_data m_setup; - - osd_ticks_t m_last_access; - - int raw_width() const { return m_texinfo.width; } - int raw_height() const { return m_texinfo.height; } - - texture_info *next() { return m_next; } - const render_texinfo &texinfo() const { return m_texinfo; } - render_texinfo &texinfo() { return m_texinfo; } - - HashT hash() const { return m_hash; } - uint32_t flags() const { return m_flags; } - // FIXME: - bool is_pixels_owned() const; - -private: - void set_coloralphamode(SDL_Texture *texture_id, const render_color *color); - - Uint32 m_sdl_access; - renderer_sdl2 * m_renderer; - render_texinfo m_texinfo; // copy of the texture info - HashT m_hash; // hash value for the texture (must be >= pointer size) - uint32_t m_flags; // rendering flags - - SDL_Texture * m_texture_id; - bool m_is_rotated; - - int m_format; // texture format - SDL_BlendMode m_sdl_blendmode; - - texture_info * m_next; // next texture in the list -}; - -//============================================================ -// TEXCOPY FUNCS -//============================================================ - -enum SDL_TEXFORMAT_E -{ - SDL_TEXFORMAT_ARGB32 = 0, - SDL_TEXFORMAT_RGB32, - SDL_TEXFORMAT_RGB32_PALETTED, - SDL_TEXFORMAT_YUY16, - SDL_TEXFORMAT_YUY16_PALETTED, - SDL_TEXFORMAT_PALETTE16, - SDL_TEXFORMAT_RGB15, - SDL_TEXFORMAT_RGB15_PALETTED, - SDL_TEXFORMAT_PALETTE16A, - SDL_TEXFORMAT_PALETTE16_ARGB1555, - SDL_TEXFORMAT_RGB15_ARGB1555, - SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555, - SDL_TEXFORMAT_LAST = SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555 -}; - -#include "blit13.h" - -struct copy_info_t -{ - int src_fmt; - Uint32 dst_fmt; - const blit_base *blitter; - Uint32 bm_mask; - const char *srcname; - const char *dstname; - /* Statistics */ - uint64_t pixel_count; - int64_t time; - int samples; - int perf; - /* list */ - copy_info_t *next; -}; - -/* renderer_sdl2 is the information about SDL for the current screen */ -class renderer_sdl2 : public osd_renderer -{ -public: - renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags); - - virtual ~renderer_sdl2() - { - destroy_all_textures(); - SDL_DestroyRenderer(m_sdl_renderer); - m_sdl_renderer = nullptr; - } - - static void init(running_machine &machine); - static void exit(); - - virtual int create() override; - virtual int draw(const int update) override; - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; - virtual render_primitive_list *get_primitives() override; - - int RendererSupportsFormat(Uint32 format, Uint32 access, const char *sformat); - - SDL_Renderer * m_sdl_renderer; - - static copy_info_t* s_blit_info[SDL_TEXFORMAT_LAST+1]; - -private: - void expand_copy_info(const copy_info_t *list); - void add_list(copy_info_t **head, const copy_info_t *element, Uint32 bm); - - void render_quad(texture_info *texture, const render_primitive &prim, const int x, const int y); - - texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup); - texture_info *texture_update(const render_primitive &prim); - - void destroy_all_textures(); - - int32_t m_blittimer; - - - simple_list<texture_info> m_texlist; // list of active textures - - float m_last_hofs; - float m_last_vofs; - - int m_width; - int m_height; - - osd_dim m_blit_dim; - - struct - { - Uint32 format; - int status; - } fmt_support[30]; - - // Stats - int64_t m_last_blit_time; - int64_t m_last_blit_pixels; - - static bool s_blit_info_initialized; - static const copy_info_t s_blit_info_default[]; -}; - -#endif // MAME_OSD_MODULES_RENDER_DRAW13_H diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp index d42f4739d26..aa4cf95f7be 100644 --- a/src/osd/modules/render/drawbgfx.cpp +++ b/src/osd/modules/render/drawbgfx.cpp @@ -5,24 +5,7 @@ // drawbgfx.cpp - BGFX renderer // //============================================================ -#include <bx/math.h> -#include <bx/readerwriter.h> -#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) -// standard windows headers -#include <windows.h> -#if defined(SDLMAME_WIN32) -#include <SDL2/SDL_syswm.h> -#endif -#else -#if defined(OSD_MAC) -extern void *GetOSWindow(void *wincontroller); -#else -#include <SDL2/SDL_syswm.h> -#endif -#endif - -#include "emu.h" #include "drawbgfx.h" // render/bgfx @@ -41,8 +24,10 @@ extern void *GetOSWindow(void *wincontroller); // render #include "aviwrite.h" #include "bgfxutil.h" +#include "render_module.h" // emu +#include "emu.h" #include "config.h" #include "render.h" #include "rendutil.h" @@ -54,6 +39,23 @@ extern void *GetOSWindow(void *wincontroller); #include "modules/lib/osdobj_common.h" #include "window.h" +#include <bx/math.h> +#include <bx/readerwriter.h> + +#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) +// standard windows headers +#include <windows.h> +#if defined(SDLMAME_WIN32) +#include <SDL2/SDL_syswm.h> +#endif +#else +#if defined(OSD_MAC) +extern void *GetOSWindow(void *wincontroller); +#else +#include <SDL2/SDL_syswm.h> +#endif +#endif + #include <bgfx/bgfx.h> #include <bgfx/platform.h> @@ -63,274 +65,447 @@ extern void *GetOSWindow(void *wincontroller); //============================================================ -// DEBUGGING +// OSD MODULE //============================================================ -//============================================================ -// CONSTANTS -//============================================================ +namespace osd { -uint16_t const renderer_bgfx::CACHE_SIZE = 1024; -uint32_t const renderer_bgfx::PACKABLE_SIZE = 128; -uint32_t const renderer_bgfx::WHITE_HASH = 0x87654321; -char const *const renderer_bgfx::WINDOW_PREFIX = "Window 0, "; +namespace { -//============================================================ -// MACROS -//============================================================ +class video_bgfx : public osd_module, public render_module +{ +public: + video_bgfx() + : osd_module(OSD_RENDERER_PROVIDER, "bgfx") + , m_options(nullptr) + , m_max_texture_size(0) + , m_bgfx_library_initialized(false) + { + } + ~video_bgfx() { exit(); } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE; } + +private: + void load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode); + void save_config(config_type cfg_type, util::xml::data_node *parentnode); + + bool init_bgfx_library(osd_window &window); + + static bool set_platform_data(bgfx::PlatformData &platform_data, osd_window const &window); + + util::notifier<util::xml::data_node const &> m_load_notifier; + util::notifier<util::xml::data_node &> m_save_notifier; + util::xml::file::ptr m_persistent_settings; + osd_options const *m_options; + uint32_t m_max_texture_size; + bool m_bgfx_library_initialized; +}; -#define GIBBERISH (0) -#define SCENE_VIEW (0) //============================================================ -// STATICS +// video_bgfx::init //============================================================ -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 }; -uint32_t renderer_bgfx::s_max_texture_size = 16384; // Relatively safe default on modern GPUs +int video_bgfx::init(osd_interface &osd, osd_options const &options) +{ + m_options = &options; + m_persistent_settings = util::xml::file::create(); + + // Check that BGFX directory exists + char const *const bgfx_path = options.bgfx_path(); + osd::directory::ptr directory = osd::directory::open(bgfx_path); + if (!directory) + { + 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 -1; + } + directory.reset(); + + // 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 -1; + } + + m_max_texture_size = 16384; // Relatively safe default on modern GPUs + + // Register configuration handlers - do this last because it can't be undone + downcast<osd_common_t &>(osd).machine().configuration().config_register( + "bgfx", + configuration_manager::load_delegate(&video_bgfx::load_config, this), + configuration_manager::save_delegate(&video_bgfx::save_config, this)); + + return 0; +} + //============================================================ -// renderer_bgfx - constructor +// video_bgfx::exit //============================================================ -renderer_bgfx::renderer_bgfx(std::shared_ptr<osd_window> w) - : osd_renderer(w, FLAG_NONE) - , m_options(downcast<osd_options &>(w->machine().options())) - , m_framebuffer(nullptr) - , m_texture_cache(nullptr) - , m_dimensions(0, 0) - , m_textures(nullptr) - , m_targets(nullptr) - , m_shaders(nullptr) - , m_effects(nullptr) - , m_chains(nullptr) - , m_ortho_view(nullptr) - , m_max_view(0) - , m_view_width(1) - , m_view_height(1) - , m_avi_view(nullptr) - , m_avi_writer(nullptr) - , m_avi_target(nullptr) +void video_bgfx::exit() { + if (m_bgfx_library_initialized) + { + osd_printf_verbose("Shutting down BGFX library\n"); + imguiDestroy(); + bgfx::shutdown(); + m_bgfx_library_initialized = false; + } + m_max_texture_size = 0; + m_persistent_settings.reset(); + m_options = nullptr; } + //============================================================ -// renderer_bgfx - destructor +// video_bgfx::create //============================================================ -renderer_bgfx::~renderer_bgfx() +std::unique_ptr<osd_renderer> video_bgfx::create(osd_window &window) { - bgfx::reset(0, 0, BGFX_RESET_NONE); - - if (m_avi_writer != nullptr && m_avi_writer->recording()) + // hacky - reinitialise when window 0 is created + // this is the cause of the fullscreen toggle crash on Linux + if ((window.index() == 0) && m_bgfx_library_initialized) { - m_avi_writer->stop(); + osd_printf_verbose("Shutting down BGFX library to recreate window 0\n"); + imguiDestroy(); + bgfx::shutdown(); + m_bgfx_library_initialized = false; + m_max_texture_size = 0; + } - m_targets->destroy_target("avibuffer0"); - m_avi_target = nullptr; + // start BGFX if this is the first window + if (!m_bgfx_library_initialized) + { + osd_printf_verbose("Initializing BGFX library\n"); + assert(window.index() == 0); // bad things will happen otherwise + if (!init_bgfx_library(window)) + { + osd_printf_error("BGFX library initialization failed\n"); + return nullptr; + } + m_bgfx_library_initialized = true; + } - bgfx::destroy(m_avi_texture); + return std::make_unique<renderer_bgfx>( + window, + *m_options, + m_load_notifier, + m_save_notifier, + *m_persistent_settings, + m_max_texture_size); +} - delete m_avi_writer; - delete [] m_avi_data; - delete m_avi_view; - } - // Cleanup. - if (m_ortho_view) - delete m_ortho_view; +//============================================================ +// video_bgfx::load_config +//============================================================ - delete m_chains; - delete m_effects; - delete m_shaders; - delete m_textures; - delete m_targets; +void video_bgfx::load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode) +{ + if ((cfg_type == config_type::SYSTEM) && parentnode) + m_load_notifier(*parentnode); } +//============================================================ +// video_bgfx::save_config +//============================================================ + +void video_bgfx::save_config(config_type cfg_type, util::xml::data_node *parentnode) +{ + if (cfg_type == config_type::SYSTEM) + m_save_notifier(*parentnode); +} + //============================================================ -// renderer_bgfx::init_bgfx_library +// video_bgfx::init_bgfx_library //============================================================ -void renderer_bgfx::init_bgfx_library() +bool video_bgfx::init_bgfx_library(osd_window &window) { - std::string backend(m_options.bgfx_backend()); + osd_dim const wdim = window.get_size(); 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.width = wdim.width(); + init.resolution.height = wdim.height(); init.resolution.numBackBuffers = 1; init.resolution.reset = BGFX_RESET_NONE; - init.platformData = m_platform_data; - if (backend == "auto") + if (!set_platform_data(init.platformData, window)) { + osd_printf_error("Setting BGFX platform data failed\n"); + return false; } + + std::string_view const backend(m_options->bgfx_backend()); + if (backend == "auto") + ; // do nothing 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()); - } + osd_printf_warning("Unknown BGFX backend type '%s', going with auto-detection.\n", backend); + + if (!bgfx::init(init)) + return false; - 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::reset(wdim.width(), wdim.height(), 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); - const bgfx::Caps* caps = bgfx::getCaps(); - s_max_texture_size = caps->limits.maxTextureSize; + // Get actual maximum texture size + bgfx::Caps const *const caps = bgfx::getCaps(); + m_max_texture_size = caps->limits.maxTextureSize; ScreenVertex::init(); imguiCreate(); -} + return true; +} //============================================================ -// Utilities for setting up window handles +// Utility for setting up window handle //============================================================ -#ifdef OSD_WINDOWS -inline void winSetHwnd(bgfx::PlatformData &platform_data, ::HWND _window) +bool video_bgfx::set_platform_data(bgfx::PlatformData &platform_data, osd_window const &window) { - platform_data.ndt = NULL; - platform_data.nwh = _window; - platform_data.context = NULL; - platform_data.backBuffer = NULL; - platform_data.backBufferDS = NULL; - bgfx::setPlatformData(platform_data); -} +#if defined(OSD_WINDOWS) + platform_data.ndt = nullptr; + platform_data.nwh = dynamic_cast<win_window_info const &>(window).platform_window(); #elif defined(OSD_MAC) -inline void macSetWindow(bgfx::PlatformData &platform_data, void *_window) -{ - platform_data.ndt = NULL; - platform_data.nwh = GetOSWindow(_window); - platform_data.context = NULL; - platform_data.backBuffer = NULL; - platform_data.backBufferDS = NULL; + platform_data.ndt = nullptr; + platform_data.nwh = GetOSWindow(dynamic_cast<mac_window_info const &>(window).platform_window()); +#else // defined(OSD_*) + SDL_SysWMinfo wmi; + SDL_VERSION(&wmi.version); + if (!SDL_GetWindowWMInfo(dynamic_cast<sdl_window_info const &>(window).platform_window(), &wmi)) + { + osd_printf_error("Error getting SDL window info: %s\n", SDL_GetError()); + return false; + } + +#if BX_PLATFORM_LINUX || BX_PLATFORM_BSD + platform_data.ndt = wmi.info.x11.display; + platform_data.nwh = (void *)uintptr_t(wmi.info.x11.window); +#elif BX_PLATFORM_OSX + platform_data.ndt = nullptr; + platform_data.nwh = wmi.info.cocoa.window; +#elif BX_PLATFORM_WINDOWS + platform_data.ndt = nullptr; + platform_data.nwh = wmi.info.win.window; +#else // BX_PLATFORM_* +#error "Unsupported BX platform" +#endif // BX_PLATFORM_* +#endif // defined(OSD_*) + + platform_data.context = nullptr; + platform_data.backBuffer = nullptr; + platform_data.backBufferDS = nullptr; bgfx::setPlatformData(platform_data); + + return true; } -#elif defined(OSD_SDL) -static void* sdlNativeWindowHandle(SDL_Window* _window) + +} // anonymous namespace + +} // namespace osd + +MODULE_DEFINITION(RENDERER_BGFX, osd::video_bgfx) + + + +//============================================================ +// CONSTANTS +//============================================================ + +uint16_t const renderer_bgfx::CACHE_SIZE = 1024; +uint32_t const renderer_bgfx::PACKABLE_SIZE = 128; +uint32_t const renderer_bgfx::WHITE_HASH = 0x87654321; +char const *const renderer_bgfx::WINDOW_PREFIX = "Window 0, "; + + + +//============================================================ +// MACROS +//============================================================ + +#define GIBBERISH (0) +#define SCENE_VIEW (0) + + + +//============================================================ +// STATICS +//============================================================ + +uint32_t renderer_bgfx::s_current_view = 0; +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 }; + + + +//============================================================ +// helper for getting native platform window +//============================================================ + +#ifdef OSD_SDL +static void *sdlNativeWindowHandle(SDL_Window *window) { SDL_SysWMinfo wmi; SDL_VERSION(&wmi.version); - if (!SDL_GetWindowWMInfo(_window, &wmi)) - { + if (!SDL_GetWindowWMInfo(window, &wmi)) return nullptr; - } -# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD || BX_PLATFORM_RPI +#if BX_PLATFORM_LINUX || BX_PLATFORM_BSD || BX_PLATFORM_RPI return (void*)wmi.info.x11.window; -# elif BX_PLATFORM_OSX +#elif BX_PLATFORM_OSX return wmi.info.cocoa.window; -# elif BX_PLATFORM_WINDOWS +#elif BX_PLATFORM_WINDOWS return wmi.info.win.window; -# elif BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_ANDROID +#elif BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_ANDROID return nullptr; -# endif // BX_PLATFORM_ +#endif // BX_PLATFORM_* } +#endif // OSD_SDL -inline bool sdlSetWindow(bgfx::PlatformData &platform_data, SDL_Window* _window) + + +//============================================================ +// renderer_bgfx - constructor +//============================================================ + +renderer_bgfx::renderer_bgfx( + osd_window &window, + const osd_options &options, + util::notifier<util::xml::data_node const &> &load_notifier, + util::notifier<util::xml::data_node &> &save_notifier, + util::xml::data_node &persistent_settings, + uint32_t max_texsize) + : osd_renderer(window) + , m_options(options) + , m_max_texture_size(max_texsize) + , m_framebuffer(nullptr) + , m_texture_cache(nullptr) + , m_dimensions(0, 0) + , m_max_view(0) + , m_view_width(1) + , m_view_height(1) + , m_avi_view(nullptr) + , m_avi_writer(nullptr) + , m_avi_target(nullptr) + , m_load_sub(load_notifier.subscribe(delegate<void (util::xml::data_node const &)>(&renderer_bgfx::load_config, this))) + , m_save_sub(save_notifier.subscribe(delegate<void (util::xml::data_node &)>(&renderer_bgfx::save_config, this))) + , m_persistent_settings(persistent_settings) { - SDL_SysWMinfo wmi; - SDL_VERSION(&wmi.version); - if (!SDL_GetWindowWMInfo(_window, &wmi) ) + // load settings if recreated after fullscreen toggle + util::xml::data_node *windownode = m_persistent_settings.get_child("window"); + while (windownode) { - return false; + if (windownode->get_attribute_int("index", -1) != window.index()) + { + windownode = windownode->get_next_sibling("window"); + } + else + { + if (!m_config) + { + m_config = util::xml::file::create(); + windownode->copy_into(*m_config); + } + std::exchange(windownode, windownode->get_next_sibling("window"))->delete_node(); + } } - -# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD - platform_data.ndt = wmi.info.x11.display; - platform_data.nwh = (void*)(uintptr_t)wmi.info.x11.window; -# elif BX_PLATFORM_OSX - platform_data.ndt = NULL; - platform_data.nwh = wmi.info.cocoa.window; -# elif BX_PLATFORM_WINDOWS - platform_data.ndt = NULL; - platform_data.nwh = wmi.info.win.window; -# endif // BX_PLATFORM_ - platform_data.context = NULL; - platform_data.backBuffer = NULL; - platform_data.backBufferDS = NULL; - bgfx::setPlatformData(platform_data); - - return true; } -#endif //============================================================ -// renderer_bgfx::create +// renderer_bgfx - destructor //============================================================ -int renderer_bgfx::create() +renderer_bgfx::~renderer_bgfx() { - std::shared_ptr<osd_window> win = assert_window(); - osd_dim wdim = win->get_size(); - const uint32_t width = wdim.width(); - const uint32_t height = wdim.height(); - s_width[win->index()] = width; - s_height[win->index()] = height; - m_dimensions = wdim; + // persist settings across fullscreen toggle + if (m_chains) + m_chains->save_config(m_persistent_settings); + else if (m_config) + m_config->get_first_child()->copy_into(m_persistent_settings); - if (s_bgfx_library_initialized) - exit(); + bgfx::reset(0, 0, BGFX_RESET_NONE); - if (win->index() == 0) + if (m_avi_writer != nullptr && m_avi_writer->recording()) { -#ifdef OSD_WINDOWS - winSetHwnd(m_platform_data, std::static_pointer_cast<win_window_info>(win)->platform_window()); -#elif defined(OSD_MAC) - macSetWindow(m_platform_data, std::static_pointer_cast<mac_window_info>(win)->platform_window()); -#else - sdlSetWindow(m_platform_data, std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()); -#endif + m_avi_writer->stop(); + + m_targets->destroy_target("avibuffer0"); + m_avi_target = nullptr; - init_bgfx_library(); + bgfx::destroy(m_avi_texture); + + delete m_avi_writer; + delete [] m_avi_data; + delete m_avi_view; } +} + + + +//============================================================ +// renderer_bgfx::create +//============================================================ + +int renderer_bgfx::create() +{ + const osd_dim wdim = window().get_size(); + s_width[window().index()] = wdim.width(); + s_height[window().index()] = wdim.height(); + m_dimensions = wdim; // finish creating the renderer - m_textures = new texture_manager(); - m_targets = new target_manager(*m_textures); + m_textures = std::make_unique<texture_manager>(); + m_targets = std::make_unique<target_manager>(*m_textures); - m_shaders = new shader_manager(); - m_effects = new effect_manager(*m_shaders); + m_shaders = std::make_unique<shader_manager>(); + m_effects = std::make_unique<effect_manager>(*m_shaders); // Create program from shaders. m_gui_effect[0] = m_effects->get_or_load_effect(m_options, "gui_opaque"); @@ -343,23 +518,32 @@ int renderer_bgfx::create() 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) + if (window().index() != 0) { #ifdef OSD_WINDOWS - m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), s_width[win->index()], s_height[win->index()]); + m_framebuffer = m_targets->create_backbuffer(dynamic_cast<win_window_info &>(window()).platform_window(), s_width[window().index()], s_height[window().index()]); #elif defined(OSD_MAC) - 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()]); + m_framebuffer = m_targets->create_backbuffer(GetOSWindow(dynamic_cast<mac_window_info &>(window()).platform_window()), s_width[window().index()], s_height[window().index()]); #else - 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()]); + m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(dynamic_cast<sdl_window_info &>(window()).platform_window()), s_width[window().index()], s_height[window().index()]); #endif - bgfx::touch(win->index()); + bgfx::touch(window().index()); if (m_ortho_view) m_ortho_view->set_backbuffer(m_framebuffer); } - const uint32_t max_prescale_size = std::min(2u * std::max(width, height), s_max_texture_size); - m_chains = new chain_manager(win->machine(), m_options, *m_textures, *m_targets, *m_effects, win->index(), *this, win->prescale(), max_prescale_size); + const uint32_t max_prescale_size = std::min(2u * std::max(wdim.width(), wdim.height()), m_max_texture_size); + m_chains = std::make_unique<chain_manager>( + window().machine(), + m_options, + *m_textures, + *m_targets, + *m_effects, + window().index(), + *this, + window().prescale(), + max_prescale_size); m_sliders_dirty = true; uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT; @@ -368,12 +552,6 @@ 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)); - // Register configuration handlers - win->machine().configuration().config_register( - "bgfx", - configuration_manager::load_delegate(&renderer_bgfx::load_config, this), - configuration_manager::save_delegate(&renderer_bgfx::save_config, this)); - return 0; } @@ -385,16 +563,12 @@ int renderer_bgfx::create() void renderer_bgfx::record() { - std::shared_ptr<osd_window> win = assert_window(); - - if (win->index() > 0) - { + if (window().index() > 0) return; - } if (m_avi_writer == nullptr) { - m_avi_writer = new avi_write(win->machine(), s_width[0], s_height[0]); + m_avi_writer = new avi_write(window().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]); } @@ -421,47 +595,6 @@ void renderer_bgfx::record() } } -bool renderer_bgfx::init(running_machine &machine) -{ - 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_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; - } - - return false; -} - -void renderer_bgfx::exit() -{ - imguiDestroy(); - bgfx::shutdown(); - s_bgfx_library_initialized = false; -} - //============================================================ // drawsdl_xy_to_render_target //============================================================ @@ -891,16 +1024,13 @@ uint32_t renderer_bgfx::u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a int renderer_bgfx::draw(int update) { - std::shared_ptr<osd_window> win = assert_window(); - - int window_index = win->index(); + int window_index = window().index(); m_seen_views.clear(); - if (m_ortho_view) { + if (m_ortho_view) m_ortho_view->set_index(UINT_MAX); - } - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); s_width[window_index] = wdim.width(); s_height[window_index] = wdim.height(); @@ -910,9 +1040,9 @@ int renderer_bgfx::draw(int update) s_current_view = 0; } - win->m_primlist->acquire_lock(); - uint32_t num_screens = m_chains->update_screen_textures(s_current_view, win->m_primlist->first(), *win.get()); - win->m_primlist->release_lock(); + window().m_primlist->acquire_lock(); + uint32_t num_screens = m_chains->update_screen_textures(s_current_view, window().m_primlist->first(), window()); + window().m_primlist->release_lock(); bool skip_frame = update_dimensions(); if (skip_frame) @@ -935,7 +1065,7 @@ int renderer_bgfx::draw(int update) m_config.reset(); } - uint32_t chain_view_count = m_chains->process_screen_chains(s_current_view, *win.get()); + uint32_t chain_view_count = m_chains->process_screen_chains(s_current_view, window()); s_current_view += chain_view_count; } @@ -948,12 +1078,12 @@ int renderer_bgfx::draw(int update) s_current_view = m_max_view; } - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // Mark our texture atlas as dirty if we need to do so bool atlas_valid = update_atlas(); - render_primitive *prim = win->m_primlist->first(); + render_primitive *prim = window().m_primlist->first(); std::vector<void*> sources; while (prim != nullptr) { @@ -1002,7 +1132,7 @@ int renderer_bgfx::draw(int update) } } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); // This dummy draw call is here to make sure that view 0 is cleared // if no other draw calls are submitted to view 0. @@ -1020,7 +1150,7 @@ int renderer_bgfx::draw(int update) } } - if (win->index() == osd_common_t::s_window_list.size() - 1) + if (window().index() == osd_common_t::window_list().size() - 1) { bgfx::frame(); } @@ -1050,8 +1180,7 @@ void renderer_bgfx::update_recording() void renderer_bgfx::add_audio_to_recording(const int16_t *buffer, int samples_this_frame) { - std::shared_ptr<osd_window> win = assert_window(); - if (m_avi_writer != nullptr && m_avi_writer->recording() && win->index() == 0) + if (m_avi_writer != nullptr && m_avi_writer->recording() && window().index() == 0) { m_avi_writer->audio_frame(buffer, samples_this_frame); } @@ -1059,9 +1188,7 @@ void renderer_bgfx::add_audio_to_recording(const int16_t *buffer, int samples_th bool renderer_bgfx::update_dimensions() { - std::shared_ptr<osd_window> win = assert_window(); - - const uint32_t window_index = win->index(); + const uint32_t window_index = window().index(); const uint32_t width = s_width[window_index]; const uint32_t height = s_height[window_index]; @@ -1070,15 +1197,15 @@ bool renderer_bgfx::update_dimensions() bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); m_dimensions = osd_dim(width, height); - if (win->index() != 0) + if (window().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); + m_framebuffer = m_targets->create_backbuffer(dynamic_cast<win_window_info &>(window()).platform_window(), width, height); #elif defined(OSD_MAC) - m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), width, height); + m_framebuffer = m_targets->create_backbuffer(GetOSWindow(dynamic_cast<mac_window_info &>(window()).platform_window()), width, height); #else - m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), width, height); + m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(dynamic_cast<sdl_window_info &>(window()).platform_window()), width, height); #endif if (m_ortho_view) { @@ -1100,7 +1227,7 @@ void renderer_bgfx::setup_ortho_view() { if (!m_ortho_view) { - m_ortho_view = new bgfx_ortho_view(this, 0, m_framebuffer, m_seen_views); + m_ortho_view = std::make_unique<bgfx_ortho_view>(this, 0, m_framebuffer, m_seen_views); } if (m_ortho_view->get_index() == UINT_MAX) { @@ -1113,10 +1240,6 @@ void renderer_bgfx::setup_ortho_view() render_primitive_list *renderer_bgfx::get_primitives() { - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - // determines whether the screen container is transformed by the chain's shaders bool chain_transform = false; @@ -1127,12 +1250,12 @@ render_primitive_list *renderer_bgfx::get_primitives() chain_transform = chain->transform(); } - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (wdim.width() > 0 && wdim.height() > 0) - win->target()->set_bounds(wdim.width(), wdim.height(), win->pixel_aspect()); + window().target()->set_bounds(wdim.width(), wdim.height(), window().pixel_aspect()); - win->target()->set_transform_container(!chain_transform); - return &win->target()->get_primitives(); + window().target()->set_transform_container(!chain_transform); + return &window().target()->get_primitives(); } renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index) @@ -1307,9 +1430,8 @@ bool renderer_bgfx::check_for_dirty_atlas() { bool atlas_dirty = false; - std::shared_ptr<osd_window> win = assert_window(); std::map<uint32_t, rectangle_packer::packable_rectangle> acquired_infos; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { bool pack = prim.packable(PACKABLE_SIZE); if (prim.type == render_primitive::QUAD && prim.texture.base != nullptr && pack) @@ -1410,33 +1532,31 @@ uint32_t renderer_bgfx::get_window_height(uint32_t index) const } -void renderer_bgfx::load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode) +void renderer_bgfx::load_config(util::xml::data_node const &parentnode) { - if ((cfg_type == config_type::SYSTEM) && parentnode) + util::xml::data_node const *windownode = parentnode.get_child("window"); + while (windownode) { - auto const win = try_getwindow(); - if (win) + if (windownode->get_attribute_int("index", -1) != window().index()) { - util::xml::data_node const *windownode = parentnode->get_child("window"); - while (windownode) - { - if (windownode->get_attribute_int("index", -1) != win->index()) - { - windownode = windownode->get_next_sibling("window"); - continue; - } - - m_config = util::xml::file::create(); - windownode->copy_into(*m_config); - break; - } + windownode = windownode->get_next_sibling("window"); + continue; } + + if (!m_config) + m_config = util::xml::file::create(); + else + m_config->get_first_child()->delete_node(); + windownode->copy_into(*m_config); + break; } } -void renderer_bgfx::save_config(config_type cfg_type, util::xml::data_node *parentnode) +void renderer_bgfx::save_config(util::xml::data_node &parentnode) { - if (cfg_type == config_type::SYSTEM) - m_chains->save_config(*parentnode); + if (m_config) + m_config->get_first_child()->copy_into(parentnode); + else + m_chains->save_config(parentnode); } diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h index 15b0d6e158b..14e076843a7 100644 --- a/src/osd/modules/render/drawbgfx.h +++ b/src/osd/modules/render/drawbgfx.h @@ -5,8 +5,6 @@ #pragma once -#include <bgfx/bgfx.h> - #include "binpacker.h" #include "bgfx/chain.h" #include "bgfx/chainmanager.h" @@ -15,6 +13,10 @@ #include "modules/osdwindow.h" +#include "notifier.h" + +#include <bgfx/bgfx.h> + #include <map> #include <memory> #include <vector> @@ -35,12 +37,15 @@ class avi_write; class renderer_bgfx : public osd_renderer, public slider_dirty_notifier { public: - renderer_bgfx(std::shared_ptr<osd_window> w); + renderer_bgfx( + osd_window &window, + const osd_options &options, + util::notifier<util::xml::data_node const &> &load_notifier, + util::notifier<util::xml::data_node &> &save_notifier, + util::xml::data_node &persistent_settings, + uint32_t max_texsize); virtual ~renderer_bgfx(); - static bool init(running_machine &machine); - static void exit(); - virtual int create() override; virtual int draw(const int update) override; @@ -73,8 +78,6 @@ private: BUFFER_DONE }; - 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(); @@ -103,11 +106,11 @@ private: void process_atlas_packs(std::vector<std::vector<rectangle_packer::packed_rectangle>>& packed); uint32_t get_texture_hash(render_primitive *prim); - void load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode); - void save_config(config_type cfg_type, util::xml::data_node *parentnode); + void load_config(util::xml::data_node const &parentnode); + void save_config(util::xml::data_node &parentnode); - osd_options& m_options; - bgfx::PlatformData m_platform_data; + const osd_options& m_options; + const uint32_t m_max_texture_size; bgfx_target *m_framebuffer; bgfx_texture *m_texture_cache; @@ -115,11 +118,11 @@ private: // Original display_mode osd_dim m_dimensions; - texture_manager *m_textures; - target_manager *m_targets; - shader_manager *m_shaders; - effect_manager *m_effects; - chain_manager *m_chains; + std::unique_ptr<texture_manager> m_textures; + std::unique_ptr<target_manager> m_targets; + std::unique_ptr<shader_manager> m_shaders; + std::unique_ptr<effect_manager> m_effects; + std::unique_ptr<chain_manager> m_chains; bgfx_effect *m_gui_effect[4]; bgfx_effect *m_screen_effect[4]; @@ -130,7 +133,7 @@ private: rectangle_packer m_packer; uint32_t m_white[16*16]; - bgfx_view *m_ortho_view; + std::unique_ptr<bgfx_view> m_ortho_view; uint32_t m_max_view; uint16_t m_view_width; uint16_t m_view_height; @@ -141,17 +144,19 @@ private: bgfx::TextureHandle m_avi_texture; bitmap_rgb32 m_avi_bitmap; uint8_t *m_avi_data; + std::unique_ptr<util::xml::file> m_config; + const util::notifier_subscription m_load_sub; + const util::notifier_subscription m_save_sub; + util::xml::data_node &m_persistent_settings; static const uint16_t CACHE_SIZE; static const uint32_t PACKABLE_SIZE; static const uint32_t WHITE_HASH; static uint32_t s_current_view; - static bool s_bgfx_library_initialized; static uint32_t s_width[16]; static uint32_t s_height[16]; - static uint32_t s_max_texture_size; }; #endif // MAME_RENDER_DRAWBGFX_H diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp index f9f03d9efc0..4bc646408b3 100644 --- a/src/osd/modules/render/drawd3d.cpp +++ b/src/osd/modules/render/drawd3d.cpp @@ -13,21 +13,120 @@ #include "rendutil.h" #include "screen.h" -#include "aviio.h" - // MAMEOS headers -#include "winmain.h" -#include "window.h" #include "drawd3d.h" -#include "modules/render/d3d/d3dhlsl.h" + +#include "d3d/d3dhlsl.h" + +#include "render_module.h" + +// from OSD implementation +#include "window.h" +#include "winmain.h" + +// general OSD headers #include "modules/monitor/monitor_module.h" + +// lib/util +#include "aviio.h" + #include <utility> + +//============================================================ +// OSD MODULE +//============================================================ + +namespace osd { + +namespace { + +class video_d3d : public osd_module, public render_module +{ +public: + video_d3d() + : osd_module(OSD_RENDERER_PROVIDER, "d3d") + , m_options(nullptr) + { + } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE; } + +private: + using d3d9_create_fn = IDirect3D9 *(WINAPI *)(UINT); + + dynamic_module::ptr m_d3d9_dll; + Microsoft::WRL::ComPtr<IDirect3D9> m_d3dobj; + osd_options const *m_options; +}; + + //============================================================ -// TYPE DEFINITIONS +// video_d3d::init //============================================================ -typedef IDirect3D9* (WINAPI *d3d9_create_fn)(UINT); +int video_d3d::init(osd_interface &osd, osd_options const &options) +{ + m_options = &options; + + m_d3d9_dll = dynamic_module::open({ "d3d9.dll" }); + auto const d3d9_create_ptr = m_d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9"); + if (!d3d9_create_ptr) + { + osd_printf_warning("Direct3D: Could not find Direct3DCreate9 function in d3d9.dll\n"); + m_d3d9_dll.reset(); + m_options = nullptr; + return -1; + } + + m_d3dobj.Attach((d3d9_create_ptr)(D3D_SDK_VERSION)); + if (!m_d3dobj) + { + osd_printf_warning("Direct3D: Unable to initialize Direct3D 9\n"); + m_d3d9_dll.reset(); + m_options = nullptr; + return -1; + } + + osd_printf_verbose("Direct3D: Using Direct3D 9\n"); + + return 0; +} + + +//============================================================ +// video_d3d::exit +//============================================================ + +void video_d3d::exit() +{ + m_d3dobj.Reset(); + m_d3d9_dll.reset(); + m_options = nullptr; +} + + +//============================================================ +// video_d3d::create +//============================================================ + +std::unique_ptr<osd_renderer> video_d3d::create(osd_window &window) +{ + return std::make_unique<renderer_d3d9>(window, m_d3dobj); +} + +} // anonymous namespace + +} // namespace osd + +MODULE_DEFINITION(RENDERER_D3D, osd::video_d3d) + //============================================================ @@ -116,13 +215,6 @@ static inline uint32_t ycc_to_rgb(uint8_t y, uint8_t cb, uint8_t cr) //============================================================ -// drawd3d_init -//============================================================ - -static d3d_base *d3dintf = nullptr; // FIX ME - - -//============================================================ // drawd3d_window_init //============================================================ @@ -174,60 +266,22 @@ void renderer_d3d9::save() render_primitive_list *renderer_d3d9::get_primitives() { RECT client; - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - - HWND hWnd = std::static_pointer_cast<win_window_info>(win)->platform_window(); + HWND hWnd = dynamic_cast<win_window_info &>(window()).platform_window(); if (IsIconic(hWnd)) return nullptr; - GetClientRectExceptMenu(hWnd, &client, win->fullscreen()); + GetClientRectExceptMenu(hWnd, &client, window().fullscreen()); if (rect_width(&client) > 0 && rect_height(&client) > 0) { - win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect()); - win->target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); + window().target()->set_bounds(rect_width(&client), rect_height(&client), window().pixel_aspect()); + window().target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); } if (m_shaders != nullptr) { // do not transform primitives (scale, offset) if shaders are enabled, the shaders will handle the transformation - win->target()->set_transform_container(!m_shaders->enabled()); + window().target()->set_transform_container(!m_shaders->enabled()); } - return &win->target()->get_primitives(); -} - - -//============================================================ -// renderer_d3d9::init -//============================================================ - -bool renderer_d3d9::init(running_machine &machine) -{ - d3dintf = new d3d_base; - - d3dintf->d3d9_dll = osd::dynamic_module::open({ "d3d9.dll" }); - - d3d9_create_fn d3d9_create_ptr = d3dintf->d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9"); - if (d3d9_create_ptr == nullptr) - { - delete d3dintf; - d3dintf = nullptr; - osd_printf_verbose("Direct3D: Unable to find Direct3D 9 runtime library\n"); - return true; - } - - d3dintf->d3dobj = (*d3d9_create_ptr)(D3D_SDK_VERSION); - if (d3dintf->d3dobj == nullptr) - { - delete d3dintf; - d3dintf = nullptr; - osd_printf_verbose("Direct3D: Unable to initialize Direct3D 9\n"); - return true; - } - - osd_printf_verbose("Direct3D: Using Direct3D 9\n"); - - return false; + return &window().target()->get_primitives(); } @@ -412,14 +466,12 @@ void renderer_d3d9::reset_render_states() m_last_wrap = (D3DTEXTUREADDRESS)-1; } -d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d) +d3d_texture_manager::d3d_texture_manager(renderer_d3d9 &d3d, IDirect3D9 *d3dobj) + : m_renderer(d3d) + , m_default_texture(nullptr) { - m_renderer = d3d; - - m_default_texture = nullptr; - D3DCAPS9 caps; - HRESULT result = d3dintf->d3dobj->GetDeviceCaps(d3d->get_adapter(), D3DDEVTYPE_HAL, &caps); + HRESULT result = d3dobj->GetDeviceCaps(d3d.get_adapter(), D3DDEVTYPE_HAL, &caps); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result); @@ -431,27 +483,23 @@ d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d) // pick a YUV texture format m_yuv_format = D3DFMT_UYVY; - result = d3dintf->d3dobj->CheckDeviceFormat(d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY); + result = d3dobj->CheckDeviceFormat(d3d.get_adapter(), D3DDEVTYPE_HAL, d3d.get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY); if (FAILED(result)) { m_yuv_format = D3DFMT_YUY2; - result = d3dintf->d3dobj->CheckDeviceFormat(d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); + result = d3dobj->CheckDeviceFormat(d3d.get_adapter(), D3DDEVTYPE_HAL, d3d.get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); if (FAILED(result)) m_yuv_format = D3DFMT_A8R8G8B8; } osd_printf_verbose("Direct3D: YUV format = %s\n", (m_yuv_format == D3DFMT_YUY2) ? "YUY2" : (m_yuv_format == D3DFMT_UYVY) ? "UYVY" : "RGB"); - auto win = d3d->assert_window(); - // set the max texture size - win->target()->set_max_texture_size(m_texture_max_width, m_texture_max_height); - osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", (int)m_texture_max_width, (int)m_texture_max_height); + d3d.window().target()->set_max_texture_size(m_texture_max_width, m_texture_max_height); + osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", m_texture_max_width, m_texture_max_height); } void d3d_texture_manager::create_resources() { - auto win = m_renderer->assert_window(); - m_default_bitmap.allocate(8, 8); m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); @@ -470,7 +518,7 @@ void d3d_texture_manager::create_resources() texture.old_id = ~0ULL; // now create it - auto tex = std::make_unique<texture_info>(this, &texture, win->prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*this, &texture, m_renderer.window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); m_default_texture = tex.get(); m_texture_list.push_back(std::move(tex)); } @@ -479,7 +527,6 @@ void d3d_texture_manager::create_resources() void d3d_texture_manager::delete_resources() { // is part of m_texlist and will be free'd there - //delete m_default_texture; m_default_texture = nullptr; // free all textures @@ -518,11 +565,35 @@ texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, u return nullptr; } -renderer_d3d9::renderer_d3d9(std::shared_ptr<osd_window> window) - : osd_renderer(window, FLAG_NONE), m_adapter(0), m_width(0), m_height(0), m_refresh(0), m_create_error_count(0), m_device(nullptr), m_gamma_supported(0), m_pixformat(), - m_vertexbuf(nullptr), m_lockedbuf(nullptr), m_numverts(0), m_vectorbatch(nullptr), m_batchindex(0), m_numpolys(0), m_toggle(false), - m_screen_format(), m_last_texture(nullptr), m_last_texture_flags(0), m_last_blendenable(0), m_last_blendop(0), m_last_blendsrc(0), m_last_blenddst(0), m_last_filter(0), - m_last_wrap(), m_last_modmode(0), m_shaders(nullptr), m_texture_manager() +renderer_d3d9::renderer_d3d9(osd_window &window, const IDirect3D9Ptr &d3dobj) + : osd_renderer(window) + , m_d3dobj(d3dobj) + , m_adapter(0) + , m_width(0) + , m_height(0) + , m_refresh(0) + , m_create_error_count(0) + , m_post_fx_available(true) + , m_gamma_supported(0) + , m_pixformat() + , m_lockedbuf(nullptr) + , m_numverts(0) + , m_vectorbatch(nullptr) + , m_batchindex(0) + , m_numpolys(0) + , m_toggle(false) + , m_screen_format() + , m_last_texture(nullptr) + , m_last_texture_flags(0) + , m_last_blendenable(0) + , m_last_blendop(0) + , m_last_blendsrc(0) + , m_last_blenddst(0) + , m_last_filter(0) + , m_last_wrap() + , m_last_modmode(0) + , m_shaders(nullptr) + , m_texture_manager() { } @@ -537,8 +608,7 @@ int renderer_d3d9::initialize() } // create the device immediately for the full screen case (defer for window mode in update_window_size()) - auto win = assert_window(); - if (win->fullscreen() && device_create(std::static_pointer_cast<win_window_info>(win->main_window())->platform_window())) + if (window().fullscreen() && device_create(dynamic_cast<win_window_info &>(window()).main_window()->platform_window())) { return false; } @@ -548,10 +618,8 @@ int renderer_d3d9::initialize() int renderer_d3d9::pre_window_draw_check() { - auto win = assert_window(); - // if we're in the middle of resizing, leave things alone - if (win->m_resize_state == RESIZE_STATE_RESIZING) + if (window().m_resize_state == RESIZE_STATE_RESIZING) return 0; // check if shaders should be toggled @@ -575,7 +643,7 @@ int renderer_d3d9::pre_window_draw_check() } // if we have a device, check the cooperative level - if (m_device != nullptr) + if (m_device) { if (device_test_cooperative()) { @@ -584,14 +652,14 @@ int renderer_d3d9::pre_window_draw_check() } // in window mode, we need to track the window size - if (!win->fullscreen() || m_device == nullptr) + if (!window().fullscreen() || !m_device) { // if the size changes, skip this update since the render target will be out of date if (update_window_size()) return 0; // if we have no device, after updating the size, return an error so GDI can try - if (m_device == nullptr) + if (!m_device) return 1; } @@ -600,18 +668,16 @@ int renderer_d3d9::pre_window_draw_check() void d3d_texture_manager::update_textures() { - auto win = m_renderer->assert_window(); - - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *m_renderer.window().m_primlist) { if (prim.texture.base != nullptr) { texture_info *texture = find_texinfo(&prim.texture, prim.flags); if (texture == nullptr) { - int prescale = m_renderer->get_shaders()->enabled() ? 1 : win->prescale(); + int prescale = m_renderer.get_shaders()->enabled() ? 1 : m_renderer.window().prescale(); - auto tex = std::make_unique<texture_info>(this, &prim.texture, prescale, prim.flags); + auto tex = std::make_unique<texture_info>(*this, &prim.texture, prescale, prim.flags); texture = tex.get(); m_texture_list.push_back(std::move(tex)); } @@ -627,21 +693,21 @@ void d3d_texture_manager::update_textures() } } - if (!m_renderer->get_shaders()->enabled()) + if (!m_renderer.get_shaders()->enabled()) { return; } int screen_index = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *m_renderer.window().m_primlist) { if (PRIMFLAG_GET_SCREENTEX(prim.flags)) { - if (!m_renderer->get_shaders()->get_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) + if (!m_renderer.get_shaders()->get_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) { - if (!m_renderer->get_shaders()->create_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) + if (!m_renderer.get_shaders()->create_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) { - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); break; } } @@ -649,11 +715,11 @@ void d3d_texture_manager::update_textures() } else if (PRIMFLAG_GET_VECTORBUF(prim.flags)) { - if (!m_renderer->get_shaders()->get_vector_target(&prim, screen_index)) + if (!m_renderer.get_shaders()->get_vector_target(&prim, screen_index)) { - if (!m_renderer->get_shaders()->create_vector_target(&prim, screen_index)) + if (!m_renderer.get_shaders()->create_vector_target(&prim, screen_index)) { - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); break; } } @@ -664,13 +730,11 @@ void d3d_texture_manager::update_textures() void renderer_d3d9::begin_frame() { - auto win = assert_window(); - HRESULT result = m_device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0xff,0,0,0), 0, 0); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result); - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // first update any textures m_texture_manager->update_textures(); @@ -681,16 +745,14 @@ void renderer_d3d9::begin_frame() osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result); if (m_shaders->enabled()) - m_shaders->begin_frame(win->m_primlist); + m_shaders->begin_frame(window().m_primlist); } void renderer_d3d9::process_primitives() { - auto win = assert_window(); - // loop over line primitives int vector_count = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { if (prim.type == render_primitive::LINE && PRIMFLAG_GET_VECTOR(prim.flags)) { @@ -699,7 +761,7 @@ void renderer_d3d9::process_primitives() } // Rotating index for vector time offsets - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { switch (prim.type) { @@ -730,9 +792,7 @@ void renderer_d3d9::process_primitives() void renderer_d3d9::end_frame() { - auto win = assert_window(); - - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); // flush any pending polygons primitive_flush_pending(); @@ -753,8 +813,6 @@ void renderer_d3d9::end_frame() void renderer_d3d9::update_presentation_parameters() { - auto win = assert_window(); - memset(&m_presentation, 0, sizeof(m_presentation)); m_presentation.BackBufferWidth = m_width; m_presentation.BackBufferHeight = m_height; @@ -762,14 +820,14 @@ void renderer_d3d9::update_presentation_parameters() m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1; m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE; m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD; - m_presentation.hDeviceWindow = std::static_pointer_cast<win_window_info>(win)->platform_window(); - m_presentation.Windowed = !win->fullscreen(); + m_presentation.hDeviceWindow = dynamic_cast<win_window_info &>(window()).platform_window(); + m_presentation.Windowed = !window().fullscreen(); m_presentation.EnableAutoDepthStencil = FALSE; m_presentation.AutoDepthStencilFormat = D3DFMT_D16; m_presentation.Flags = 0; m_presentation.FullScreen_RefreshRateInHz = m_refresh; m_presentation.PresentationInterval = ( - (video_config.triplebuf && win->fullscreen()) + (video_config.triplebuf && window().fullscreen()) || video_config.waitvsync || video_config.syncrefresh) ? D3DPRESENT_INTERVAL_ONE @@ -784,13 +842,11 @@ void renderer_d3d9::update_gamma_ramp() return; } - auto win = assert_window(); - // set the gamma if we need to - if (win->fullscreen()) + if (window().fullscreen()) { // only set the gamma if it's not 1.0 - auto &options = downcast<windows_options &>(win->machine().options()); + auto &options = downcast<windows_options &>(window().machine().options()); float brightness = options.full_screen_brightness(); float contrast = options.full_screen_contrast(); float gamma = options.full_screen_gamma(); @@ -820,27 +876,23 @@ int renderer_d3d9::device_create(HWND hwnd) HWND device_hwnd = GetAncestor(hwnd, GA_ROOT); // if a device exists, free it - if (m_device != nullptr) - { + if (m_device) device_delete(); - } // verify the caps if (!device_verify_caps()) - { return 1; - } - m_texture_manager = std::make_unique<d3d_texture_manager>(this); + m_texture_manager = std::make_unique<d3d_texture_manager>(*this, m_d3dobj.Get()); // try for XRGB first m_screen_format = D3DFMT_X8R8G8B8; - HRESULT result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); + HRESULT result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); if (FAILED(result)) { // if not, try for ARGB m_screen_format = D3DFMT_A8R8G8B8; - result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); + result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); if (FAILED(result)) { osd_printf_error("Error: unable to configure a screen texture format\n"); @@ -852,8 +904,13 @@ int renderer_d3d9::device_create(HWND hwnd) update_presentation_parameters(); // create the D3D device - result = d3dintf->d3dobj->CreateDevice( - m_adapter, D3DDEVTYPE_HAL, device_hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device); + result = m_d3dobj->CreateDevice( + m_adapter, + D3DDEVTYPE_HAL, + device_hwnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, + &m_presentation, + &m_device); if (FAILED(result)) { // if we got a "DEVICELOST" error, it may be transitory; count it and only fail if @@ -886,16 +943,13 @@ int renderer_d3d9::device_create(HWND hwnd) int renderer_d3d9::device_create_resources() { - auto win = assert_window(); - // create shaders only once - if (m_shaders == nullptr) - { - m_shaders = new shaders; - } + if (!m_shaders) + m_shaders = std::make_unique<shaders>(); - if (m_shaders->init(d3dintf, &win->machine(), this)) + if (m_shaders->init(m_d3dobj.Get(), &window().machine(), this)) { + m_post_fx_available = true; m_shaders->init_slider_list(); m_sliders_dirty = true; } @@ -909,12 +963,12 @@ int renderer_d3d9::device_create_resources() // allocate a vertex buffer to use HRESULT result = m_device->CreateVertexBuffer( - sizeof(vertex) * VERTEX_BUFFER_SIZE, - D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, - VERTEX_BASE_FORMAT | ((m_shaders->enabled()) - ? D3DFVF_XYZW - : D3DFVF_XYZRHW), - D3DPOOL_DEFAULT, &m_vertexbuf, nullptr); + sizeof(vertex) * VERTEX_BUFFER_SIZE, + D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, + VERTEX_BASE_FORMAT | (m_shaders->enabled() ? D3DFVF_XYZW : D3DFVF_XYZRHW), + D3DPOOL_DEFAULT, + &m_vertexbuf, + nullptr); if (FAILED(result)) { osd_printf_error("Error creating vertex buffer (%08X)\n", (uint32_t)result); @@ -923,9 +977,7 @@ int renderer_d3d9::device_create_resources() // set the vertex format result = m_device->SetFVF( - (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled()) - ? D3DFVF_XYZW - : D3DFVF_XYZRHW))); + D3DFORMAT(VERTEX_BASE_FORMAT | (m_shaders->enabled() ? D3DFVF_XYZW : D3DFVF_XYZRHW))); if (FAILED(result)) { osd_printf_error("Error setting vertex format (%08X)\n", (uint32_t)result); @@ -977,24 +1029,6 @@ int renderer_d3d9::device_create_resources() renderer_d3d9::~renderer_d3d9() { device_delete(); - - // todo: throws error when switching from full screen to window mode - //if (m_shaders != nullptr) - //{ - // // delete the HLSL interface - // delete m_shaders; - // m_shaders = nullptr; - //} -} - -void renderer_d3d9::exit() -{ - if (d3dintf != nullptr) - { - d3dintf->d3dobj->Release(); - delete d3dintf; - d3dintf = nullptr; - } } void renderer_d3d9::device_delete() @@ -1007,11 +1041,7 @@ void renderer_d3d9::device_delete() m_texture_manager.reset(); // free the device itself - if (m_device != nullptr) - { - m_device->Release(); - m_device = nullptr; - } + m_device.Reset(); } @@ -1021,22 +1051,14 @@ void renderer_d3d9::device_delete() void renderer_d3d9::device_delete_resources() { - if (m_shaders != nullptr) - { + if (m_shaders) m_shaders->delete_resources(); - } - if (m_texture_manager != nullptr) - { + if (m_texture_manager) m_texture_manager->delete_resources(); - } // free the vertex buffer - if (m_vertexbuf != nullptr) - { - m_vertexbuf->Release(); - m_vertexbuf = nullptr; - } + m_vertexbuf.Reset(); } @@ -1049,7 +1071,7 @@ bool renderer_d3d9::device_verify_caps() bool success = true; D3DCAPS9 caps; - HRESULT result = d3dintf->d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps); + HRESULT result = m_d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps); if (FAILED(result)) { osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result); @@ -1059,7 +1081,7 @@ bool renderer_d3d9::device_verify_caps() if (caps.MaxPixelShader30InstructionSlots < 512) { osd_printf_verbose("Direct3D: Warning - Device does not support Pixel Shader 3.0, falling back to non-PS rendering\n"); - d3dintf->post_fx_available = false; + set_post_fx_unavailable(); } // verify presentation capabilities @@ -1114,7 +1136,7 @@ bool renderer_d3d9::device_verify_caps() } // verify texture formats - result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); + result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); if (FAILED(result)) { osd_printf_error("Direct3D Error: Your graphics card does not support the A8R8G8B8 texture format.\n"); @@ -1190,7 +1212,7 @@ int renderer_d3d9::config_adapter_mode() // get the identifier D3DADAPTER_IDENTIFIER9 id; - HRESULT result = d3dintf->d3dobj->GetAdapterIdentifier(m_adapter, 0, &id); + HRESULT result = m_d3dobj->GetAdapterIdentifier(m_adapter, 0, &id); if (FAILED(result)) { osd_printf_error("Error getting identifier for adapter #%d\n", m_adapter); @@ -1200,22 +1222,20 @@ int renderer_d3d9::config_adapter_mode() osd_printf_verbose("Direct3D: Configuring adapter #%d = %s\n", m_adapter, id.Description); // get the current display mode - result = d3dintf->d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode); + result = m_d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode); if (FAILED(result)) { osd_printf_error("Error getting mode for adapter #%d\n", m_adapter); return 1; } - auto win = assert_window(); - - // choose a resolution: window mode case - if (!win->fullscreen() || !video_config.switchres) + if (!window().fullscreen() || !video_config.switchres) { - RECT client; + // choose a resolution: window mode case // bounds are from the window client rect - GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen()); + RECT client; + GetClientRectExceptMenu(dynamic_cast<win_window_info &>(window()).platform_window(), &client, window().fullscreen()); m_width = client.right - client.left; m_height = client.bottom - client.top; @@ -1226,14 +1246,14 @@ int renderer_d3d9::config_adapter_mode() // make sure it's a pixel format we can get behind if (m_pixformat != D3DFMT_X1R5G5B5 && m_pixformat != D3DFMT_R5G6B5 && m_pixformat != D3DFMT_X8R8G8B8) { - osd_printf_error("Device %s currently in an unsupported mode\n", win->monitor()->devicename()); + osd_printf_error("Device %s currently in an unsupported mode\n", window().monitor()->devicename()); return 1; } } - - // choose a resolution: full screen mode case else { + // choose a resolution: full screen mode case + // default to the current mode exactly m_width = m_origmode.Width; m_height = m_origmode.Height; @@ -1246,10 +1266,10 @@ int renderer_d3d9::config_adapter_mode() } // see if we can handle the device type - result = d3dintf->d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !win->fullscreen()); + result = m_d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !window().fullscreen()); if (FAILED(result)) { - osd_printf_error("Proposed video mode not supported on device %s\n", win->monitor()->devicename()); + osd_printf_error("Proposed video mode not supported on device %s\n", window().monitor()->devicename()); return 1; } @@ -1263,18 +1283,16 @@ int renderer_d3d9::config_adapter_mode() int renderer_d3d9::get_adapter_for_monitor() { - int maxadapter = d3dintf->d3dobj->GetAdapterCount(); - - auto win = assert_window(); + int maxadapter = m_d3dobj->GetAdapterCount(); // iterate over adapters until we error or find a match for (int adapternum = 0; adapternum < maxadapter; adapternum++) { // get the monitor for this adapter - HMONITOR curmonitor = d3dintf->d3dobj->GetAdapterMonitor(adapternum); + HMONITOR curmonitor = m_d3dobj->GetAdapterMonitor(adapternum); // if we match the proposed monitor, this is it - if (curmonitor == reinterpret_cast<HMONITOR>(win->monitor()->oshandle())) + if (curmonitor == reinterpret_cast<HMONITOR>(window().monitor()->oshandle())) { return adapternum; } @@ -1295,10 +1313,8 @@ void renderer_d3d9::pick_best_mode() int32_t minwidth, minheight; float best_score = 0.0f; - auto win = assert_window(); - // determine the refresh rate of the primary screen - const screen_device *primary_screen = screen_device_enumerator(win->machine().root_device()).first(); + const screen_device *primary_screen = screen_device_enumerator(window().machine().root_device()).first(); if (primary_screen != nullptr) { target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); @@ -1308,14 +1324,14 @@ void renderer_d3d9::pick_best_mode() // note: technically we should not be calling this from an alternate window // thread; however, it is only done during init time, and the init code on // the main thread is waiting for us to finish, so it is safe to do so here - win->target()->compute_minimum_size(minwidth, minheight); + window().target()->compute_minimum_size(minwidth, minheight); // use those as the target for now int32_t target_width = minwidth; int32_t target_height = minheight; // determine the maximum number of modes - int maxmodes = d3dintf->d3dobj->GetAdapterModeCount(m_adapter, D3DFMT_X8R8G8B8); + int maxmodes = m_d3dobj->GetAdapterModeCount(m_adapter, D3DFMT_X8R8G8B8); // enumerate all the video modes and find the best match osd_printf_verbose("Direct3D: Selecting video mode...\n"); @@ -1323,7 +1339,7 @@ void renderer_d3d9::pick_best_mode() { // check this mode D3DDISPLAYMODE mode; - HRESULT result = d3dintf->d3dobj->EnumAdapterModes(m_adapter, D3DFMT_X8R8G8B8, modenum, &mode); + HRESULT result = m_d3dobj->EnumAdapterModes(m_adapter, D3DFMT_X8R8G8B8, modenum, &mode); if (FAILED(result)) break; @@ -1343,7 +1359,7 @@ void renderer_d3d9::pick_best_mode() size_score *= 0.1f; // if we're looking for a particular mode, that's a winner - if (mode.Width == win->m_win_config.width && mode.Height == win->m_win_config.height) + if (mode.Width == window().m_win_config.width && mode.Height == window().m_win_config.height) size_score = 2.0f; // compute refresh score @@ -1354,7 +1370,7 @@ void renderer_d3d9::pick_best_mode() refresh_score *= 0.1f; // if we're looking for a particular refresh, make sure it matches - if (mode.RefreshRate == win->m_win_config.refresh) + if (mode.RefreshRate == window().m_win_config.refresh) refresh_score = 2.0f; // weight size and refresh equally @@ -1381,33 +1397,31 @@ void renderer_d3d9::pick_best_mode() bool renderer_d3d9::update_window_size() { - auto win = assert_window(); - // get the current window bounds RECT client; - GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen()); + GetClientRectExceptMenu(dynamic_cast<win_window_info &>(window()).platform_window(), &client, window().fullscreen()); // if we have a device and matching width/height, nothing to do - if (m_device != nullptr && rect_width(&client) == m_width && rect_height(&client) == m_height) + if (m_device && rect_width(&client) == m_width && rect_height(&client) == m_height) { // clear out any pending resizing if the area didn't change - if (win->m_resize_state == RESIZE_STATE_PENDING) - win->m_resize_state = RESIZE_STATE_NORMAL; + if (window().m_resize_state == RESIZE_STATE_PENDING) + window().m_resize_state = RESIZE_STATE_NORMAL; return false; } // if we're in the middle of resizing, leave it alone as well - if (win->m_resize_state == RESIZE_STATE_RESIZING) + if (window().m_resize_state == RESIZE_STATE_RESIZING) return false; // set the new bounds and create the device again m_width = rect_width(&client); m_height = rect_height(&client); - if (device_create(std::static_pointer_cast<win_window_info>(win->main_window())->platform_window())) + if (device_create(dynamic_cast<win_window_info &>(window()).main_window()->platform_window())) return false; // reset the resize state to normal, and indicate we made a change - win->m_resize_state = RESIZE_STATE_NORMAL; + window().m_resize_state = RESIZE_STATE_NORMAL; return true; } @@ -1418,8 +1432,6 @@ bool renderer_d3d9::update_window_size() void renderer_d3d9::batch_vectors(int vector_count) { - auto win = assert_window(); - float quad_width = 0.0f; float quad_height = 0.0f; float target_width = 0.0f; @@ -1432,7 +1444,7 @@ void renderer_d3d9::batch_vectors(int vector_count) uint32_t tint = 0xffffffff; uint32_t cached_flags = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { switch (prim.type) { @@ -1476,15 +1488,15 @@ void renderer_d3d9::batch_vectors(int vector_count) if (m_shaders->enabled()) { bool orientation_swap_xy = - (win->machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; + (window().machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; bool rotation_swap_xy = - (win->target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; + (window().target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; bool swap_xy = orientation_swap_xy ^ rotation_swap_xy; - bool rotation_0 = win->target()->orientation() == ROT0; - bool rotation_90 = win->target()->orientation() == ROT90; - bool rotation_180 = win->target()->orientation() == ROT180; - bool rotation_270 = win->target()->orientation() == ROT270; + bool rotation_0 = window().target()->orientation() == ROT0; + bool rotation_90 = window().target()->orientation() == ROT90; + bool rotation_180 = window().target()->orientation() == ROT180; + bool rotation_270 = window().target()->orientation() == ROT270; bool flip_x = ((rotation_0 || rotation_270) && orientation_swap_xy) || ((rotation_180 || rotation_270) && !orientation_swap_xy); @@ -1828,7 +1840,7 @@ void renderer_d3d9::primitive_flush_pending() m_lockedbuf = nullptr; // set the stream - result = m_device->SetStreamSource(0, m_vertexbuf, 0, sizeof(vertex)); + result = m_device->SetStreamSource(0, m_vertexbuf.Get(), 0, sizeof(vertex)); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result); @@ -1931,19 +1943,6 @@ void renderer_d3d9::set_sliders_dirty() texture_info::~texture_info() { - if (m_d3dfinaltex != nullptr) - { - if (m_d3dtex == m_d3dfinaltex) - m_d3dtex = nullptr; - - m_d3dfinaltex->Release(); - } - - if (m_d3dtex != nullptr) - m_d3dtex->Release(); - - if (m_d3dsurface != nullptr) - m_d3dsurface->Release(); } @@ -1951,74 +1950,53 @@ texture_info::~texture_info() // texture_info constructor //============================================================ -texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* texsource, int prescale, uint32_t flags) +texture_info::texture_info(d3d_texture_manager &manager, const render_texinfo* texsource, int prescale, uint32_t flags) + : m_texture_manager(manager) + , m_renderer(manager.get_d3d()) + , m_hash(manager.texture_compute_hash(texsource, flags)) + , m_flags(flags) + , m_texinfo(*texsource) + , m_type(!PRIMFLAG_GET_SCREENTEX(flags) ? TEXTURE_TYPE_PLAIN : TEXTURE_TYPE_DYNAMIC) // required to compute texture size + , m_xprescale(prescale) + , m_yprescale(prescale) { HRESULT result; - // fill in the core data - m_texture_manager = manager; - m_renderer = m_texture_manager->get_d3d(); - m_hash = m_texture_manager->texture_compute_hash(texsource, flags); - m_flags = flags; - m_texinfo = *texsource; - m_xprescale = prescale; - m_yprescale = prescale; - - m_d3dtex = nullptr; - m_d3dsurface = nullptr; - m_d3dfinaltex = nullptr; - - // determine texture type, required to compute texture size - if (!PRIMFLAG_GET_SCREENTEX(flags)) - { - m_type = TEXTURE_TYPE_PLAIN; - } - else - { - m_type = TEXTURE_TYPE_DYNAMIC; - } - // compute the size compute_size(texsource->width, texsource->height); - // non-screen textures are easy if (!PRIMFLAG_GET_SCREENTEX(flags)) { + // non-screen textures are easy assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16); - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex, nullptr); + result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex, nullptr); if (FAILED(result)) goto error; + m_d3dfinaltex = m_d3dtex; } - - // screen textures are allocated differently else { + // screen textures are allocated differently D3DFORMAT format; DWORD usage = D3DUSAGE_DYNAMIC; D3DPOOL pool = D3DPOOL_DEFAULT; - int maxdim = std::max(m_renderer->get_presentation()->BackBufferWidth, m_renderer->get_presentation()->BackBufferHeight); + int maxdim = std::max(m_renderer.get_presentation()->BackBufferWidth, m_renderer.get_presentation()->BackBufferHeight); // pick the format if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_YUY16) - { - format = m_texture_manager->get_yuv_format(); - } + format = m_texture_manager.get_yuv_format(); else if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_ARGB32) - { format = D3DFMT_A8R8G8B8; - } else - { - format = m_renderer->get_screen_format(); - } + format = m_renderer.get_screen_format(); // don't prescale above screen size while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale >= 2 * maxdim) { m_xprescale--; } - while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale > manager->get_max_texture_width()) + while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale > manager.get_max_texture_width()) { m_xprescale--; } @@ -2026,62 +2004,51 @@ texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* t { m_yprescale--; } - while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale > manager->get_max_texture_height()) + while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale > manager.get_max_texture_height()) { m_yprescale--; } - auto win = m_renderer->assert_window(); - - int prescale = win->prescale(); + const int prescale = m_renderer.window().prescale(); if (m_xprescale != prescale || m_yprescale != prescale) - { osd_printf_verbose("Direct3D: adjusting prescale from %dx%d to %dx%d\n", prescale, prescale, m_xprescale, m_yprescale); - } // loop until we allocate something or error for (int attempt = 0; attempt < 2; attempt++) { // second attempt is always 1:1 if (attempt == 1) - { m_xprescale = m_yprescale = 1; - } - // screen textures with no prescaling are pretty easy if (m_xprescale == 1 && m_yprescale == 1) { - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); + // screen textures with no prescaling are pretty easy + result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); if (result == D3D_OK) { m_d3dfinaltex = m_d3dtex; break; } } - // screen textures with prescaling require two allocations else { - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); + // screen textures with prescaling require two allocations + result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); if (FAILED(result)) - { continue; - } // for the target surface, we allocate a render target texture - int scwidth = m_rawdims.c.x * m_xprescale; - int scheight = m_rawdims.c.y * m_yprescale; + const int scwidth = m_rawdims.c.x * m_xprescale; + const int scheight = m_rawdims.c.y * m_yprescale; // target surfaces typically cannot be YCbCr, so we always pick RGB in that case - D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8; + const D3DFORMAT finalfmt = (format != m_texture_manager.get_yuv_format()) ? format : D3DFMT_A8R8G8B8; - result = m_renderer->get_device()->CreateTexture(scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex, nullptr); + result = m_renderer.get_device()->CreateTexture(scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex, nullptr); if (result == D3D_OK) - { break; - } - m_d3dtex->Release(); - m_d3dtex = nullptr; + m_d3dtex.Reset(); } } } @@ -2092,12 +2059,10 @@ texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* t return; error: - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); osd_printf_error("Direct3D: Critical warning: A texture failed to allocate. Expect things to get bad quickly.\n"); - if (m_d3dsurface != nullptr) - m_d3dsurface->Release(); - if (m_d3dtex != nullptr) - m_d3dtex->Release(); + m_d3dsurface.Reset(); + m_d3dtex.Reset(); } @@ -2111,11 +2076,11 @@ void texture_info::compute_size_subroutine(int texwidth, int texheight, int* p_w int finalwidth = texwidth; // adjust the aspect ratio if we need to - while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect()) + while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager.get_max_texture_aspect()) { finalwidth *= 2; } - while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect()) + while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager.get_max_texture_aspect()) { finalheight *= 2; } @@ -2137,7 +2102,7 @@ void texture_info::compute_size(int texwidth, int texheight) m_xborderpix = 0; m_yborderpix = 0; - bool shaders_enabled = m_renderer->get_shaders()->enabled(); + bool shaders_enabled = m_renderer.get_shaders()->enabled(); bool wrap_texture = (m_flags & PRIMFLAG_TEXWRAP_MASK) == PRIMFLAG_TEXWRAP_MASK; // skip border when shaders are enabled @@ -2161,7 +2126,7 @@ void texture_info::compute_size(int texwidth, int texheight) compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight); // if we added pixels for the border, and that just barely pushed us over, take it back - if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) + if (finalwidth > m_texture_manager.get_max_texture_width() || finalheight > m_texture_manager.get_max_texture_height()) { finalheight = texheight; finalwidth = texwidth; @@ -2174,10 +2139,18 @@ void texture_info::compute_size(int texwidth, int texheight) } // if we're above the max width/height, do what? - if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) + if (finalwidth > m_texture_manager.get_max_texture_width() || finalheight > m_texture_manager.get_max_texture_height()) { static bool printed = false; - if (!printed) osd_printf_warning("Texture too big! (wanted: %dx%d, max is %dx%d)\n", finalwidth, finalheight, (int)m_texture_manager->get_max_texture_width(), (int)m_texture_manager->get_max_texture_height()); + if (!printed) + { + osd_printf_warning( + "Texture too big! (wanted: %dx%d, max is %dx%d)\n", + finalwidth, + finalheight, + m_texture_manager.get_max_texture_width(), + m_texture_manager.get_max_texture_height()); + } printed = true; } @@ -2430,9 +2403,9 @@ void texture_info::set_data(const render_texinfo *texsource, uint32_t flags) break; case TEXFORMAT_YUY16: - if (m_texture_manager->get_yuv_format() == D3DFMT_YUY2) + if (m_texture_manager.get_yuv_format() == D3DFMT_YUY2) copyline_yuy16_to_yuy2((uint16_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); - else if (m_texture_manager->get_yuv_format() == D3DFMT_UYVY) + else if (m_texture_manager.get_yuv_format() == D3DFMT_UYVY) copyline_yuy16_to_uyvy((uint16_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); else copyline_yuy16_to_argb((uint32_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); @@ -2467,7 +2440,6 @@ void texture_info::set_data(const render_texinfo *texsource, uint32_t flags) void texture_info::prescale() { - IDirect3DSurface9 *scale_surface; HRESULT result; int i; @@ -2476,39 +2448,39 @@ void texture_info::prescale() return; // for all cases, we need to get the surface of the render target + Microsoft::WRL::ComPtr<IDirect3DSurface9> scale_surface; result = m_d3dfinaltex->GetSurfaceLevel(0, &scale_surface); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during texture GetSurfaceLevel call\n", result); // if we have an offscreen plain surface, we can just StretchRect to it - IDirect3DSurface9 *backbuffer; - - assert(m_d3dtex != nullptr); + assert(m_d3dtex); // first remember the original render target and set the new one - result = m_renderer->get_device()->GetRenderTarget(0, &backbuffer); + Microsoft::WRL::ComPtr<IDirect3DSurface9> backbuffer; + result = m_renderer.get_device()->GetRenderTarget(0, &backbuffer); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device GetRenderTarget call\n", result); - result = m_renderer->get_device()->SetRenderTarget(0, scale_surface); + result = m_renderer.get_device()->SetRenderTarget(0, scale_surface.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 1\n", result); - m_renderer->reset_render_states(); + m_renderer.reset_render_states(); // start the scene - result = m_renderer->get_device()->BeginScene(); + result = m_renderer.get_device()->BeginScene(); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result); // configure the rendering pipeline - m_renderer->set_filter(FALSE); - m_renderer->set_blendmode(BLENDMODE_NONE); - result = m_renderer->get_device()->SetTexture(0, m_d3dtex); + m_renderer.set_filter(FALSE); + m_renderer.set_blendmode(BLENDMODE_NONE); + result = m_renderer.get_device()->SetTexture(0, m_d3dtex.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetTexture call\n", result); // lock the vertex buffer vertex *lockedbuf; - result = m_renderer->get_vertex_buffer()->Lock(0, 0, (VOID **)&lockedbuf, D3DLOCK_DISCARD); + result = m_renderer.get_vertex_buffer()->Lock(0, 0, (VOID **)&lockedbuf, D3DLOCK_DISCARD); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during vertex buffer lock call\n", result); @@ -2541,32 +2513,32 @@ void texture_info::prescale() } // unlock the vertex buffer - result = m_renderer->get_vertex_buffer()->Unlock(); + result = m_renderer.get_vertex_buffer()->Unlock(); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during vertex buffer unlock call\n", result); // set the stream and draw the triangle strip - result = m_renderer->get_device()->SetStreamSource(0, m_renderer->get_vertex_buffer(), 0, sizeof(vertex)); + result = m_renderer.get_device()->SetStreamSource(0, m_renderer.get_vertex_buffer(), 0, sizeof(vertex)); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result); - result = m_renderer->get_device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + result = m_renderer.get_device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result); // end the scene - result = m_renderer->get_device()->EndScene(); + result = m_renderer.get_device()->EndScene(); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device end_scene call\n", result); // reset the render target and release our reference to the backbuffer - result = m_renderer->get_device()->SetRenderTarget(0, backbuffer); + result = m_renderer.get_device()->SetRenderTarget(0, backbuffer.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 2\n", result); - backbuffer->Release(); - m_renderer->reset_render_states(); + backbuffer.Reset(); + m_renderer.reset_render_states(); // release our reference to the target surface - scale_surface->Release(); + scale_surface.Reset(); } @@ -2576,35 +2548,6 @@ void texture_info::prescale() d3d_render_target::~d3d_render_target() { - for (int index = 0; index < MAX_BLOOM_COUNT; index++) - { - if (bloom_texture[index] != nullptr) - bloom_texture[index]->Release(); - - if (bloom_surface[index] != nullptr) - bloom_surface[index]->Release(); - } - - for (int index = 0; index < 2; index++) - { - if (source_texture[index] != nullptr) - source_texture[index]->Release(); - - if (source_surface[index] != nullptr) - source_surface[index]->Release(); - - if (target_texture[index] != nullptr) - target_texture[index]->Release(); - - if (target_surface[index] != nullptr) - target_surface[index]->Release(); - } - - if (cache_texture != nullptr) - cache_texture->Release(); - - if (cache_surface != nullptr) - cache_surface->Release(); } @@ -2645,9 +2588,7 @@ bool d3d_render_target::init(renderer_d3d9 *d3d, int source_width, int source_he cache_texture->GetSurfaceLevel(0, &cache_surface); - auto win = d3d->assert_window(); - - const screen_device *first_screen = screen_device_enumerator(win->machine().root_device()).first(); + const screen_device *first_screen = screen_device_enumerator(d3d->window().machine().root_device()).first(); bool vector_screen = first_screen != nullptr && first_screen->screen_type() == SCREEN_TYPE_VECTOR; diff --git a/src/osd/modules/render/drawd3d.h b/src/osd/modules/render/drawd3d.h index 2fa4a30873c..3ab7651d87c 100644 --- a/src/osd/modules/render/drawd3d.h +++ b/src/osd/modules/render/drawd3d.h @@ -10,20 +10,24 @@ #pragma once +#include "d3d/d3dcomm.h" -#ifdef OSD_WINDOWS +#include "modules/lib/osdlib.h" +#include "modules/osdwindow.h" + +#include "sliderdirtynotifier.h" #include <windows.h> #include <tchar.h> #include <mmsystem.h> #include <d3d9.h> #include <d3dx9.h> -#include <cmath> #undef interface -#include "d3d/d3dcomm.h" -#include "sliderdirtynotifier.h" -#include "modules/lib/osdlib.h" +#include <memory> +#include <vector> +#include <cmath> + //============================================================ // CONSTANTS @@ -36,15 +40,6 @@ // TYPE DEFINITIONS //============================================================ -struct d3d_base -{ - // internal objects - IDirect3D9 *d3dobj; - bool post_fx_available; - - osd::dynamic_module::ptr d3d9_dll; -}; - class shaders; struct hlsl_options; @@ -52,11 +47,10 @@ struct hlsl_options; class renderer_d3d9 : public osd_renderer, public slider_dirty_notifier { public: - renderer_d3d9(std::shared_ptr<osd_window> window); - virtual ~renderer_d3d9(); + using IDirect3D9Ptr = Microsoft::WRL::ComPtr<IDirect3D9>; - static bool init(running_machine &machine); - static void exit(); + renderer_d3d9(osd_window &window, const IDirect3D9Ptr &d3dobj); + virtual ~renderer_d3d9(); virtual int create() override; virtual render_primitive_list *get_primitives() override; @@ -113,11 +107,13 @@ public: vec2f get_dims() const { return vec2f(m_width, m_height); } int get_height() const { return m_height; } int get_refresh() const { return m_refresh; } + bool post_fx_available() const { return m_post_fx_available; } + void set_post_fx_unavailable() { m_post_fx_available = false; } - IDirect3DDevice9 * get_device() const { return m_device; } + IDirect3DDevice9 * get_device() const { return m_device.Get(); } D3DPRESENT_PARAMETERS * get_presentation() { return &m_presentation; } - IDirect3DVertexBuffer9 *get_vertex_buffer() const { return m_vertexbuf; } + IDirect3DVertexBuffer9 *get_vertex_buffer() const { return m_vertexbuf.Get(); } void set_toggle(bool toggle) { m_toggle = toggle; } @@ -125,27 +121,32 @@ public: D3DFORMAT get_pixel_format() const { return m_pixformat; } D3DDISPLAYMODE get_origmode() const { return m_origmode; } - uint32_t get_last_texture_flags() const { return m_last_texture_flags; } + uint32_t get_last_texture_flags() const { return m_last_texture_flags; } d3d_texture_manager * get_texture_manager() const { return m_texture_manager.get(); } texture_info * get_default_texture(); - shaders * get_shaders() const { return m_shaders; } + shaders * get_shaders() const { return m_shaders.get(); } private: + using IDirect3DDevice9Ptr = Microsoft::WRL::ComPtr<IDirect3DDevice9>; + using IDirect3DVertexBuffer9Ptr = Microsoft::WRL::ComPtr<IDirect3DVertexBuffer9>; + + const IDirect3D9Ptr m_d3dobj; // Direct3D 9 API object int m_adapter; // ordinal adapter number int m_width; // current width int m_height; // current height int m_refresh; // current refresh rate int m_create_error_count; // number of consecutive create errors + bool m_post_fx_available; - IDirect3DDevice9 * m_device; // pointer to the Direct3DDevice object + IDirect3DDevice9Ptr m_device; // pointer to the Direct3DDevice object int m_gamma_supported; // is full screen gamma supported? D3DPRESENT_PARAMETERS m_presentation; // set of presentation parameters D3DDISPLAYMODE m_origmode; // original display mode for the adapter D3DFORMAT m_pixformat; // pixel format we are using - IDirect3DVertexBuffer9 *m_vertexbuf; // pointer to the vertex buffer object + IDirect3DVertexBuffer9Ptr m_vertexbuf; // pointer to the vertex buffer object vertex * m_lockedbuf; // pointer to the locked vertex buffer int m_numverts; // number of accumulated vertices @@ -160,20 +161,18 @@ private: D3DFORMAT m_screen_format; // format to use for screen textures texture_info * m_last_texture; // previous texture - uint32_t m_last_texture_flags; // previous texture flags + uint32_t m_last_texture_flags; // previous texture flags int m_last_blendenable; // previous blendmode int m_last_blendop; // previous blendmode int m_last_blendsrc; // previous blendmode int m_last_blenddst; // previous blendmode int m_last_filter; // previous texture filter - uint32_t m_last_wrap; // previous wrap state + uint32_t m_last_wrap; // previous wrap state int m_last_modmode; // previous texture modulation - shaders * m_shaders; // HLSL interface + std::unique_ptr<shaders> m_shaders; // HLSL interface std::unique_ptr<d3d_texture_manager> m_texture_manager; // texture manager }; -#endif // OSD_WINDOWS - #endif // MAME_OSD_MODULES_RENDER_DRAWD3D_H diff --git a/src/osd/modules/render/drawgdi.cpp b/src/osd/modules/render/drawgdi.cpp index 32dac94c24a..69ac20434b3 100644 --- a/src/osd/modules/render/drawgdi.cpp +++ b/src/osd/modules/render/drawgdi.cpp @@ -2,21 +2,53 @@ // copyright-holders:Aaron Giles //============================================================ // -// drawgdi.c - Win32 GDI drawing +// drawgdi.cpp - Win32 GDI drawing // //============================================================ +#include "render_module.h" + +#include "modules/osdmodule.h" + +#if defined(OSD_WINDOWS) + +#include "window.h" + +// emu #include "emu.h" -#include "drawgdi.h" #include "rendersw.hxx" -//============================================================ -// destructor -//============================================================ +// standard windows headers +#include <windows.h> + + +namespace osd { + +namespace { -renderer_gdi::~renderer_gdi() +// renderer_gdi is the information for the current screen +class renderer_gdi : public osd_renderer { -} +public: + renderer_gdi(osd_window &window) + : osd_renderer(window) + , m_bmdata(nullptr) + , m_bmsize(0) + { + } + + 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 {} + +private: + BITMAPINFO m_bminfo; + std::unique_ptr<uint8_t []> m_bmdata; + size_t m_bmsize; +}; //============================================================ // renderer_gdi::create @@ -34,6 +66,7 @@ int renderer_gdi::create() m_bminfo.bmiHeader.biYPelsPerMeter = 0; m_bminfo.bmiHeader.biClrUsed = 0; m_bminfo.bmiHeader.biClrImportant = 0; + return 0; } @@ -43,16 +76,12 @@ int renderer_gdi::create() render_primitive_list *renderer_gdi::get_primitives() { - auto win = try_getwindow(); - if (win == nullptr) + osd_dim const dimensions = window().get_size(); + if ((dimensions.width() <= 0) || (dimensions.height() <= 0)) return nullptr; - RECT client; - GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client); - if ((rect_width(&client) == 0) || (rect_height(&client) == 0)) - return nullptr; - win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(dimensions.width(), dimensions.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); } //============================================================ @@ -61,23 +90,22 @@ render_primitive_list *renderer_gdi::get_primitives() int renderer_gdi::draw(const int update) { - auto win = assert_window(); - // we don't have any special resize behaviors - if (win->m_resize_state == RESIZE_STATE_PENDING) - win->m_resize_state = RESIZE_STATE_NORMAL; + if (window().m_resize_state == RESIZE_STATE_PENDING) + window().m_resize_state = RESIZE_STATE_NORMAL; // get the target bounds RECT bounds; - GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &bounds); + GetClientRect(dynamic_cast<win_window_info &>(window()).platform_window(), &bounds); // compute width/height/pitch of target - int width = rect_width(&bounds); - int height = rect_height(&bounds); - int pitch = (width + 3) & ~3; + osd_dim const dimensions = window().get_size(); + int const width = dimensions.width(); + int const height = dimensions.height(); + int const pitch = (width + 3) & ~3; // make sure our temporary bitmap is big enough - if (pitch * height * 4 > m_bmsize) + if ((pitch * height * 4) > m_bmsize) { m_bmsize = pitch * height * 4 * 2; m_bmdata.reset(); @@ -85,9 +113,9 @@ int renderer_gdi::draw(const int update) } // draw the primitives to the bitmap - win->m_primlist->acquire_lock(); - software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*win->m_primlist, m_bmdata.get(), width, height, pitch); - win->m_primlist->release_lock(); + window().m_primlist->acquire_lock(); + software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, m_bmdata.get(), width, height, pitch); + window().m_primlist->release_lock(); // fill in bitmap-specific info m_bminfo.bmiHeader.biWidth = pitch; @@ -95,8 +123,43 @@ int renderer_gdi::draw(const int update) // blit to the screen StretchDIBits( - win->m_dc, 0, 0, width, height, + window().m_dc, 0, 0, width, height, 0, 0, width, height, m_bmdata.get(), &m_bminfo, DIB_RGB_COLORS, SRCCOPY); + return 0; } + + +class video_gdi : public osd_module, public render_module +{ +public: + video_gdi() : osd_module(OSD_RENDERER_PROVIDER, "gdi") { } + + virtual int init(osd_interface &osd, osd_options const &options) override { return 0; } + virtual void exit() override { } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE; } +}; + +std::unique_ptr<osd_renderer> video_gdi::create(osd_window &window) +{ + return std::make_unique<renderer_gdi>(window); +} + +} // anonymous namespace + +} // namespace osd + + +#else // defined(OSD_WINDOWS) + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_gdi, OSD_RENDERER_PROVIDER, "gdi") } } + +#endif // defined(OSD_WINDOWS) + + +MODULE_DEFINITION(RENDERER_GDI, osd::video_gdi) diff --git a/src/osd/modules/render/drawgdi.h b/src/osd/modules/render/drawgdi.h deleted file mode 100644 index 0dfc4bf2641..00000000000 --- a/src/osd/modules/render/drawgdi.h +++ /dev/null @@ -1,55 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -//============================================================ -// -// drawgdi.h - Win32 GDI drawing -// -//============================================================ -#ifndef MAME_OSD_MODULES_RENDER_DRAWGDI_H -#define MAME_OSD_MODULES_RENDER_DRAWGDI_H - -#pragma once - - -// standard windows headers -#include <windows.h> - -// MAME headers - -// MAMEOS headers -#include "window.h" - - -//============================================================ -// TYPE DEFINITIONS -//============================================================ - -/* renderer_gdi is the information for the current screen */ -class renderer_gdi : public osd_renderer -{ -public: - renderer_gdi(std::shared_ptr<osd_window> window) - : osd_renderer(window, FLAG_NONE) - , m_bmdata(nullptr) - , m_bmsize(0) - { - } - virtual ~renderer_gdi(); - - static bool init(running_machine &machine) { return false; } - static void exit() { } - - 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 {} - -private: - BITMAPINFO m_bminfo; - std::unique_ptr<uint8_t []> m_bmdata; - size_t m_bmsize; -}; - -#endif // MAME_OSD_MODULES_RENDER_DRAWGDI_H diff --git a/src/osd/modules/render/drawnone.cpp b/src/osd/modules/render/drawnone.cpp index 6f591879038..0f9fa36bd7a 100644 --- a/src/osd/modules/render/drawnone.cpp +++ b/src/osd/modules/render/drawnone.cpp @@ -6,25 +6,77 @@ // //============================================================ -// standard windows headers -#include <windows.h> +#include "render_module.h" -#include "drawnone.h" +#include "modules/lib/osdobj_common.h" +#include "modules/osdmodule.h" +#include "modules/osdwindow.h" -//============================================================ -// drawnone_window_get_primitives -//============================================================ +#include "emu.h" // FIXME: only here for main.h, won't be necessary soon +#include "main.h" +#include "render.h" + +#include <memory> + + +namespace osd { + +namespace { + +class renderer_none : public osd_renderer +{ +public: + renderer_none(osd_window &window) : osd_renderer(window) { } + + virtual int create() override { return 0; } + virtual render_primitive_list *get_primitives() override; + virtual int draw(const int update) override { return 0; } + virtual void save() override { } + virtual void record() override { } + virtual void toggle_fsfx() override { } +}; render_primitive_list *renderer_none::get_primitives() { - auto win = try_getwindow(); - if (win == nullptr) + osd_dim const dimensions = window().get_size(); + if ((dimensions.width() <= 0) || (dimensions.height() <= 0)) return nullptr; - RECT client; - GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client); - if ((rect_width(&client) == 0) || (rect_height(&client) == 0)) - return nullptr; - win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(dimensions.width(), dimensions.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); } + + +class video_none : public osd_module, public render_module +{ +public: + video_none() : osd_module(OSD_RENDERER_PROVIDER, "none") { } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override { } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return 0; } +}; + +int video_none::init(osd_interface &osd, osd_options const &options) +{ + if (!emulator_info::standalone() && (options.seconds_to_run() == 0)) + osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n"); + + return 0; +} + +std::unique_ptr<osd_renderer> video_none::create(osd_window &window) +{ + return std::make_unique<renderer_none>(window); +} + +} // anonymous namespace + +} // namespace osd + + +MODULE_DEFINITION(RENDERER_NONE, osd::video_none) diff --git a/src/osd/modules/render/drawnone.h b/src/osd/modules/render/drawnone.h deleted file mode 100644 index c884f969204..00000000000 --- a/src/osd/modules/render/drawnone.h +++ /dev/null @@ -1,33 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -//============================================================ -// -// drawnone.h - stub "nothing" drawer -// -//============================================================ - -#ifndef __DRAWNONE__ -#define __DRAWNONE__ - -#include "window.h" - -class renderer_none : public osd_renderer -{ -public: - renderer_none(std::shared_ptr<osd_window> window) - : osd_renderer(window, FLAG_NONE) { } - - virtual ~renderer_none() { } - - static bool init(running_machine &machine) { return false; } - static void exit() { } - - virtual int create() override { return 0; } - virtual render_primitive_list *get_primitives() override; - virtual int draw(const int update) override { return 0; } - virtual void save() override { } - virtual void record() override { } - virtual void toggle_fsfx() override { } -}; - -#endif // __DRAWNONE__ diff --git a/src/osd/modules/render/drawogl.cpp b/src/osd/modules/render/drawogl.cpp index 9e200f3817c..7489af2f612 100644 --- a/src/osd/modules/render/drawogl.cpp +++ b/src/osd/modules/render/drawogl.cpp @@ -12,37 +12,61 @@ // //============================================================ -// standard C headers -#include <cmath> -#include <cstdio> +#include "render_module.h" + +#include "modules/osdmodule.h" -// MAME headers +#if USE_OPENGL + +// will be picked up from specific OSD implementation +#include "window.h" + +// OSD common headers +#include "modules/lib/osdlib.h" +#include "modules/lib/osdobj_common.h" +#include "modules/opengl/gl_shader_mgr.h" +#include "modules/opengl/gl_shader_tool.h" #include "osdcomm.h" -#include "emu.h" -#include "emuopts.h" -#ifdef OSD_MAC +// OSD headers +#if defined(OSD_WINDOWS) +typedef uint64_t HashT; +#include "winglcontext.h" +#elif defined(OSD_MAC) #define GL_SILENCE_DEPRECATION (1) +#include "osdmac.h" +#else +#include "osdsdl.h" +#include "sdlglcontext.h" #endif +// emu +#include "emucore.h" +#include "emuopts.h" +#include "render.h" + + #if !defined(OSD_WINDOWS) && !defined(OSD_MAC) + // standard SDL headers #define TOBEMIGRATED 1 #include <SDL2/SDL.h> -#endif -#include "modules/lib/osdlib.h" -#include "modules/lib/osdobj_common.h" +#endif // !defined(OSD_WINDOWS && !defined(OSD_MAC) -// OpenGL headers -#include "modules/opengl/osd_opengl.h" -#include "modules/opengl/gl_shader_tool.h" -#include "modules/opengl/gl_shader_mgr.h" +// standard C headers +#include <cmath> +#include <cstdio> +#include <memory> +#include <utility> + #if defined(SDLMAME_MACOSX) || defined(OSD_MAC) + #include <cstring> #include <cstdio> + #include <sys/types.h> #include <sys/sysctl.h> @@ -72,7 +96,13 @@ typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum m_target, GLuint r typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum m_target, GLenum internalformat, GLsizei width, GLsizei height); typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum m_target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); -#endif + +#endif // defined(SDLMAME_MACOSX) || defined(OSD_MAC) + + +namespace osd { + +namespace { // make sure the extensions compile OK everywhere #ifndef GL_TEXTURE_STORAGE_HINT_APPLE @@ -128,7 +158,261 @@ typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuin #define GL_DEPTH_COMPONENT32 0x81A7 #endif -#include "drawogl.h" + +//============================================================ +// Configuration +//============================================================ + +#define GLSL_SHADER_MAX 10 + +struct ogl_video_config +{ + ogl_video_config() = default; + + bool vbo = false; + bool pbo = false; + bool allowtexturerect = false; // allow GL_ARB_texture_rectangle, default: no + bool forcepow2texture = false; // force power of two textures, default: no + bool glsl = false; + int glsl_filter = 0; // glsl filtering, >0 disables filter + std::string glsl_shader_mamebm[GLSL_SHADER_MAX]; // custom glsl shader set, mame bitmap + int glsl_shader_mamebm_num = 0; // custom glsl shader set number, mame bitmap + std::string glsl_shader_scrn[GLSL_SHADER_MAX]; // custom glsl shader set, screen bitmap + int glsl_shader_scrn_num = 0; // custom glsl shader number, screen bitmap +}; + + +//============================================================ +// Textures +//============================================================ + +/* ogl_texture_info holds information about a texture */ +class ogl_texture_info +{ +public: + ogl_texture_info() + : hash(0), flags(0), rawwidth(0), rawheight(0), + rawwidth_create(0), rawheight_create(0), + type(0), format(0), borderpix(0), xprescale(0), yprescale(0), nocopy(0), + texture(0), texTarget(0), texpow2(0), mpass_dest_idx(0), pbo(0), data(nullptr), + data_own(0), texCoordBufferName(0) + { + for (int i=0; i<2; i++) + { + mpass_textureunit[i] = 0; + mpass_texture_mamebm[i] = 0; + mpass_fbo_mamebm[i] = 0; + mpass_texture_scrn[i] = 0; + mpass_fbo_scrn[i] = 0; + } + for (int i=0; i<8; i++) + texCoord[i] = 0.0f; + } + + HashT hash; // hash value for the texture (must be >= pointer size) + uint32_t flags; // rendering flags + render_texinfo texinfo; // copy of the texture info + int rawwidth, rawheight; // raw width/height of the texture + int rawwidth_create; // raw width/height, pow2 compatible, if needed + int rawheight_create; // (create and initial set the texture, not for copy!) + int type; // what type of texture are we? + int format; // texture format + int borderpix; // do we have a 1 pixel border? + int xprescale; // what is our X prescale factor? + int yprescale; // what is our Y prescale factor? + int nocopy; // must the texture date be copied? + + uint32_t texture; // OpenGL texture "name"/ID + + GLenum texTarget; // OpenGL texture target + int texpow2; // Is this texture pow2 + + uint32_t mpass_dest_idx; // Multipass dest idx [0..1] + uint32_t mpass_textureunit[2]; // texture unit names for GLSL + + uint32_t mpass_texture_mamebm[2];// Multipass OpenGL texture "name"/ID for the shader + uint32_t mpass_fbo_mamebm[2]; // framebuffer object for this texture, multipass + uint32_t mpass_texture_scrn[2]; // Multipass OpenGL texture "name"/ID for the shader + uint32_t mpass_fbo_scrn[2]; // framebuffer object for this texture, multipass + + uint32_t pbo; // pixel buffer object for this texture (DYNAMIC only!) + uint32_t *data; // pixels for the texture + int data_own; // do we own / allocated it ? + GLfloat texCoord[8]; + GLuint texCoordBufferName; + +}; + +// renderer_ogl is the information about OpenGL for the current screen +class renderer_ogl : public osd_renderer +{ +public: + renderer_ogl(osd_window &window, ogl_video_config const &ogl_config) + : osd_renderer(window) + , m_ogl_config(ogl_config) + , m_blittimer(0) + , m_width(0) + , m_height(0) + , m_blit_dim(0, 0) + , m_initialized(0) + , m_last_blendmode(0) + , m_texture_max_width(0) + , m_texture_max_height(0) + , m_texpoweroftwo(0) + , m_usevbo(0) + , m_usepbo(0) + , m_usefbo(0) + , m_useglsl(0) + , m_glsl(nullptr) + , m_glsl_program_num(0) + , m_glsl_program_mb2sc(0) + , m_usetexturerect(0) + , m_init_context(0) + , m_last_hofs(0.0f) + , m_last_vofs(0.0f) + , m_surf_w(0) + , m_surf_h(0) + { + for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++) + m_texhash[i] = nullptr; + for (int i=0; i < 2*GLSL_SHADER_MAX; i++) + m_glsl_program[i] = 0; + for (int i=0; i < 8; i++) + m_texVerticex[i] = 0.0f; + } + virtual ~renderer_ogl() + { + // free the memory in the window + destroy_all_textures(); + } + + virtual int create() override; + virtual int draw(const int update) override; + +#ifndef OSD_WINDOWS + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; +#endif + virtual render_primitive_list *get_primitives() override + { + osd_dim nd = window().get_size(); + if (nd != m_blit_dim) + { + m_blit_dim = nd; + notify_changed(); + } + if ((m_blit_dim.width() == 0) || (m_blit_dim.height() == 0)) + return nullptr; + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); + } + +#ifdef OSD_WINDOWS + virtual void save() override { } + virtual void record() override { } + virtual void toggle_fsfx() override { } +#endif + +private: + static const uint32_t HASH_SIZE = ((1 << 10) + 1); + static const uint32_t OVERFLOW_SIZE = (1 << 10); + + void destroy_all_textures(); + + void loadGLExtensions(); + void initialize_gl(); + void set_blendmode(int blendmode); + HashT texture_compute_hash(const render_texinfo *texture, uint32_t flags); + void texture_compute_type_subroutine(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); + void texture_compute_size_subroutine(ogl_texture_info *texture, uint32_t flags, + uint32_t width, uint32_t height, + int* p_width, int* p_height, int* p_width_create, int* p_height_create); + void texture_compute_size_type(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); + ogl_texture_info *texture_create(const render_texinfo *texsource, uint32_t flags); + int texture_shader_create(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); + ogl_texture_info *texture_find(const render_primitive *prim); + void texture_coord_update(ogl_texture_info *texture, const render_primitive *prim, int shaderIdx); + void texture_mpass_flip(ogl_texture_info *texture, int shaderIdx); + void texture_shader_update(ogl_texture_info *texture, render_container *container, int shaderIdx); + ogl_texture_info * texture_update(const render_primitive *prim, int shaderIdx); + void texture_disable(ogl_texture_info * texture); + void texture_all_disable(); + + int gl_checkFramebufferStatus() const; + int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) const; + void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) const; + + ogl_video_config const &m_ogl_config; + + int32_t m_blittimer; + int m_width; + int m_height; + osd_dim m_blit_dim; + + std::unique_ptr<osd_gl_context> m_gl_context; + + int m_initialized; // is everything well initialized, i.e. all GL stuff etc. + // 3D info (GL mode only) + ogl_texture_info * m_texhash[HASH_SIZE + OVERFLOW_SIZE]; + int m_last_blendmode; // previous blendmode + int32_t m_texture_max_width; // texture maximum width + int32_t m_texture_max_height; // texture maximum height + int m_texpoweroftwo; // must textures be power-of-2 sized? + int m_usevbo; // runtime check if VBO is available + int m_usepbo; // runtime check if PBO is available + int m_usefbo; // runtime check if FBO is available + int m_useglsl; // runtime check if GLSL is available + + glsl_shader_info *m_glsl; // glsl_shader_info + + GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0 + int m_glsl_program_num; // number of GLSL programs + int m_glsl_program_mb2sc; // GLSL program idx, which transforms + // the mame-bitmap. screen-bitmap (size/rotation/..) + // All progs <= glsl_program_mb2sc using the mame bitmap + // as input, otherwise the screen bitmap. + // All progs >= glsl_program_mb2sc using the screen bitmap + // as output, otherwise the mame bitmap. + int m_usetexturerect; // use ARB_texture_rectangle for non-power-of-2, general use + + int m_init_context; // initialize context before next draw + + float m_last_hofs; + float m_last_vofs; + + // Static vars from draogl_window_dra + int32_t m_surf_w; + int32_t m_surf_h; + GLfloat m_texVerticex[8]; + + // OGL 1.3 +#if defined(GL_ARB_multitexture) && !defined(OSD_MAC) + PFNGLACTIVETEXTUREARBPROC m_glActiveTexture = nullptr; +#else + PFNGLACTIVETEXTUREPROC m_glActiveTexture = nullptr; +#endif + + // VBO + PFNGLGENBUFFERSPROC m_glGenBuffers = nullptr; + PFNGLDELETEBUFFERSPROC m_glDeleteBuffers = nullptr; + PFNGLBINDBUFFERPROC m_glBindBuffer = nullptr; + PFNGLBUFFERDATAPROC m_glBufferData = nullptr; + PFNGLBUFFERSUBDATAPROC m_glBufferSubData = nullptr; + + // PBO + PFNGLMAPBUFFERPROC m_glMapBuffer = nullptr; + PFNGLUNMAPBUFFERPROC m_glUnmapBuffer = nullptr; + + // FBO + PFNGLISFRAMEBUFFEREXTPROC m_glIsFramebuffer = nullptr; + PFNGLBINDFRAMEBUFFEREXTPROC m_glBindFramebuffer = nullptr; + PFNGLDELETEFRAMEBUFFERSEXTPROC m_glDeleteFramebuffers = nullptr; + PFNGLGENFRAMEBUFFERSEXTPROC m_glGenFramebuffers = nullptr; + PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC m_glCheckFramebufferStatus = nullptr; + PFNGLFRAMEBUFFERTEXTURE2DEXTPROC m_glFramebufferTexture2D = nullptr; + + static bool s_shown_video_info; +}; + //============================================================ // DEBUGGING @@ -241,101 +525,19 @@ void renderer_ogl::set_blendmode(int blendmode) } } -//============================================================ -// STATIC VARIABLES -//============================================================ - -// OGL 1.3 -#if defined(GL_ARB_multitexture) && !defined(OSD_MAC) -static PFNGLACTIVETEXTUREARBPROC pfn_glActiveTexture = nullptr; -#else -static PFNGLACTIVETEXTUREPROC pfn_glActiveTexture = nullptr; -#endif - -// VBO -static PFNGLGENBUFFERSPROC pfn_glGenBuffers = nullptr; -static PFNGLDELETEBUFFERSPROC pfn_glDeleteBuffers = nullptr; -static PFNGLBINDBUFFERPROC pfn_glBindBuffer = nullptr; -static PFNGLBUFFERDATAPROC pfn_glBufferData = nullptr; -static PFNGLBUFFERSUBDATAPROC pfn_glBufferSubData = nullptr; - -// PBO -static PFNGLMAPBUFFERPROC pfn_glMapBuffer = nullptr; -static PFNGLUNMAPBUFFERPROC pfn_glUnmapBuffer = nullptr; - -// FBO -static PFNGLISFRAMEBUFFEREXTPROC pfn_glIsFramebuffer = nullptr; -static PFNGLBINDFRAMEBUFFEREXTPROC pfn_glBindFramebuffer = nullptr; -static PFNGLDELETEFRAMEBUFFERSEXTPROC pfn_glDeleteFramebuffers = nullptr; -static PFNGLGENFRAMEBUFFERSEXTPROC pfn_glGenFramebuffers = nullptr; -static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pfn_glCheckFramebufferStatus = nullptr; -static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pfn_glFramebufferTexture2D = nullptr; - static int glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN; //============================================================ -// Textures -//============================================================ - -static void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags); - -//============================================================ // Static Variables //============================================================ bool renderer_ogl::s_shown_video_info = false; -bool renderer_ogl::s_dll_loaded = false; - -void renderer_ogl::init(running_machine &machine) -{ - s_dll_loaded = false; - - load_gl_lib(machine); -#if defined(OSD_WINDOWS) - osd_printf_verbose("Using Windows OpenGL driver\n"); -#else - osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n"); -#endif -} - -//============================================================ -// CONSTRUCTOR & DESTRUCTOR -//============================================================ - -renderer_ogl::~renderer_ogl() -{ - // free the memory in the window - destroy_all_textures(); - - delete m_gl_context; - m_gl_context = nullptr; -} - -void renderer_ogl::exit() -{ - for (int i = 0; i < video_config.glsl_shader_mamebm_num; i++) - { - if (nullptr != video_config.glsl_shader_mamebm[i]) - { - free(video_config.glsl_shader_mamebm[i]); - video_config.glsl_shader_mamebm[i] = nullptr; - } - } - for (int i =0; i < video_config.glsl_shader_scrn_num; i++) - { - if (nullptr != video_config.glsl_shader_scrn[i]) - { - free(video_config.glsl_shader_scrn[i]); - video_config.glsl_shader_scrn[i] = nullptr; - } - } -} //============================================================ // Load the OGL function addresses //============================================================ -static void loadgl_functions(osd_gl_context *context) +static void loadgl_functions(osd_gl_context &context) { #ifdef USE_DISPATCH_GL @@ -346,7 +548,7 @@ static void loadgl_functions(osd_gl_context *context) */ #define OSD_GL(ret,func,params) \ - if (!( func = (ret (APIENTRY *)params) context->getProcAddress( #func ) )) \ + if (!( func = (ret (APIENTRY *)params) context.getProcAddress( #func ) )) \ { err_count++; osd_printf_error("GL function %s not found!\n", #func ); } #define OSD_GL_UNUSED(ret,func,params) @@ -361,45 +563,6 @@ static void loadgl_functions(osd_gl_context *context) #endif } -//============================================================ -// Load GL library -//============================================================ - -#ifdef USE_DISPATCH_GL -osd_gl_dispatch *gl_dispatch = nullptr; -#endif - -void renderer_ogl::load_gl_lib(running_machine &machine) -{ - if (!s_dll_loaded) - { -#ifndef OSD_WINDOWS -#ifdef USE_DISPATCH_GL - /* - * directfb and and x11 use this env var - * SDL_VIDEO_GL_DRIVER - */ - const char *stemp; - - stemp = downcast<sdl_options &>(machine.options()).gl_lib(); - if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) == 0) - stemp = nullptr; - - if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==nullptr - { - fatalerror("Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); - } - osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); - /* FIXME: must be freed as well */ -#endif -#endif -#ifdef USE_DISPATCH_GL - gl_dispatch = new osd_gl_dispatch; -#endif - s_dll_loaded = true; - } -} - void renderer_ogl::initialize_gl() { int has_and_allow_texturerect = 0; @@ -425,7 +588,7 @@ void renderer_ogl::initialize_gl() m_usefbo = 0; m_useglsl = 0; - if (video_config.allowtexturerect && (strstr(extstr, "GL_ARB_texture_rectangle") || strstr(extstr, "GL_EXT_texture_rectangle"))) + if (m_ogl_config.allowtexturerect && (strstr(extstr, "GL_ARB_texture_rectangle") || strstr(extstr, "GL_EXT_texture_rectangle"))) { has_and_allow_texturerect = 1; if (!s_shown_video_info) @@ -435,7 +598,7 @@ void renderer_ogl::initialize_gl() } // does this card support non-power-of-two sized textures? (they're faster, so use them if possible) - if ( !video_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two")) + if ( !m_ogl_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two")) { if (!s_shown_video_info) { @@ -465,7 +628,7 @@ void renderer_ogl::initialize_gl() if (strstr(extstr, "GL_ARB_vertex_buffer_object")) { - m_usevbo = video_config.vbo; + m_usevbo = m_ogl_config.vbo; if (!s_shown_video_info) { if(m_usevbo) @@ -479,7 +642,7 @@ void renderer_ogl::initialize_gl() { if( m_usevbo ) { - m_usepbo = video_config.pbo; + m_usepbo = m_ogl_config.pbo; if (!s_shown_video_info) { if(m_usepbo) @@ -522,7 +685,7 @@ void renderer_ogl::initialize_gl() strstr(extstr, "GL_ARB_fragment_shader") ) { - m_useglsl = video_config.glsl; + m_useglsl = m_ogl_config.glsl; if (!s_shown_video_info) { if(m_useglsl) @@ -562,16 +725,14 @@ void renderer_ogl::initialize_gl() int renderer_ogl::create() { - auto win = assert_window(); - // create renderer #if defined(OSD_WINDOWS) - m_gl_context = new win_gl_context(std::static_pointer_cast<win_window_info>(win)->platform_window()); + m_gl_context.reset(new win_gl_context(dynamic_cast<win_window_info &>(window()).platform_window())); #elif defined(OSD_MAC) // TODO -// m_gl_context = new mac_gl_context(std::static_pointer_cast<mac_window_info>(win)->platform_window()); +// m_gl_context.reset(new mac_gl_context(dynamic_cast<mac_window_info &>(window()).platform_window())); #else - m_gl_context = new sdl_gl_context(std::static_pointer_cast<sdl_window_info>(win)->platform_window()); + m_gl_context.reset(new sdl_gl_context(dynamic_cast<sdl_window_info &>(window()).platform_window())); #endif if (m_gl_context->LastErrorMsg() != nullptr) { @@ -580,7 +741,6 @@ int renderer_ogl::create() } m_gl_context->SetSwapInterval(video_config.waitvsync ? 1 : 0); - m_blittimer = 0; m_surf_w = 0; m_surf_h = 0; @@ -595,10 +755,9 @@ int renderer_ogl::create() /* load any GL function addresses * this must be done here because we need a context */ - loadgl_functions(m_gl_context); + loadgl_functions(*m_gl_context); initialize_gl(); - m_init_context = 0; osd_printf_verbose("Leave renderer_ogl::create\n"); @@ -628,27 +787,15 @@ int renderer_ogl::xy_to_render_target(int x, int y, int *xt, int *yt) void renderer_ogl::destroy_all_textures() { - ogl_texture_info *texture = nullptr; - bool lock=false; - int i; - if ( !m_initialized ) - return; - - auto win = try_getwindow(); - - // During destroy this can get called - // and the window is no longer available - if (win == nullptr) + if (!m_initialized) return; m_gl_context->MakeCurrent(); - if(win->m_primlist) - { - lock=true; - win->m_primlist->acquire_lock(); - } + bool const lock = bool(window().m_primlist); + if (lock) + window().m_primlist->acquire_lock(); glFinish(); @@ -656,41 +803,39 @@ void renderer_ogl::destroy_all_textures() glFinish(); glDisableClientState(GL_VERTEX_ARRAY); - i=0; - while (i<HASH_SIZE+OVERFLOW_SIZE) + for (int i = 0; i < (HASH_SIZE + OVERFLOW_SIZE); ++i) { - texture = m_texhash[i]; - m_texhash[i] = nullptr; - if (texture != nullptr) + ogl_texture_info *const texture = std::exchange(m_texhash[i], nullptr); + if (texture) { - if(m_usevbo) + if (m_usevbo) { - pfn_glDeleteBuffers( 1, &(texture->texCoordBufferName) ); + m_glDeleteBuffers( 1, &(texture->texCoordBufferName) ); texture->texCoordBufferName=0; } - if(m_usepbo && texture->pbo) + if (m_usepbo && texture->pbo) { - pfn_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) ); + m_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) ); texture->pbo=0; } - if( m_glsl_program_num > 1 ) + if (m_glsl_program_num > 1) { assert(m_usefbo); - pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); + m_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); glDeleteTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]); } - if ( m_glsl_program_mb2sc < m_glsl_program_num - 1 ) + if (m_glsl_program_mb2sc < m_glsl_program_num - 1) { assert(m_usefbo); - pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); + m_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); glDeleteTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]); } glDeleteTextures(1, (GLuint *)&texture->texture); - if ( texture->data_own ) + if (texture->data_own) { free(texture->data); texture->data=nullptr; @@ -698,9 +843,9 @@ void renderer_ogl::destroy_all_textures() } delete texture; } - i++; } - if ( m_useglsl ) + + if (m_useglsl) { glsl_shader_free(m_glsl); m_glsl = nullptr; @@ -709,7 +854,7 @@ void renderer_ogl::destroy_all_textures() m_initialized = 0; if (lock) - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); } //============================================================ // loadGLExtensions @@ -747,55 +892,55 @@ void renderer_ogl::loadGLExtensions() // VBO: if( m_usevbo ) { - pfn_glGenBuffers = (PFNGLGENBUFFERSPROC) m_gl_context->getProcAddress("glGenBuffers"); - pfn_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) m_gl_context->getProcAddress("glDeleteBuffers"); - pfn_glBindBuffer = (PFNGLBINDBUFFERPROC) m_gl_context->getProcAddress("glBindBuffer"); - pfn_glBufferData = (PFNGLBUFFERDATAPROC) m_gl_context->getProcAddress("glBufferData"); - pfn_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) m_gl_context->getProcAddress("glBufferSubData"); + m_glGenBuffers = (PFNGLGENBUFFERSPROC) m_gl_context->getProcAddress("glGenBuffers"); + m_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) m_gl_context->getProcAddress("glDeleteBuffers"); + m_glBindBuffer = (PFNGLBINDBUFFERPROC) m_gl_context->getProcAddress("glBindBuffer"); + m_glBufferData = (PFNGLBUFFERDATAPROC) m_gl_context->getProcAddress("glBufferData"); + m_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) m_gl_context->getProcAddress("glBufferSubData"); } // PBO: if ( m_usepbo ) { - pfn_glMapBuffer = (PFNGLMAPBUFFERPROC) m_gl_context->getProcAddress("glMapBuffer"); - pfn_glUnmapBuffer= (PFNGLUNMAPBUFFERPROC) m_gl_context->getProcAddress("glUnmapBuffer"); + m_glMapBuffer = (PFNGLMAPBUFFERPROC) m_gl_context->getProcAddress("glMapBuffer"); + m_glUnmapBuffer= (PFNGLUNMAPBUFFERPROC) m_gl_context->getProcAddress("glUnmapBuffer"); } // FBO: if ( m_usefbo ) { - pfn_glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glIsFramebufferEXT"); - pfn_glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glBindFramebufferEXT"); - pfn_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glDeleteFramebuffersEXT"); - pfn_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glGenFramebuffersEXT"); - pfn_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) m_gl_context->getProcAddress("glCheckFramebufferStatusEXT"); - pfn_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) m_gl_context->getProcAddress("glFramebufferTexture2DEXT"); + m_glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glIsFramebufferEXT"); + m_glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glBindFramebufferEXT"); + m_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glDeleteFramebuffersEXT"); + m_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glGenFramebuffersEXT"); + m_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) m_gl_context->getProcAddress("glCheckFramebufferStatusEXT"); + m_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) m_gl_context->getProcAddress("glFramebufferTexture2DEXT"); } if ( m_usevbo && - ( !pfn_glGenBuffers || !pfn_glDeleteBuffers || - !pfn_glBindBuffer || !pfn_glBufferData || !pfn_glBufferSubData + ( !m_glGenBuffers || !m_glDeleteBuffers || + !m_glBindBuffer || !m_glBufferData || !m_glBufferSubData ) ) { m_usepbo=false; if (_once) { osd_printf_warning("OpenGL: VBO not supported, missing: "); - if (!pfn_glGenBuffers) + if (!m_glGenBuffers) { osd_printf_warning("glGenBuffers, "); } - if (!pfn_glDeleteBuffers) + if (!m_glDeleteBuffers) { osd_printf_warning("glDeleteBuffers"); } - if (!pfn_glBindBuffer) + if (!m_glBindBuffer) { osd_printf_warning("glBindBuffer, "); } - if (!pfn_glBufferData) + if (!m_glBufferData) { osd_printf_warning("glBufferData, "); } - if (!pfn_glBufferSubData) + if (!m_glBufferSubData) { osd_printf_warning("glBufferSubData, "); } @@ -811,17 +956,17 @@ void renderer_ogl::loadGLExtensions() } } - if ( m_usepbo && ( !pfn_glMapBuffer || !pfn_glUnmapBuffer ) ) + if ( m_usepbo && ( !m_glMapBuffer || !m_glUnmapBuffer ) ) { m_usepbo=false; if (_once) { osd_printf_warning("OpenGL: PBO not supported, missing: "); - if (!pfn_glMapBuffer) + if (!m_glMapBuffer) { osd_printf_warning("glMapBuffer, "); } - if (!pfn_glUnmapBuffer) + if (!m_glUnmapBuffer) { osd_printf_warning("glUnmapBuffer, "); } @@ -830,37 +975,37 @@ void renderer_ogl::loadGLExtensions() } if ( m_usefbo && - ( !pfn_glIsFramebuffer || !pfn_glBindFramebuffer || !pfn_glDeleteFramebuffers || - !pfn_glGenFramebuffers || !pfn_glCheckFramebufferStatus || !pfn_glFramebufferTexture2D + ( !m_glIsFramebuffer || !m_glBindFramebuffer || !m_glDeleteFramebuffers || + !m_glGenFramebuffers || !m_glCheckFramebufferStatus || !m_glFramebufferTexture2D )) { m_usefbo=false; if (_once) { osd_printf_warning("OpenGL: FBO not supported, missing: "); - if (!pfn_glIsFramebuffer) + if (!m_glIsFramebuffer) { - osd_printf_warning("pfn_glIsFramebuffer, "); + osd_printf_warning("m_glIsFramebuffer, "); } - if (!pfn_glBindFramebuffer) + if (!m_glBindFramebuffer) { - osd_printf_warning("pfn_glBindFramebuffer, "); + osd_printf_warning("m_glBindFramebuffer, "); } - if (!pfn_glDeleteFramebuffers) + if (!m_glDeleteFramebuffers) { - osd_printf_warning("pfn_glDeleteFramebuffers, "); + osd_printf_warning("m_glDeleteFramebuffers, "); } - if (!pfn_glGenFramebuffers) + if (!m_glGenFramebuffers) { - osd_printf_warning("pfn_glGenFramebuffers, "); + osd_printf_warning("m_glGenFramebuffers, "); } - if (!pfn_glCheckFramebufferStatus) + if (!m_glCheckFramebufferStatus) { - osd_printf_warning("pfn_glCheckFramebufferStatus, "); + osd_printf_warning("m_glCheckFramebufferStatus, "); } - if (!pfn_glFramebufferTexture2D) + if (!m_glFramebufferTexture2D) { - osd_printf_warning("pfn_glFramebufferTexture2D, "); + osd_printf_warning("m_glFramebufferTexture2D, "); } osd_printf_warning("\n"); } @@ -899,11 +1044,11 @@ void renderer_ogl::loadGLExtensions() if ( m_useglsl ) { #if defined(GL_ARB_multitexture) && !defined(OSD_MAC) - pfn_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB"); + m_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB"); #else - pfn_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture"); + m_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture"); #endif - if (!pfn_glActiveTexture) + if (!m_glActiveTexture) { if (_once) { @@ -915,7 +1060,7 @@ void renderer_ogl::loadGLExtensions() if ( m_useglsl ) { - m_glsl = glsl_shader_init(m_gl_context); + m_glsl = glsl_shader_init(m_gl_context.get()); m_useglsl = (m_glsl != nullptr ? 1 : 0); if ( ! m_useglsl ) @@ -927,9 +1072,9 @@ void renderer_ogl::loadGLExtensions() } } - if ( m_useglsl ) + if (m_useglsl) { - if (assert_window()->prescale() != 1 ) + if (window().prescale() != 1 ) { m_useglsl = 0; if (_once) @@ -939,7 +1084,7 @@ void renderer_ogl::loadGLExtensions() } } - if ( m_useglsl ) + if (m_useglsl) { int i; video_config.filter = false; @@ -947,7 +1092,7 @@ void renderer_ogl::loadGLExtensions() m_glsl_program_num = 0; m_glsl_program_mb2sc = 0; - for(i=0; i<video_config.glsl_shader_mamebm_num; i++) + for(i=0; i<m_ogl_config.glsl_shader_mamebm_num; i++) { if ( !m_usefbo && m_glsl_program_num==1 ) { @@ -958,50 +1103,50 @@ void renderer_ogl::loadGLExtensions() break; } - if ( glsl_shader_add_mamebm(m_glsl, video_config.glsl_shader_mamebm[i], m_glsl_program_num) ) + if ( glsl_shader_add_mamebm(m_glsl, m_ogl_config.glsl_shader_mamebm[i].c_str(), m_glsl_program_num) ) { osd_printf_error("OpenGL: GLSL loading mame bitmap shader %d failed (%s)\n", - i, video_config.glsl_shader_mamebm[i]); + i, m_ogl_config.glsl_shader_mamebm[i]); } else { glsl_shader_feature = GLSL_SHADER_FEAT_CUSTOM; if (_once) { osd_printf_verbose("OpenGL: GLSL using mame bitmap shader filter %d: '%s'\n", - m_glsl_program_num, video_config.glsl_shader_mamebm[i]); + m_glsl_program_num, m_ogl_config.glsl_shader_mamebm[i]); } m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it. m_glsl_program_num++; } } - if ( video_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 ) + if ( m_ogl_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 ) { osd_printf_verbose("OpenGL: GLSL cannot use screen bitmap shader without bitmap shader\n"); } - for(i=0; m_usefbo && m_glsl_program_num>0 && i<video_config.glsl_shader_scrn_num; i++) + for(i=0; m_usefbo && m_glsl_program_num>0 && i<m_ogl_config.glsl_shader_scrn_num; i++) { - if ( glsl_shader_add_scrn(m_glsl, video_config.glsl_shader_scrn[i], + if ( glsl_shader_add_scrn(m_glsl, m_ogl_config.glsl_shader_scrn[i].c_str(), m_glsl_program_num-1-m_glsl_program_mb2sc) ) { osd_printf_error("OpenGL: GLSL loading screen bitmap shader %d failed (%s)\n", - i, video_config.glsl_shader_scrn[i]); + i, m_ogl_config.glsl_shader_scrn[i]); } else { if (_once) { osd_printf_verbose("OpenGL: GLSL using screen bitmap shader filter %d: '%s'\n", - m_glsl_program_num, video_config.glsl_shader_scrn[i]); + m_glsl_program_num, m_ogl_config.glsl_shader_scrn[i]); } m_glsl_program_num++; } } if ( 0==m_glsl_program_num && - 0 <= video_config.glsl_filter && video_config.glsl_filter < GLSL_SHADER_FEAT_INT_NUMBER ) + 0 <= m_ogl_config.glsl_filter && m_ogl_config.glsl_filter < GLSL_SHADER_FEAT_INT_NUMBER ) { m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it. m_glsl_program_num++; - glsl_shader_feature = video_config.glsl_filter; + glsl_shader_feature = m_ogl_config.glsl_filter; if (_once) { @@ -1031,16 +1176,7 @@ int renderer_ogl::draw(const int update) float vofs, hofs; int pendingPrimitive=GL_NO_PRIMITIVE, curPrimitive=GL_NO_PRIMITIVE; -#ifdef TOBEMIGRATED - if (video_config.novideo) - { - return 0; - } -#endif - - auto win = assert_window(); - - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) { @@ -1192,16 +1328,15 @@ int renderer_ogl::draw(const int update) hofs = (cw - m_blit_dim.width()) / 2.0f; } } -#else #endif m_last_hofs = hofs; m_last_vofs = vofs; - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // now draw - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { int i; @@ -1407,7 +1542,7 @@ int renderer_ogl::draw(const int update) pendingPrimitive=GL_NO_PRIMITIVE; } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); m_init_context = 0; m_gl_context->SwapBuffer(); @@ -1543,9 +1678,8 @@ void renderer_ogl::texture_compute_size_subroutine(ogl_texture_info *texture, ui while (texture->yprescale > 1 && height_create * texture->yprescale > m_texture_max_height) texture->yprescale--; - auto win = assert_window(); - if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != win->prescale() || texture->yprescale != win->prescale())) - osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", win->prescale(), win->prescale(), texture->xprescale, texture->yprescale); + if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != window().prescale() || texture->yprescale != window().prescale())) + osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", window().prescale(), window().prescale(), texture->xprescale, texture->yprescale); width *= texture->xprescale; height *= texture->yprescale; @@ -1640,10 +1774,9 @@ void renderer_ogl::texture_compute_size_type(const render_texinfo *texsource, og // texture_create //============================================================ -static int gl_checkFramebufferStatus() +int renderer_ogl::gl_checkFramebufferStatus() const { - GLenum status; - status=(GLenum)pfn_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + GLenum const status = (GLenum)m_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); switch(status) { case GL_FRAMEBUFFER_COMPLETE_EXT: return 0; @@ -1683,10 +1816,10 @@ static int gl_checkFramebufferStatus() return -1; } -static int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) +int renderer_ogl::texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) const { - pfn_glActiveTexture(text_unit); - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name); + m_glActiveTexture(text_unit); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name); glBindTexture(GL_TEXTURE_2D, text_name); { GLint _width, _height; @@ -1708,7 +1841,7 @@ static int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t f glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - pfn_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + m_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, text_name, 0); if ( gl_checkFramebufferStatus() ) @@ -1789,7 +1922,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex { // multipass mode // GL_TEXTURE2/GL_TEXTURE3 - pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); + m_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); glGenTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]); for (i=0; i<2; i++) @@ -1803,7 +1936,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex } } - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); osd_printf_verbose("GL texture: mpass mame-bmp 2x %dx%d (pow2 %dx%d)\n", texture->rawwidth, texture->rawheight, texture->rawwidth_create, texture->rawheight_create); @@ -1813,7 +1946,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex { // multipass mode // GL_TEXTURE2/GL_TEXTURE3 - pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); + m_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); glGenTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]); for (i=0; i<2; i++) @@ -1834,7 +1967,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex // GL_TEXTURE0 // get a name for this texture glGenTextures(1, (GLuint *)&texture->texture); - pfn_glActiveTexture(GL_TEXTURE0); + m_glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture->texture); glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth_create); @@ -1907,9 +2040,8 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, texture->texinfo.seqid = -1; // force set data if (PRIMFLAG_GET_SCREENTEX(flags)) { - auto win = assert_window(); - texture->xprescale = win->prescale(); - texture->yprescale = win->prescale(); + texture->xprescale = window().prescale(); + texture->yprescale = window().prescale(); } else { @@ -2028,12 +2160,12 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, assert(m_usepbo); // create the PBO - pfn_glGenBuffers(1, (GLuint *)&texture->pbo); + m_glGenBuffers(1, (GLuint *)&texture->pbo); - pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); + m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); // set up the PBO dimension, .. - pfn_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, + m_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, texture->rawwidth * texture->rawheight * sizeof(uint32_t), nullptr, GL_STREAM_DRAW); } @@ -2063,10 +2195,10 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, if (m_usevbo) { // Generate And Bind The Texture Coordinate Buffer - pfn_glGenBuffers( 1, &(texture->texCoordBufferName) ); - pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); + m_glGenBuffers( 1, &(texture->texCoordBufferName) ); + m_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); // Load The Data - pfn_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW ); + m_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW ); glTexCoordPointer( 2, GL_FLOAT, 0, (char *) nullptr ); // we are using ARB VBO buffers } else @@ -2327,14 +2459,14 @@ static inline void copyline_yuy16_to_argb(uint32_t *dst, const uint16_t *src, in // texture_set_data //============================================================ -static void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) +void renderer_ogl::texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) const { if ( texture->type == TEXTURE_TYPE_DYNAMIC ) { assert(texture->pbo); assert(!texture->nocopy); - texture->data = (uint32_t *) pfn_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); + texture->data = (uint32_t *) m_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } // note that nocopy and borderpix are mutually exclusive, IOW @@ -2401,7 +2533,7 @@ static void texture_set_data(ogl_texture_info *texture, const render_texinfo *te if ( texture->type == TEXTURE_TYPE_SHADER ) { - pfn_glActiveTexture(GL_TEXTURE0); + m_glActiveTexture(GL_TEXTURE0); glBindTexture(texture->texTarget, texture->texture); if (texture->nocopy) @@ -2420,7 +2552,7 @@ static void texture_set_data(ogl_texture_info *texture, const render_texinfo *te glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth); // unmap the buffer from the CPU space so it can DMA - pfn_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); + m_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); // kick off the DMA glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight, @@ -2575,7 +2707,7 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx) GL_CHECK_ERROR_NORMAL(); } - pfn_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]); + m_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]); if ( shaderIdx<=m_glsl_program_mb2sc ) { glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[mpass_src_idx]); @@ -2584,22 +2716,22 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx) { glBindTexture(texture->texTarget, texture->mpass_texture_scrn[mpass_src_idx]); } - pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); + m_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); glBindTexture(texture->texTarget, 0); - pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); + m_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); if ( shaderIdx<m_glsl_program_num-1 ) { if ( shaderIdx>=m_glsl_program_mb2sc ) { glBindTexture(texture->texTarget, texture->mpass_texture_scrn[texture->mpass_dest_idx]); - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]); } else { glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[texture->mpass_dest_idx]); - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]); } if ( shaderIdx==0 ) @@ -2620,7 +2752,7 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx) else { glBindTexture(texture->texTarget, 0); - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); if ( m_glsl_program_mb2sc == m_glsl_program_num-1 ) { @@ -2628,7 +2760,7 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx) GL_CHECK_ERROR_NORMAL(); } - pfn_glActiveTexture(GL_TEXTURE0); + m_glActiveTexture(GL_TEXTURE0); glBindTexture(texture->texTarget, 0); } } @@ -2676,7 +2808,7 @@ ogl_texture_info * renderer_ogl::texture_update(const render_primitive *prim, in else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) { assert ( m_usepbo ) ; - pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); + m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); glEnable(texture->texTarget); } else @@ -2716,9 +2848,9 @@ ogl_texture_info * renderer_ogl::texture_update(const render_primitive *prim, in glEnableClientState(GL_TEXTURE_COORD_ARRAY); if(m_usevbo) { - pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); + m_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); // Load The Data - pfn_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord ); + m_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord ); glTexCoordPointer( 2, GL_FLOAT, 0, (char *) nullptr ); // we are using ARB VBO buffers } else @@ -2736,11 +2868,14 @@ void renderer_ogl::texture_disable(ogl_texture_info * texture) { assert ( m_useglsl ); pfn_glUseProgramObjectARB(0); // back to fixed function pipeline - } else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) + } + else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) { - pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); + m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDisable(texture->texTarget); - } else { + } + else + { glDisable(texture->texTarget); } } @@ -2751,18 +2886,18 @@ void renderer_ogl::texture_all_disable() { pfn_glUseProgramObjectARB(0); // back to fixed function pipeline - pfn_glActiveTexture(GL_TEXTURE3); + m_glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, 0); - if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - pfn_glActiveTexture(GL_TEXTURE2); + if ( m_usefbo ) m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0); - if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - pfn_glActiveTexture(GL_TEXTURE1); + if ( m_usefbo ) m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); - if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - pfn_glActiveTexture(GL_TEXTURE0); + if ( m_usefbo ) m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); - if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + if ( m_usefbo ) m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); @@ -2775,10 +2910,143 @@ void renderer_ogl::texture_all_disable() glDisableClientState(GL_TEXTURE_COORD_ARRAY); if(m_usevbo) { - pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind .. + m_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind .. } if ( m_usepbo ) { - pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); + m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); } } + + +class video_opengl : public osd_module, public render_module +{ +public: + video_opengl() + : osd_module(OSD_RENDERER_PROVIDER, "opengl") +#ifdef USE_DISPATCH_GL + , m_dll_loaded(false) +#endif + { + } + ~video_opengl() { exit(); } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE | FLAG_SDL_NEEDS_OPENGL; } + +private: + ogl_video_config m_ogl_config; +#ifdef USE_DISPATCH_GL + std::unique_ptr<osd_gl_dispatch> m_gl_dispatch; + bool m_dll_loaded; +#endif +}; + +int video_opengl::init(osd_interface &osd, osd_options const &options) +{ + m_ogl_config.vbo = options.gl_vbo(); + m_ogl_config.pbo = options.gl_pbo(); + m_ogl_config.allowtexturerect = !options.gl_no_texture_rect(); + m_ogl_config.forcepow2texture = options.gl_force_pow2_texture(); + m_ogl_config.glsl = options.gl_glsl(); + if (m_ogl_config.glsl) + { + m_ogl_config.glsl_filter = options.glsl_filter(); + + m_ogl_config.glsl_shader_mamebm_num = 0; + for (int i = 0; i < GLSL_SHADER_MAX; i++) + { + char const *const stemp = options.shader_mame(i); + if (stemp && *stemp && strcmp(stemp, OSDOPTVAL_NONE)) + m_ogl_config.glsl_shader_mamebm[m_ogl_config.glsl_shader_mamebm_num++] = stemp; + } + + m_ogl_config.glsl_shader_scrn_num = 0; + for (int i = 0; i < GLSL_SHADER_MAX; i++) + { + char const *const stemp = options.shader_screen(i); + if (stemp && *stemp && strcmp(stemp, OSDOPTVAL_NONE)) + m_ogl_config.glsl_shader_scrn[m_ogl_config.glsl_shader_scrn_num++] = stemp; + } + } + else + { + m_ogl_config.glsl_filter = 0; + + m_ogl_config.glsl_shader_mamebm_num = 0; + for (std::string &s : m_ogl_config.glsl_shader_mamebm) + s.clear(); + + m_ogl_config.glsl_shader_scrn_num = 0; + for (std::string &s : m_ogl_config.glsl_shader_scrn) + s.clear(); + } + +#if defined(USE_DISPATCH_GL) +#if defined(OSD_SDL) + if (!m_dll_loaded) + { + // directfb and and x11 use this env var: SDL_VIDEO_GL_DRIVER + char const *libname = dynamic_cast<sdl_options const &>(options).gl_lib(); + if (libname && (!*libname || !std::strcmp(libname, OSDOPTVAL_AUTO))) + libname = nullptr; + + if (SDL_GL_LoadLibrary(libname) != 0) + { + osd_printf_error("Unable to load OpenGL shared library: %s\n", libname ? libname : "<default>"); + return -1; + } + + osd_printf_verbose("Loaded OpenGL shared library: %s\n", libname ? libname : "<default>"); + } +#endif // defined(OSD_SDL) + m_dll_loaded = true; + m_gl_dispatch = std::make_unique<osd_gl_dispatch>(); +#endif // defined(USE_DISPATCH_GL) + +#if defined(OSD_WINDOWS) + osd_printf_verbose("Using Windows OpenGL driver\n"); +#else // defined(OSD_WINDOWS) + osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n"); +#endif // defined(OSD_WINDOWS) + + return 0; +} + +void video_opengl::exit() +{ +#if defined(USE_DISPATCH_GL) +#if defined(OSD_SDL) + if (m_dll_loaded) + SDL_GL_UnloadLibrary(); +#endif // defined(OSD_SDL) + m_gl_dispatch.reset(); + m_dll_loaded = false; +#endif // defined(USE_DISPATCH_GL) + + m_ogl_config = ogl_video_config(); +} + +std::unique_ptr<osd_renderer> video_opengl::create(osd_window &window) +{ + return std::make_unique<renderer_ogl>(window, m_ogl_config); +} + +} // anonymous namespace + +} // namespace osd + + +#else // USE_OPENGL + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_opengl, OSD_RENDERER_PROVIDER, "opengl") } } + +#endif // USE_OPENGL + + +MODULE_DEFINITION(RENDERER_OPENGL, osd::video_opengl) diff --git a/src/osd/modules/render/drawogl.h b/src/osd/modules/render/drawogl.h deleted file mode 100644 index 61b9794353c..00000000000 --- a/src/osd/modules/render/drawogl.h +++ /dev/null @@ -1,244 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert, R. Belmont -//============================================================ -// -// drawogl.h - SDL software and OpenGL implementation -// -// SDLMAME by Olivier Galibert and R. Belmont -// -//============================================================ -#ifndef MAME_OSD_MODULES_RENDER_DRAWOGL_H -#define MAME_OSD_MODULES_RENDER_DRAWOGL_H - -#pragma once - -// OSD headers -#ifndef OSD_WINDOWS -#ifdef OSD_MAC -#include "osdmac.h" -#else -#include "osdsdl.h" -#endif -#include "window.h" -#else -#include "../windows/window.h" -typedef uint64_t HashT; -#endif - -#if defined(OSD_WINDOWS) -#include "winglcontext.h" -#elif defined (OSD_MAC) -#else -#include "sdlglcontext.h" -#endif - -#include "modules/opengl/gl_shader_mgr.h" - -#include "emucore.h" -#include "render.h" - -//============================================================ -// Textures -//============================================================ - -/* ogl_texture_info holds information about a texture */ -class ogl_texture_info -{ -public: - ogl_texture_info() - : hash(0), flags(0), rawwidth(0), rawheight(0), - rawwidth_create(0), rawheight_create(0), - type(0), format(0), borderpix(0), xprescale(0), yprescale(0), nocopy(0), - texture(0), texTarget(0), texpow2(0), mpass_dest_idx(0), pbo(0), data(nullptr), - data_own(0), texCoordBufferName(0) - { - for (int i=0; i<2; i++) - { - mpass_textureunit[i] = 0; - mpass_texture_mamebm[i] = 0; - mpass_fbo_mamebm[i] = 0; - mpass_texture_scrn[i] = 0; - mpass_fbo_scrn[i] = 0; - } - for (int i=0; i<8; i++) - texCoord[i] = 0.0f; - } - - HashT hash; // hash value for the texture (must be >= pointer size) - uint32_t flags; // rendering flags - render_texinfo texinfo; // copy of the texture info - int rawwidth, rawheight; // raw width/height of the texture - int rawwidth_create; // raw width/height, pow2 compatible, if needed - int rawheight_create; // (create and initial set the texture, not for copy!) - int type; // what type of texture are we? - int format; // texture format - int borderpix; // do we have a 1 pixel border? - int xprescale; // what is our X prescale factor? - int yprescale; // what is our Y prescale factor? - int nocopy; // must the texture date be copied? - - uint32_t texture; // OpenGL texture "name"/ID - - GLenum texTarget; // OpenGL texture target - int texpow2; // Is this texture pow2 - - uint32_t mpass_dest_idx; // Multipass dest idx [0..1] - uint32_t mpass_textureunit[2]; // texture unit names for GLSL - - uint32_t mpass_texture_mamebm[2];// Multipass OpenGL texture "name"/ID for the shader - uint32_t mpass_fbo_mamebm[2]; // framebuffer object for this texture, multipass - uint32_t mpass_texture_scrn[2]; // Multipass OpenGL texture "name"/ID for the shader - uint32_t mpass_fbo_scrn[2]; // framebuffer object for this texture, multipass - - uint32_t pbo; // pixel buffer object for this texture (DYNAMIC only!) - uint32_t *data; // pixels for the texture - int data_own; // do we own / allocated it ? - GLfloat texCoord[8]; - GLuint texCoordBufferName; - -}; - -/* renderer_ogl is the information about OpenGL for the current screen */ -class renderer_ogl : public osd_renderer -{ -public: - renderer_ogl(std::shared_ptr<osd_window> window) - : osd_renderer(window, FLAG_NEEDS_OPENGL) - , m_blittimer(0) - , m_width(0) - , m_height(0) - , m_blit_dim(0, 0) - , m_gl_context(nullptr) - , m_initialized(0) - , m_last_blendmode(0) - , m_texture_max_width(0) - , m_texture_max_height(0) - , m_texpoweroftwo(0) - , m_usevbo(0) - , m_usepbo(0) - , m_usefbo(0) - , m_useglsl(0) - , m_glsl(nullptr) - , m_glsl_program_num(0) - , m_glsl_program_mb2sc(0) - , m_usetexturerect(0) - , m_init_context(0) - , m_last_hofs(0.0f) - , m_last_vofs(0.0f) - , m_surf_w(0) - , m_surf_h(0) - { - for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++) - m_texhash[i] = nullptr; - for (int i=0; i < 2*GLSL_SHADER_MAX; i++) - m_glsl_program[i] = 0; - for (int i=0; i < 8; i++) - m_texVerticex[i] = 0.0f; - } - virtual ~renderer_ogl(); - - static void init(running_machine &machine); - static void exit(); - - virtual int create() override; - virtual int draw(const int update) override; - -#ifndef OSD_WINDOWS - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; -#endif - virtual render_primitive_list *get_primitives() override - { - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - - osd_dim nd = win->get_size(); - if (nd != m_blit_dim) - { - m_blit_dim = nd; - notify_changed(); - } - if ((m_blit_dim.width() == 0) || (m_blit_dim.height() == 0)) - return nullptr; - win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect()); - return &win->target()->get_primitives(); - } - -#ifdef OSD_WINDOWS - virtual void save() override { } - virtual void record() override { } - virtual void toggle_fsfx() override { } -#endif - -private: - static const uint32_t HASH_SIZE = ((1 << 10) + 1); - static const uint32_t OVERFLOW_SIZE = (1 << 10); - - void destroy_all_textures(); - - static void load_gl_lib(running_machine &machine); - void loadGLExtensions(); - void initialize_gl(); - void set_blendmode(int blendmode); - HashT texture_compute_hash(const render_texinfo *texture, uint32_t flags); - void texture_compute_type_subroutine(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); - void texture_compute_size_subroutine(ogl_texture_info *texture, uint32_t flags, - uint32_t width, uint32_t height, - int* p_width, int* p_height, int* p_width_create, int* p_height_create); - void texture_compute_size_type(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); - ogl_texture_info *texture_create(const render_texinfo *texsource, uint32_t flags); - int texture_shader_create(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); - ogl_texture_info *texture_find(const render_primitive *prim); - void texture_coord_update(ogl_texture_info *texture, const render_primitive *prim, int shaderIdx); - void texture_mpass_flip(ogl_texture_info *texture, int shaderIdx); - void texture_shader_update(ogl_texture_info *texture, render_container *container, int shaderIdx); - ogl_texture_info * texture_update(const render_primitive *prim, int shaderIdx); - void texture_disable(ogl_texture_info * texture); - void texture_all_disable(); - - int32_t m_blittimer; - int m_width; - int m_height; - osd_dim m_blit_dim; - - osd_gl_context *m_gl_context; - - int m_initialized; // is everything well initialized, i.e. all GL stuff etc. - // 3D info (GL mode only) - ogl_texture_info * m_texhash[HASH_SIZE + OVERFLOW_SIZE]; - int m_last_blendmode; // previous blendmode - int32_t m_texture_max_width; // texture maximum width - int32_t m_texture_max_height; // texture maximum height - int m_texpoweroftwo; // must textures be power-of-2 sized? - int m_usevbo; // runtime check if VBO is available - int m_usepbo; // runtime check if PBO is available - int m_usefbo; // runtime check if FBO is available - int m_useglsl; // runtime check if GLSL is available - - glsl_shader_info *m_glsl; // glsl_shader_info - - GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0 - int m_glsl_program_num; // number of GLSL programs - int m_glsl_program_mb2sc; // GLSL program idx, which transforms - // the mame-bitmap. screen-bitmap (size/rotation/..) - // All progs <= glsl_program_mb2sc using the mame bitmap - // as input, otherwise the screen bitmap. - // All progs >= glsl_program_mb2sc using the screen bitmap - // as output, otherwise the mame bitmap. - int m_usetexturerect; // use ARB_texture_rectangle for non-power-of-2, general use - - int m_init_context; // initialize context before next draw - - float m_last_hofs; - float m_last_vofs; - - // Static vars from draogl_window_dra - int32_t m_surf_w; - int32_t m_surf_h; - GLfloat m_texVerticex[8]; - - static bool s_shown_video_info; - static bool s_dll_loaded; -}; - -#endif // MAME_OSD_MODULES_RENDER_DRAWOGL_H diff --git a/src/osd/modules/render/drawsdl.cpp b/src/osd/modules/render/drawsdl.cpp index 3d51b85c9a4..46aa098a7bc 100644 --- a/src/osd/modules/render/drawsdl.cpp +++ b/src/osd/modules/render/drawsdl.cpp @@ -2,7 +2,7 @@ // copyright-holders:Couriersud, Olivier Galibert, R. Belmont //============================================================ // -// drawsdl.c - SDL software and OpenGL implementation +// drawsdl.cpp - SDL software and OpenGL implementation // // SDLMAME by Olivier Galibert and R. Belmont // @@ -10,25 +10,37 @@ // //============================================================ -#include "drawsdl.h" +#include "render_module.h" + +#include "modules/osdmodule.h" + +#if defined(OSD_SDL) + +// from specific OSD implementation +#include "sdlopts.h" +#include "window.h" + +// general OSD headers +#include "modules/monitor/monitor_module.h" // MAME headers #include "emucore.h" +#include "render.h" #include "rendersw.hxx" -#include "ui/uimain.h" +//#include "ui/uimain.h" -// osd headers -#include "modules/monitor/monitor_module.h" +#include <SDL2/SDL.h> // standard C headers #include <cmath> #include <cstdio> +#include <memory> -//============================================================ -// DEBUGGING -//============================================================ +namespace osd { + +namespace { //============================================================ // CONSTANTS @@ -38,6 +50,76 @@ #define DRAW2_SCALEMODE_LINEAR "1" #define DRAW2_SCALEMODE_BEST "2" + +struct sdl_scale_mode +{ + const char *name; + int is_scale; /* Scale mode? */ + int is_yuv; /* Yuv mode? */ + int mult_w; /* Width multiplier */ + int mult_h; /* Height multiplier */ + const char *sdl_scale_mode_hint; /* what to use as a hint ? */ + int pixel_format; /* Pixel/Overlay format */ + void (*yuv_blit)(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height); +}; + + +// renderer_sdl1 is the information about SDL for the current screen +class renderer_sdl1 : public osd_renderer +{ +public: + + renderer_sdl1(osd_window &w, sdl_scale_mode const &scale_mode) + : osd_renderer(w) + , m_scale_mode(scale_mode) + , m_sdl_renderer(nullptr) + , m_texture_id(nullptr) + , m_yuv_lookup() + , m_yuv_bitmap() + //, m_hw_scale_width(0) + //, m_hw_scale_height(0) + , m_last_hofs(0) + , m_last_vofs(0) + , m_blit_dim(0, 0) + , m_last_dim(0, 0) + { + } + virtual ~renderer_sdl1(); + + virtual int create() override; + virtual int draw(const int update) override; + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; + virtual render_primitive_list *get_primitives() override; + +private: + void show_info(struct SDL_RendererInfo *render_info); + + void destroy_all_textures(); + void yuv_init(); + void setup_texture(const osd_dim &size); + void yuv_lookup_set(unsigned int pen, unsigned char red, + unsigned char green, unsigned char blue); + + int32_t m_blittimer; + + sdl_scale_mode const &m_scale_mode; + SDL_Renderer *m_sdl_renderer; + SDL_Texture *m_texture_id; + + // YUV overlay + std::unique_ptr<uint32_t []> m_yuv_lookup; + std::unique_ptr<uint16_t []> m_yuv_bitmap; + + // if we leave scaling to SDL and the underlying driver, this + // is the render_target_width/height to use + + int m_last_hofs; + int m_last_vofs; + osd_dim m_blit_dim; + osd_dim m_last_dim; +}; + + //============================================================ // PROTOTYPES //============================================================ @@ -53,84 +135,41 @@ static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitc static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ const uint32_t *lookup, const int width, const int height); -// Static declarations - -static const sdl_scale_mode scale_modes[] = -{ - { "none", 0, 0, 1, 1, DRAW2_SCALEMODE_NEAREST, 0, nullptr }, - { "hwblit", 1, 0, 1, 1, DRAW2_SCALEMODE_LINEAR, 0, nullptr }, - { "hwbest", 1, 0, 1, 1, DRAW2_SCALEMODE_BEST, 0, nullptr }, - /* SDL1.2 uses interpolation as well */ - { "yv12", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12 }, - { "yv12x2", 1, 1, 2, 2, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12X2 }, - { "yuy2", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2 }, - { "yuy2x2", 1, 1, 2, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2X2 }, - { nullptr } -}; - -int drawsdl_scale_mode(const char *s) -{ - const sdl_scale_mode *sm = scale_modes; - int index; - - index = 0; - while (sm->name != nullptr) - { - if (strcmp(sm->name, s) == 0) - return index; - index++; - sm++; - } - return -1; -} - -//============================================================ -// drawsdl_init -//============================================================ - -void renderer_sdl1::init(running_machine &machine) -{ - osd_printf_verbose("Using SDL multi-window soft driver (SDL 2.0+)\n"); -} - //============================================================ // setup_texture for window //============================================================ void renderer_sdl1::setup_texture(const osd_dim &size) { - const sdl_scale_mode *sdl_sm = &scale_modes[video_config.scale_mode]; SDL_DisplayMode mode; uint32_t fmt; - auto win = assert_window(); - // Determine preferred pixelformat and set up yuv if necessary - SDL_GetCurrentDisplayMode(win->monitor()->oshandle(), &mode); + SDL_GetCurrentDisplayMode(window().monitor()->oshandle(), &mode); m_yuv_bitmap.reset(); - fmt = (sdl_sm->pixel_format ? sdl_sm->pixel_format : mode.format); + fmt = (m_scale_mode.pixel_format ? m_scale_mode.pixel_format : mode.format); - if (sdl_sm->is_scale) + if (m_scale_mode.is_scale) { int m_hw_scale_width = 0; int m_hw_scale_height = 0; - win->target()->compute_minimum_size(m_hw_scale_width, m_hw_scale_height); - if (win->prescale()) + window().target()->compute_minimum_size(m_hw_scale_width, m_hw_scale_height); + if (window().prescale()) { - m_hw_scale_width *= win->prescale(); - m_hw_scale_height *= win->prescale(); + m_hw_scale_width *= window().prescale(); + m_hw_scale_height *= window().prescale(); /* This must be a multiple of 2 */ m_hw_scale_width = (m_hw_scale_width + 1) & ~1; } - if (sdl_sm->is_yuv) + if (m_scale_mode.is_yuv) m_yuv_bitmap = std::make_unique<uint16_t []>(m_hw_scale_width * m_hw_scale_height); - int w = m_hw_scale_width * sdl_sm->mult_w; - int h = m_hw_scale_height * sdl_sm->mult_h; + int w = m_hw_scale_width * m_scale_mode.mult_w; + int h = m_hw_scale_height * m_scale_mode.mult_h; m_texture_id = SDL_CreateTexture(m_sdl_renderer, fmt, SDL_TEXTUREACCESS_STREAMING, w, h); @@ -179,26 +218,23 @@ void renderer_sdl1::show_info(struct SDL_RendererInfo *render_info) int renderer_sdl1::create() { - const sdl_scale_mode *sm = &scale_modes[video_config.scale_mode]; - - auto win = assert_window(); // create renderer /* set hints ... */ - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, sm->sdl_scale_mode_hint); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, m_scale_mode.sdl_scale_mode_hint); if (video_config.waitvsync) - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); else - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_ACCELERATED); if (!m_sdl_renderer) { if (video_config.waitvsync) - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_SOFTWARE); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_SOFTWARE); else - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_SOFTWARE); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_SOFTWARE); } if (!m_sdl_renderer) @@ -213,18 +249,18 @@ int renderer_sdl1::create() // Check scale mode - if (sm->pixel_format) + if (m_scale_mode.pixel_format) { int i; int found = 0; for (i=0; i < render_info.num_texture_formats; i++) - if (sm->pixel_format == render_info.texture_formats[i]) + if (m_scale_mode.pixel_format == render_info.texture_formats[i]) found = 1; if (!found) { - fatalerror("window: Scale mode %s not supported!", sm->name); + fatalerror("window: Scale mode %s not supported!", m_scale_mode.name); } } @@ -285,7 +321,6 @@ void renderer_sdl1::destroy_all_textures() int renderer_sdl1::draw(int update) { - const sdl_scale_mode *sm = &scale_modes[video_config.scale_mode]; uint8_t *surfptr; int32_t pitch; Uint32 rmask, gmask, bmask; @@ -293,14 +328,7 @@ int renderer_sdl1::draw(int update) int32_t vofs, hofs, blitwidth, blitheight, ch, cw; int bpp; - if (video_config.novideo) - { - return 0; - } - - auto win = assert_window(); - - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (has_flags(FI_CHANGED) || (wdim != m_last_dim)) { destroy_all_textures(); @@ -367,15 +395,15 @@ int renderer_sdl1::draw(int update) m_last_hofs = hofs; m_last_vofs = vofs; - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); int mamewidth, mameheight; Uint32 fmt = 0; int access = 0; SDL_QueryTexture(m_texture_id, &fmt, &access, &mamewidth, &mameheight); - mamewidth /= sm->mult_w; - mameheight /= sm->mult_h; + mamewidth /= m_scale_mode.mult_w; + mameheight /= m_scale_mode.mult_h; //printf("w h %d %d %d %d\n", mamewidth, mameheight, blitwidth, blitheight); // rescale bounds @@ -385,7 +413,7 @@ int renderer_sdl1::draw(int update) // FIXME: this could be a lot easier if we get the primlist here! // Bounds would be set fit for purpose and done! - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { prim.bounds.x0 = floor(fw * prim.bounds.x0 + 0.5f); prim.bounds.x1 = floor(fw * prim.bounds.x1 + 0.5f); @@ -394,32 +422,32 @@ int renderer_sdl1::draw(int update) } // render to it - if (!sm->is_yuv) + if (!m_scale_mode.is_yuv) { switch (rmask) { case 0xff000000: - software_renderer<uint32_t, 0,0,0, 24,16,8>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4); + software_renderer<uint32_t, 0,0,0, 24,16,8>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4); break; case 0x0000ff00: - software_renderer<uint32_t, 0,0,0, 8,16,24>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4); + software_renderer<uint32_t, 0,0,0, 8,16,24>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4); break; case 0x00ff0000: - software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4); + software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4); break; case 0x000000ff: - software_renderer<uint32_t, 0,0,0, 0,8,16>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4); + software_renderer<uint32_t, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4); break; case 0xf800: - software_renderer<uint16_t, 3,2,3, 11,5,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 2); + software_renderer<uint16_t, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 2); break; case 0x7c00: - software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 2); + software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 2); break; default: @@ -431,11 +459,11 @@ int renderer_sdl1::draw(int update) { assert (m_yuv_bitmap != nullptr); assert (surfptr != nullptr); - software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*win->m_primlist, m_yuv_bitmap.get(), mamewidth, mameheight, mamewidth); - sm->yuv_blit(m_yuv_bitmap.get(), surfptr, pitch, m_yuv_lookup.get(), mamewidth, mameheight); + software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, m_yuv_bitmap.get(), mamewidth, mameheight, mamewidth); + m_scale_mode.yuv_blit(m_yuv_bitmap.get(), surfptr, pitch, m_yuv_lookup.get(), mamewidth, mameheight); } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); // unlock and flip SDL_UnlockTexture(m_texture_id); @@ -663,16 +691,98 @@ static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pi render_primitive_list *renderer_sdl1::get_primitives() { - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - - osd_dim nd = win->get_size(); + osd_dim nd = window().get_size(); if (nd != m_blit_dim) { m_blit_dim = nd; notify_changed(); } - win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); +} + + +class video_sdl1 : public osd_module, public render_module +{ +public: + video_sdl1() + : osd_module(OSD_RENDERER_PROVIDER, "soft") + , m_scale_mode(-1) + { + } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override { } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE | FLAG_SDL_NEEDS_OPENGL; } + +private: + static int get_scale_mode(char const *modestr); + + int m_scale_mode; + + static sdl_scale_mode const s_scale_modes[]; +}; + +int video_sdl1::init(osd_interface &osd, osd_options const &options) +{ + osd_printf_verbose("Using SDL multi-window soft driver (SDL 2.0+)\n"); + + // yuv settings ... + char const *const modestr = dynamic_cast<sdl_options const &>(options).scale_mode(); + m_scale_mode = get_scale_mode(modestr); + if (m_scale_mode < 0) + { + osd_printf_warning("Invalid yuvmode value %s; reverting to none\n", modestr); + m_scale_mode = 0; + } + + return 0; } + +std::unique_ptr<osd_renderer> video_sdl1::create(osd_window &window) +{ + return std::make_unique<renderer_sdl1>(window, s_scale_modes[m_scale_mode]); +} + +int video_sdl1::get_scale_mode(char const *modestr) +{ + const sdl_scale_mode *sm = s_scale_modes; + int index = 0; + while (sm->name) + { + if (!strcmp(sm->name, modestr)) + return index; + index++; + sm++; + } + return -1; +} + +sdl_scale_mode const video_sdl1::s_scale_modes[] = { + { "none", 0, 0, 1, 1, DRAW2_SCALEMODE_NEAREST, 0, nullptr }, + { "hwblit", 1, 0, 1, 1, DRAW2_SCALEMODE_LINEAR, 0, nullptr }, + { "hwbest", 1, 0, 1, 1, DRAW2_SCALEMODE_BEST, 0, nullptr }, + /* SDL1.2 uses interpolation as well */ + { "yv12", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12 }, + { "yv12x2", 1, 1, 2, 2, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12X2 }, + { "yuy2", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2 }, + { "yuy2x2", 1, 1, 2, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2X2 }, + { nullptr } }; + +} // anonymous namespace + +} // namespace osd + + +#else // defined(OSD_SDL) + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_sdl1, OSD_RENDERER_PROVIDER, "soft") } } + +#endif // defined(OSD_SDL) + + +MODULE_DEFINITION(RENDERER_SDL1, osd::video_sdl1) diff --git a/src/osd/modules/render/drawsdl.h b/src/osd/modules/render/drawsdl.h deleted file mode 100644 index cc07b848c91..00000000000 --- a/src/osd/modules/render/drawsdl.h +++ /dev/null @@ -1,94 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Couriersud, Olivier Galibert, R. Belmont -//============================================================ -// -// drawsdl.h - SDL software and OpenGL implementation -// -// SDLMAME by Olivier Galibert and R. Belmont -// -// yuvmodes by Couriersud -// -//============================================================ - -#ifndef MAME_OSD_MODULES_RENDER_DRAWSDL_H -#define MAME_OSD_MODULES_RENDER_DRAWSDL_H - -#pragma once - -// OSD headers -#include "window.h" - -#include <SDL2/SDL.h> - -#include <memory> - - -/* renderer_sdl1 is the information about SDL for the current screen */ -class renderer_sdl1 : public osd_renderer -{ -public: - - renderer_sdl1(std::shared_ptr<osd_window> w, int extra_flags) - : osd_renderer(w, FLAG_NEEDS_OPENGL | extra_flags) - , m_sdl_renderer(nullptr) - , m_texture_id(nullptr) - , m_yuv_lookup() - , m_yuv_bitmap() - //, m_hw_scale_width(0) - //, m_hw_scale_height(0) - , m_last_hofs(0) - , m_last_vofs(0) - , m_blit_dim(0, 0) - , m_last_dim(0, 0) - { - } - virtual ~renderer_sdl1(); - - static void init(running_machine &machine); - static void exit() { } - - virtual int create() override; - virtual int draw(const int update) override; - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; - virtual render_primitive_list *get_primitives() override; - -private: - void show_info(struct SDL_RendererInfo *render_info); - - void destroy_all_textures(); - void yuv_init(); - void setup_texture(const osd_dim &size); - void yuv_lookup_set(unsigned int pen, unsigned char red, - unsigned char green, unsigned char blue); - - int32_t m_blittimer; - - SDL_Renderer *m_sdl_renderer; - SDL_Texture *m_texture_id; - - // YUV overlay - std::unique_ptr<uint32_t []> m_yuv_lookup; - std::unique_ptr<uint16_t []> m_yuv_bitmap; - - // if we leave scaling to SDL and the underlying driver, this - // is the render_target_width/height to use - - int m_last_hofs; - int m_last_vofs; - osd_dim m_blit_dim; - osd_dim m_last_dim; -}; - -struct sdl_scale_mode -{ - const char *name; - int is_scale; /* Scale mode? */ - int is_yuv; /* Yuv mode? */ - int mult_w; /* Width multiplier */ - int mult_h; /* Height multiplier */ - const char *sdl_scale_mode_hint; /* what to use as a hint ? */ - int pixel_format; /* Pixel/Overlay format */ - void (*yuv_blit)(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height); -}; - -#endif // MAME_OSD_MODULES_RENDER_DRAWSDL_H diff --git a/src/osd/modules/render/render_module.h b/src/osd/modules/render/render_module.h new file mode 100644 index 00000000000..b22f35fdb3c --- /dev/null +++ b/src/osd/modules/render/render_module.h @@ -0,0 +1,38 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +#ifndef MAME_OSD_MODULES_RENDER_RENDER_MODULE_H +#define MAME_OSD_MODULES_RENDER_RENDER_MODULE_H + +#pragma once + +#include "osdepend.h" +#include "modules/osdmodule.h" + +#include <memory> + + +#define OSD_RENDERER_PROVIDER "video" + + +class osd_renderer; +class osd_window; + + +class render_module +{ +public: + virtual ~render_module() = default; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) = 0; + + bool is_interactive() const { return flags() & FLAG_INTERACTIVE; } + bool sdl_needs_opengl() const { return flags() & FLAG_SDL_NEEDS_OPENGL; } + +protected: + static inline constexpr unsigned FLAG_INTERACTIVE = 1; + static inline constexpr unsigned FLAG_SDL_NEEDS_OPENGL = 2; + + virtual unsigned flags() const = 0; +}; + +#endif // MAME_OSD_MODULES_RENDER_RENDER_MODULE_H diff --git a/src/osd/modules/sound/coreaudio_sound.cpp b/src/osd/modules/sound/coreaudio_sound.cpp index 53e2a30d521..408fe9e3991 100644 --- a/src/osd/modules/sound/coreaudio_sound.cpp +++ b/src/osd/modules/sound/coreaudio_sound.cpp @@ -8,10 +8,11 @@ #include "sound_module.h" #include "modules/osdmodule.h" -#include "modules/lib/osdobj_common.h" #ifdef SDLMAME_MACOSX +#include "modules/lib/osdobj_common.h" + #include <AvailabilityMacros.h> #include <AudioToolbox/AudioToolbox.h> #include <AudioUnit/AudioUnit.h> @@ -36,6 +37,8 @@ public: sound_module(), m_graph(nullptr), m_node_count(0), + m_sample_rate(0), + m_audio_latency(0), m_sample_bytes(0), m_headroom(0), m_buffer_size(0), @@ -166,14 +169,16 @@ private: unsigned m_node_count; node_detail m_node_details[EFFECT_COUNT_MAX + 2]; - uint32_t m_sample_bytes; - uint32_t m_headroom; - uint32_t m_buffer_size; + int m_sample_rate; + int m_audio_latency; + uint32_t m_sample_bytes; + uint32_t m_headroom; + uint32_t m_buffer_size; std::unique_ptr<int8_t []> m_buffer; - uint32_t m_playpos; - uint32_t m_writepos; + uint32_t m_playpos; + uint32_t m_writepos; bool m_in_underrun; - int32_t m_scale; + int32_t m_scale; unsigned m_overflows; unsigned m_underflows; }; @@ -184,7 +189,9 @@ int sound_coreaudio::init(osd_interface &osd, const osd_options &options) OSStatus err; // Don't bother with any of this if sound is disabled - if (sample_rate() == 0) + m_sample_rate = options.sample_rate(); + m_audio_latency = options.audio_latency(); + if (m_sample_rate == 0) return 0; // Create the output graph @@ -194,7 +201,7 @@ int sound_coreaudio::init(osd_interface &osd, const osd_options &options) // Set audio stream format for two-channel native-endian 16-bit packed linear PCM AudioStreamBasicDescription format; - format.mSampleRate = sample_rate(); + format.mSampleRate = m_sample_rate; format.mFormatID = kAudioFormatLinearPCM; format.mFormatFlags = kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsSignedInteger @@ -219,8 +226,8 @@ int sound_coreaudio::init(osd_interface &osd, const osd_options &options) m_sample_bytes = format.mBytesPerFrame; // Allocate buffer - m_headroom = m_sample_bytes * (clamped_latency() * sample_rate() / 40); - m_buffer_size = m_sample_bytes * std::max<uint32_t>(sample_rate() * (clamped_latency() + 3) / 40, 256U); + m_headroom = m_sample_bytes * (clamped_latency() * m_sample_rate / 40); + m_buffer_size = m_sample_bytes * std::max<uint32_t>(m_sample_rate * (clamped_latency() + 3) / 40, 256U); try { m_buffer = std::make_unique<int8_t []>(m_buffer_size); @@ -285,7 +292,7 @@ void sound_coreaudio::exit() void sound_coreaudio::update_audio_stream(bool is_throttled, int16_t const *buffer, int samples_this_frame) { - if ((sample_rate() == 0) || !m_buffer) + if ((m_sample_rate == 0) || !m_buffer) return; uint32_t const bytes_this_frame = samples_this_frame * m_sample_bytes; @@ -1010,10 +1017,10 @@ OSStatus sound_coreaudio::render_callback( } // namespace osd -#else /* SDLMAME_MACOSX */ +#else // SDLMAME_MACOSX namespace osd { namespace { MODULE_NOT_SUPPORTED(sound_coreaudio, OSD_SOUND_PROVIDER, "coreaudio") } } -#endif +#endif // SDLMAME_MACOSX MODULE_DEFINITION(SOUND_COREAUDIO, osd::sound_coreaudio) diff --git a/src/osd/modules/sound/direct_sound.cpp b/src/osd/modules/sound/direct_sound.cpp index dd598af94d1..f214215f1d9 100644 --- a/src/osd/modules/sound/direct_sound.cpp +++ b/src/osd/modules/sound/direct_sound.cpp @@ -15,11 +15,11 @@ #include "emuopts.h" // osd headers +#include "modules/lib/osdobj_common.h" #include "osdepend.h" #include "osdcore.h" #ifdef SDLMAME_WIN32 -#include "modules/lib/osdobj_common.h" #include "sdl/window.h" #include <SDL2/SDL_syswm.h> #else @@ -207,10 +207,11 @@ private: class sound_direct_sound : public osd_module, public sound_module { public: - sound_direct_sound() : osd_module(OSD_SOUND_PROVIDER, "dsound"), sound_module(), + m_sample_rate(0), + m_audio_latency(0), m_bytes_per_sample(0), m_primary_buffer(), m_stream_buffer(), @@ -219,7 +220,6 @@ public: m_buffer_overflows(0) { } - virtual ~sound_direct_sound() { } virtual int init(osd_interface &osd, osd_options const &options) override; virtual void exit() override; @@ -237,6 +237,10 @@ private: // DirectSound objects Microsoft::WRL::ComPtr<IDirectSound> m_dsound; + // configuration + int m_sample_rate; + int m_audio_latency; + // descriptors and formats uint32_t m_bytes_per_sample; @@ -257,10 +261,14 @@ private: int sound_direct_sound::init(osd_interface &osd, osd_options const &options) { - // attempt to initialize DirectSound - // don't make it fatal if we can't -- we'll just run without sound - dsound_init(); + m_sample_rate = options.sample_rate(); + m_audio_latency = options.audio_latency(); m_buffer_underflows = m_buffer_overflows = 0; + + // attempt to initialize DirectSound + if (dsound_init() != DS_OK) + return -1; + return 0; } @@ -407,10 +415,14 @@ HRESULT sound_direct_sound::dsound_init() #ifdef SDLMAME_WIN32 SDL_SysWMinfo wminfo; SDL_VERSION(&wminfo.version); - SDL_GetWindowWMInfo(std::dynamic_pointer_cast<sdl_window_info>(osd_common_t::s_window_list.front())->platform_window(), &wminfo); + if (!SDL_GetWindowWMInfo(dynamic_cast<sdl_window_info &>(*osd_common_t::window_list().front()).platform_window(), &wminfo)) + { + result = DSERR_UNSUPPORTED; // just so it has something to return + goto error; + } HWND const window = wminfo.info.win.window; #else // SDLMAME_WIN32 - HWND const window = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(); + HWND const window = dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(); #endif // SDLMAME_WIN32 result = m_dsound->SetCooperativeLevel(window, DSSCL_PRIORITY); } @@ -426,7 +438,7 @@ HRESULT sound_direct_sound::dsound_init() stream_format.wBitsPerSample = 16; stream_format.wFormatTag = WAVE_FORMAT_PCM; stream_format.nChannels = 2; - stream_format.nSamplesPerSec = sample_rate(); + stream_format.nSamplesPerSec = m_sample_rate; stream_format.nBlockAlign = stream_format.wBitsPerSample * stream_format.nChannels / 8; stream_format.nAvgBytesPerSec = stream_format.nSamplesPerSec * stream_format.nBlockAlign; @@ -567,4 +579,5 @@ namespace osd { namespace { MODULE_NOT_SUPPORTED(sound_direct_sound, OSD_SOUND_P #endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) + MODULE_DEFINITION(SOUND_DSOUND, osd::sound_direct_sound) diff --git a/src/osd/modules/sound/js_sound.cpp b/src/osd/modules/sound/js_sound.cpp index e3f61296537..7375d014141 100644 --- a/src/osd/modules/sound/js_sound.cpp +++ b/src/osd/modules/sound/js_sound.cpp @@ -11,7 +11,7 @@ #include "sound_module.h" #include "modules/osdmodule.h" -#if (defined(SDLMAME_EMSCRIPTEN)) +#if defined(SDLMAME_EMSCRIPTEN) #include "emscripten.h" @@ -19,8 +19,7 @@ class sound_js : public osd_module, public sound_module { public: - sound_js() - : osd_module(OSD_SOUND_PROVIDER, "js"), sound_module() + sound_js() : osd_module(OSD_SOUND_PROVIDER, "js"), sound_module() { } virtual ~sound_js() { } @@ -32,23 +31,28 @@ public: virtual void update_audio_stream(bool is_throttled, const int16_t *buffer, int samples_this_frame) { - EM_ASM_ARGS({ - // Forward audio stream update on to JS backend implementation. - jsmame_update_audio_stream($0, $1); - }, (unsigned int)buffer, samples_this_frame); + EM_ASM_ARGS( + { + // Forward audio stream update on to JS backend implementation. + jsmame_update_audio_stream($0, $1); + }, + (unsigned int)buffer, + samples_this_frame); } + virtual void set_mastervolume(int attenuation) { - EM_ASM_ARGS({ - // Forward volume update on to JS backend implementation. - jsmame_set_mastervolume($0); - }, attenuation); + EM_ASM_ARGS( + { + // Forward volume update on to JS backend implementation. + jsmame_set_mastervolume($0); + }, + attenuation); } - }; -#else /* SDLMAME_EMSCRIPTEN */ +#else // SDLMAME_EMSCRIPTEN MODULE_NOT_SUPPORTED(sound_js, OSD_SOUND_PROVIDER, "js") -#endif +#endif // SDLMAME_EMSCRIPTEN MODULE_DEFINITION(SOUND_JS, sound_js) diff --git a/src/osd/modules/sound/pa_sound.cpp b/src/osd/modules/sound/pa_sound.cpp index 8d2b71a03c2..d5bb96a25af 100644 --- a/src/osd/modules/sound/pa_sound.cpp +++ b/src/osd/modules/sound/pa_sound.cpp @@ -157,6 +157,8 @@ private: PaStream* m_pa_stream; PaError err; + int m_sample_rate; + int m_audio_latency; int m_attenuation; audio_buffer<s16>* m_ab; @@ -179,6 +181,10 @@ private: int sound_pa::init(osd_interface &osd, osd_options const &options) { + m_sample_rate = options.sample_rate(); + if (!m_sample_rate) + return 0; + PaStreamParameters stream_params; const PaStreamInfo* stream_info; const PaHostApiInfo* api_info; @@ -187,9 +193,6 @@ int sound_pa::init(osd_interface &osd, osd_options const &options) unsigned long frames_per_callback = paFramesPerBufferUnspecified; double callback_interval; - if (!sample_rate()) - return 0; - m_attenuation = options.volume(); m_underflows = 0; m_overflows = 0; @@ -199,7 +202,7 @@ int sound_pa::init(osd_interface &osd, osd_options const &options) m_skip_threshold_ticks = 0; m_osd_tps = osd_ticks_per_second(); m_buffer_min_ct = INT_MAX; - m_audio_latency = std::clamp<int>(m_audio_latency, LATENCY_MIN, LATENCY_MAX); + m_audio_latency = std::clamp<int>(options.audio_latency(), LATENCY_MIN, LATENCY_MAX); try { m_ab = new audio_buffer<s16>(m_sample_rate, 2); @@ -371,7 +374,7 @@ int sound_pa::callback(s16* output_buffer, size_t number_of_samples) int adjust = m_buffer_min_ct - m_skip_threshold / 2; // if adjustment is less than two milliseconds, don't bother - if (adjust / 2 > sample_rate() / 500) { + if (adjust / 2 > m_sample_rate / 500) { m_ab->increment_playpos(adjust); m_has_overflowed = true; } @@ -398,7 +401,7 @@ int sound_pa::callback(s16* output_buffer, size_t number_of_samples) void sound_pa::update_audio_stream(bool is_throttled, const s16 *buffer, int samples_this_frame) { - if (!sample_rate()) + if (!m_sample_rate) return; #if LOG_BUFCNT @@ -433,7 +436,7 @@ void sound_pa::set_mastervolume(int attenuation) void sound_pa::exit() { - if (!sample_rate()) + if (!m_sample_rate) return; #if LOG_BUFCNT diff --git a/src/osd/modules/sound/pulse_sound.cpp b/src/osd/modules/sound/pulse_sound.cpp index ced2cd66a59..a0b316bee84 100644 --- a/src/osd/modules/sound/pulse_sound.cpp +++ b/src/osd/modules/sound/pulse_sound.cpp @@ -296,24 +296,26 @@ int sound_pulse::init(osd_interface &osd, osd_options const &options) if(res != 'r') return 1; + const int sample_rate = options.sample_rate(); + pa_sample_spec ss; #ifdef LSB_FIRST ss.format = PA_SAMPLE_S16LE; #else ss.format = PA_SAMPLE_S16BE; #endif - ss.rate = sample_rate(); + ss.rate = sample_rate; ss.channels = 2; m_stream = pa_stream_new(m_context, "main output", &ss, nullptr); pa_stream_set_state_callback(m_stream, i_stream_notify, this); pa_stream_set_write_callback(m_stream, i_stream_write_request, this); pa_buffer_attr battr; - battr.fragsize = sample_rate() / 1000; + battr.fragsize = sample_rate / 1000; battr.maxlength = uint32_t(-1); - battr.minreq = sample_rate() / 1000; + battr.minreq = sample_rate / 1000; battr.prebuf = uint32_t(-1); - battr.tlength = sample_rate() / 1000; + battr.tlength = sample_rate / 1000; err = pa_stream_connect_playback(m_stream, nullptr, &battr, PA_STREAM_ADJUST_LATENCY, nullptr, nullptr); if(err) diff --git a/src/osd/modules/sound/sdl_sound.cpp b/src/osd/modules/sound/sdl_sound.cpp index cae544fa016..ba7082312ea 100644 --- a/src/osd/modules/sound/sdl_sound.cpp +++ b/src/osd/modules/sound/sdl_sound.cpp @@ -14,6 +14,7 @@ #if (defined(OSD_SDL) || defined(USE_SDL_SOUND)) +#include "modules/lib/osdobj_common.h" #include "osdcore.h" // standard sdl header @@ -50,10 +51,16 @@ public: sound_sdl() : osd_module(OSD_SOUND_PROVIDER, "sdl"), sound_module(), + sample_rate(0), + sdl_xfer_samples(SDL_XFER_SAMPLES), stream_in_initialized(0), - attenuation(0), buf_locked(0), stream_buffer(nullptr), stream_buffer_size(0), buffer_underflows(0), buffer_overflows(0) + attenuation(0), + buf_locked(0), + stream_buffer(nullptr), + stream_buffer_size(0), + buffer_underflows(0), + buffer_overflows(0) { - sdl_xfer_samples = SDL_XFER_SAMPLES; } virtual ~sound_sdl() { } @@ -91,6 +98,7 @@ private: int sdl_create_buffers(); void sdl_destroy_buffers(); + int sample_rate; int sdl_xfer_samples; int stream_in_initialized; int attenuation; @@ -244,10 +252,9 @@ void sound_sdl::copy_sample_data(bool is_throttled, const int16_t *data, int byt void sound_sdl::update_audio_stream(bool is_throttled, const int16_t *buffer, int samples_this_frame) { // if nothing to do, don't do it - if (sample_rate() == 0 || !stream_buffer) + if (sample_rate == 0 || !stream_buffer) return; - if (!stream_in_initialized) { // Fill in some zeros to prevent an initial buffer underflow @@ -345,7 +352,8 @@ int sound_sdl::init(osd_interface &osd, const osd_options &options) sound_log = std::make_unique<std::ofstream>(SDLMAME_SOUND_LOG); // skip if sound disabled - if (sample_rate() != 0) + sample_rate = options.sample_rate(); + if (sample_rate != 0) { if (SDL_InitSubSystem(SDL_INIT_AUDIO)) { @@ -361,7 +369,7 @@ int sound_sdl::init(osd_interface &osd, const osd_options &options) stream_in_initialized = 0; // set up the audio specs - aspec.freq = sample_rate(); + aspec.freq = sample_rate; aspec.format = AUDIO_S16SYS; // keep endian independent aspec.channels = n_channels; aspec.samples = sdl_xfer_samples; @@ -377,10 +385,10 @@ int sound_sdl::init(osd_interface &osd, const osd_options &options) sdl_xfer_samples = obtained.samples; // pin audio latency - audio_latency = std::clamp(m_audio_latency, 1, MAX_AUDIO_LATENCY); + audio_latency = std::clamp(options.audio_latency(), 1, MAX_AUDIO_LATENCY); // compute the buffer sizes - stream_buffer_size = (sample_rate() * 2 * sizeof(int16_t) * (2 + audio_latency)) / 30; + stream_buffer_size = (sample_rate * 2 * sizeof(int16_t) * (2 + audio_latency)) / 30; stream_buffer_size = (stream_buffer_size / 1024) * 1024; if (stream_buffer_size < 1024) stream_buffer_size = 1024; @@ -414,7 +422,7 @@ int sound_sdl::init(osd_interface &osd, const osd_options &options) void sound_sdl::exit() { // if nothing to do, don't do it - if (sample_rate() == 0) + if (sample_rate == 0) return; osd_printf_verbose("sdl_kill: closing audio\n"); diff --git a/src/osd/modules/sound/sound_module.h b/src/osd/modules/sound/sound_module.h index d741c732622..088da5ea8d0 100644 --- a/src/osd/modules/sound/sound_module.h +++ b/src/osd/modules/sound/sound_module.h @@ -20,18 +20,10 @@ class sound_module { public: - sound_module() : m_sample_rate(0), m_audio_latency(1) { } - virtual ~sound_module() = default; virtual void update_audio_stream(bool is_throttled, const int16_t *buffer, int samples_this_frame) = 0; virtual void set_mastervolume(int attenuation) = 0; - - int sample_rate() const { return m_sample_rate; } - - // FIXME: these should be set by the implementation on initialisation, not by the OSD object - int m_sample_rate; - int m_audio_latency; }; #endif // MAME_OSD_SOUND_SOUND_MODULE_H diff --git a/src/osd/modules/sound/xaudio2_sound.cpp b/src/osd/modules/sound/xaudio2_sound.cpp index 97803b58e4e..e2d4b2ab1c3 100644 --- a/src/osd/modules/sound/xaudio2_sound.cpp +++ b/src/osd/modules/sound/xaudio2_sound.cpp @@ -10,14 +10,14 @@ #include "modules/osdmodule.h" -#if defined(OSD_WINDOWS) - -// MAME headers -#include "winutil.h" +#if defined(OSD_WINDOWS) | defined(SDLMAME_WIN32) +// OSD headers #include "modules/lib/osdlib.h" +#include "modules/lib/osdobj_common.h" #include "osdcore.h" #include "osdepend.h" +#include "windows/winutil.h" // stdlib includes #include <algorithm> @@ -34,8 +34,6 @@ // XAudio2 include #include <xaudio2.h> -#undef interface - namespace osd { @@ -186,29 +184,6 @@ public: // The main class for the XAudio2 sound module implementation class sound_xaudio2 : public osd_module, public sound_module, public IXAudio2VoiceCallback { -private: - Microsoft::WRL::ComPtr<IXAudio2> m_xAudio2; - mastering_voice_ptr m_masterVoice; - src_voice_ptr m_sourceVoice; - DWORD m_sample_bytes; - std::unique_ptr<BYTE[]> m_buffer; - DWORD m_buffer_size; - DWORD m_buffer_count; - DWORD m_writepos; - std::mutex m_buffer_lock; - HANDLE m_hEventBufferCompleted; - HANDLE m_hEventDataAvailable; - HANDLE m_hEventExiting; - std::thread m_audioThread; - std::queue<xaudio2_buffer> m_queue; - std::unique_ptr<bufferpool> m_buffer_pool; - uint32_t m_overflows; - uint32_t m_underflows; - BOOL m_in_underflow; - BOOL m_initialized; - OSD_DYNAMIC_API(xaudio2, "XAudio2_9.dll", "XAudio2_8.dll"); - OSD_DYNAMIC_API_FN(xaudio2, HRESULT, WINAPI, XAudio2Create, IXAudio2 **, uint32_t, XAUDIO2_PROCESSOR); - public: sound_xaudio2() : osd_module(OSD_SOUND_PROVIDER, "xaudio2"), @@ -216,6 +191,8 @@ public: m_xAudio2(nullptr), m_masterVoice(nullptr), m_sourceVoice(nullptr), + m_sample_rate(0), + m_audio_latency(0), m_sample_bytes(0), m_buffer(nullptr), m_buffer_size(0), @@ -232,8 +209,6 @@ public: { } - virtual ~sound_xaudio2() { } - bool probe() override; int init(osd_interface &osd, osd_options const &options) override; void exit() override; @@ -242,6 +217,7 @@ public: void update_audio_stream(bool is_throttled, int16_t const *buffer, int samples_this_frame) override; void set_mastervolume(int attenuation) override; +private: // Xaudio callbacks void STDAPICALLTYPE OnVoiceProcessingPassStart(uint32_t bytes_required) override; void STDAPICALLTYPE OnVoiceProcessingPassEnd() override {} @@ -251,7 +227,6 @@ public: void STDAPICALLTYPE OnVoiceError(void* pBufferContext, HRESULT error) override {} void STDAPICALLTYPE OnBufferEnd(void *pBufferContext) override; -private: void create_buffers(const WAVEFORMATEX &format); HRESULT create_voices(const WAVEFORMATEX &format); void process_audio(); @@ -259,6 +234,31 @@ private: void submit_needed(); void roll_buffer(); BOOL submit_next_queued(); + + Microsoft::WRL::ComPtr<IXAudio2> m_xAudio2; + mastering_voice_ptr m_masterVoice; + src_voice_ptr m_sourceVoice; + int m_sample_rate; + int m_audio_latency; + DWORD m_sample_bytes; + std::unique_ptr<BYTE[]> m_buffer; + DWORD m_buffer_size; + DWORD m_buffer_count; + DWORD m_writepos; + std::mutex m_buffer_lock; + HANDLE m_hEventBufferCompleted; + HANDLE m_hEventDataAvailable; + HANDLE m_hEventExiting; + std::thread m_audioThread; + std::queue<xaudio2_buffer> m_queue; + std::unique_ptr<bufferpool> m_buffer_pool; + uint32_t m_overflows; + uint32_t m_underflows; + BOOL m_in_underflow; + BOOL m_initialized; + + OSD_DYNAMIC_API(xaudio2, "XAudio2_9.dll", "XAudio2_8.dll"); + OSD_DYNAMIC_API_FN(xaudio2, HRESULT, WINAPI, XAudio2Create, IXAudio2 **, uint32_t, XAUDIO2_PROCESSOR); }; //============================================================ @@ -276,12 +276,7 @@ bool sound_xaudio2::probe() int sound_xaudio2::init(osd_interface &osd, osd_options const &options) { - HRESULT result; - WAVEFORMATEX format = {0}; - auto init_start = std::chrono::system_clock::now(); - std::chrono::milliseconds init_time; - - CoInitializeEx(nullptr, COINIT_MULTITHREADED); + auto const init_start = std::chrono::system_clock::now(); // Make sure our XAudio2Create entrypoint is bound if (!OSD_DYNAMIC_API_TEST(XAudio2Create)) @@ -290,6 +285,15 @@ int sound_xaudio2::init(osd_interface &osd, osd_options const &options) return 1; } + HRESULT result; + std::chrono::milliseconds init_time; + WAVEFORMATEX format = { 0 }; + + m_sample_rate = options.sample_rate(); + m_audio_latency = options.audio_latency(); + + CoInitializeEx(nullptr, COINIT_MULTITHREADED); + // Create the IXAudio2 object HR_GOERR(OSD_DYNAMIC_CALL(XAudio2Create, m_xAudio2.GetAddressOf(), 0, XAUDIO2_DEFAULT_PROCESSOR)); @@ -297,7 +301,7 @@ int sound_xaudio2::init(osd_interface &osd, osd_options const &options) format.wBitsPerSample = 16; format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 2; - format.nSamplesPerSec = sample_rate(); + format.nSamplesPerSec = m_sample_rate; format.nBlockAlign = format.wBitsPerSample * format.nChannels / 8; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; @@ -316,10 +320,10 @@ int sound_xaudio2::init(osd_interface &osd, osd_options const &options) HR_GOERR(m_sourceVoice->Start()); // Start the thread listening - m_audioThread = std::thread([](sound_xaudio2* self) { self->process_audio(); }, this); + m_audioThread = std::thread([] (sound_xaudio2 *self) { self->process_audio(); }, this); init_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - init_start); - osd_printf_verbose("Sound: XAudio2 initialized. %d ms.\n", static_cast<int>(init_time.count())); + osd_printf_verbose("Sound: XAudio2 initialized. %d ms.\n", init_time.count()); m_initialized = TRUE; return 0; @@ -382,7 +386,7 @@ void sound_xaudio2::update_audio_stream( int16_t const *buffer, int samples_this_frame) { - if (!m_initialized || sample_rate() == 0 || !m_buffer) + if (!m_initialized || m_sample_rate == 0 || !m_buffer) return; uint32_t const bytes_this_frame = samples_this_frame * m_sample_bytes; @@ -533,7 +537,7 @@ HRESULT sound_xaudio2::create_voices(const WAVEFORMATEX &format) m_xAudio2->CreateMasteringVoice( &temp_master_voice, format.nChannels, - sample_rate())); + m_sample_rate)); m_masterVoice = mastering_voice_ptr(temp_master_voice); diff --git a/src/osd/sdl/osdsdl.cpp b/src/osd/sdl/osdsdl.cpp index 7af11bf2d04..633abff3a3d 100644 --- a/src/osd/sdl/osdsdl.cpp +++ b/src/osd/sdl/osdsdl.cpp @@ -134,23 +134,22 @@ void osd_sdl_info() } -std::shared_ptr<sdl_window_info> window_from_id(Uint32 id) +sdl_window_info *window_from_id(Uint32 id) { SDL_Window const *const sdl_window = SDL_GetWindowFromID(id); - auto &windows = osd_common_t::s_window_list; auto const window = std::find_if( - windows.begin(), - windows.end(), - [sdl_window] (std::shared_ptr<osd_window> w) + osd_common_t::window_list().begin(), + osd_common_t::window_list().end(), + [sdl_window] (std::unique_ptr<osd_window> const &w) { - return std::static_pointer_cast<sdl_window_info>(w)->platform_window() == sdl_window; + return dynamic_cast<sdl_window_info &>(*w).platform_window() == sdl_window; }); - if (window == windows.end()) + if (window == osd_common_t::window_list().end()) return nullptr; - return std::static_pointer_cast<sdl_window_info>(*window); + return &static_cast<sdl_window_info &>(**window); } } // anonymous namespace @@ -164,7 +163,7 @@ std::shared_ptr<sdl_window_info> window_from_id(Uint32 id) sdl_osd_interface::sdl_osd_interface(sdl_options &options) : osd_common_t(options), m_options(options), - m_focus_window(), + m_focus_window(nullptr), m_mouse_over_window(0), m_modifier_keys(0), m_last_click_time(std::chrono::steady_clock::time_point::min()), @@ -422,18 +421,6 @@ void sdl_osd_interface::customize_input_type_list(std::vector<input_type_entry> } -void sdl_osd_interface::video_register() -{ - video_options_add("soft", nullptr); - video_options_add("accel", nullptr); -#if USE_OPENGL - video_options_add("opengl", nullptr); -#endif - video_options_add("bgfx", nullptr); - //video_options_add("auto", nullptr); // making d3d video default one -} - - void sdl_osd_interface::poll_inputs() { m_keyboard_input->poll_if_necessary(); @@ -501,21 +488,21 @@ void sdl_osd_interface::process_events() if (event.key.keysym.sym < 0x20) { // push control characters - they don't arrive as text input events - machine().ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), event.key.keysym.sym); + machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), event.key.keysym.sym); } else if (m_modifier_keys & MODIFIER_KEY_CTRL) { // SDL filters out control characters for text input, so they are decoded here if (event.key.keysym.sym >= 0x40 && event.key.keysym.sym < 0x7f) { - machine().ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), event.key.keysym.sym & 0x1f); + machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), event.key.keysym.sym & 0x1f); } else if (m_modifier_keys & MODIFIER_KEY_SHIFT) { if (event.key.keysym.sym == SDLK_6) // Ctrl-^ (RS) - machine().ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), 0x1e); + machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), 0x1e); else if (event.key.keysym.sym == SDLK_MINUS) // Ctrl-_ (US) - machine().ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), 0x1f); + machine().ui_input().push_char_event(osd_common_t::window_list().front()->target(), 0x1f); } } break; @@ -688,7 +675,7 @@ void sdl_osd_interface::process_textinput_event(SDL_Event const &event) if (*event.text.text) { auto const window = focus_window(event.text); - //printf("Focus window is %p - wl %p\n", window, osd_common_t::s_window_list); + //printf("Focus window is %p - wl %p\n", window, osd_common_t::window_list().front().get()); if (window != nullptr) { auto ptr = event.text.text; @@ -716,11 +703,11 @@ void sdl_osd_interface::check_osd_inputs() // check for toggling fullscreen mode if (machine().ui_input().pressed(IPT_OSD_1)) { - for (auto curwin : osd_common_t::s_window_list) - std::static_pointer_cast<sdl_window_info>(curwin)->toggle_full_screen(); + for (auto const &curwin : osd_common_t::window_list()) + dynamic_cast<sdl_window_info &>(*curwin).toggle_full_screen(); } - auto window = osd_common_t::s_window_list.front(); + auto const &window = osd_common_t::window_list().front(); if (USE_OPENGL) { @@ -733,10 +720,10 @@ void sdl_osd_interface::check_osd_inputs() } if (machine().ui_input().pressed(IPT_OSD_6)) - std::static_pointer_cast<sdl_window_info>(window)->modify_prescale(-1); + dynamic_cast<sdl_window_info &>(*window).modify_prescale(-1); if (machine().ui_input().pressed(IPT_OSD_7)) - std::static_pointer_cast<sdl_window_info>(window)->modify_prescale(1); + dynamic_cast<sdl_window_info &>(*window).modify_prescale(1); if (machine().ui_input().pressed(IPT_OSD_8)) window->renderer().record(); @@ -748,7 +735,7 @@ sdl_window_info *sdl_osd_interface::focus_window(T const &event) const { // FIXME: SDL does not properly report the window for certain OS. if (false) - return window_from_id(event.windowID).get(); + return window_from_id(event.windowID); else - return m_focus_window.get(); + return m_focus_window; } diff --git a/src/osd/sdl/osdsdl.h b/src/osd/sdl/osdsdl.h index 61b4d3faf03..80499f96236 100644 --- a/src/osd/sdl/osdsdl.h +++ b/src/osd/sdl/osdsdl.h @@ -150,8 +150,6 @@ public: // input overridables virtual void customize_input_type_list(std::vector<input_type_entry> &typelist) override; - virtual void video_register() override; - virtual bool video_init() override; virtual bool window_init() override; @@ -199,7 +197,7 @@ private: template <typename T> sdl_window_info *focus_window(T const &event) const; sdl_options &m_options; - std::shared_ptr<sdl_window_info> m_focus_window; + sdl_window_info *m_focus_window; int m_mouse_over_window; uint8_t m_modifier_keys; diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp index fb0384e3f81..7c549b16dc5 100644 --- a/src/osd/sdl/video.cpp +++ b/src/osd/sdl/video.cpp @@ -14,6 +14,7 @@ #include "osdsdl.h" #include "modules/lib/osdlib.h" #include "modules/monitor/monitor_module.h" +#include "modules/render/render_module.h" // MAME headers #include "emu.h" @@ -65,12 +66,16 @@ bool sdl_osd_interface::video_init() get_resolution(options().resolution(), options().resolution(index), &conf, true); // create window ... - std::shared_ptr<sdl_window_info> win = std::make_shared<sdl_window_info>(machine(), index, m_monitor_module->pick_monitor(reinterpret_cast<osd_options &>(options()), index), &conf); - + auto win = std::make_unique<sdl_window_info>(machine(), *m_render, index, m_monitor_module->pick_monitor(reinterpret_cast<osd_options &>(options()), index), &conf); if (win->window_init()) return false; + + s_window_list.emplace_back(std::move(win)); } + if (m_render->is_interactive()) + SDL_RaiseWindow(dynamic_cast<sdl_window_info &>(*osd_common_t::s_window_list.front()).platform_window()); + return true; } @@ -95,7 +100,7 @@ void sdl_osd_interface::update(bool skip_redraw) if (!skip_redraw) { // profiler_mark(PROFILER_BLIT); - for (auto window : osd_common_t::s_window_list) + for (auto const &window : osd_common_t::window_list()) window->update(); // profiler_mark(PROFILER_END); } @@ -111,8 +116,6 @@ void sdl_osd_interface::update(bool skip_redraw) void sdl_osd_interface::extract_video_config() { - const char *stemp; - video_config.perftest = options().video_fps(); // global options: extract the data @@ -128,47 +131,6 @@ void sdl_osd_interface::extract_video_config() if (machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) video_config.windowed = true; - // default to working video please - video_config.novideo = 0; - - // video options: extract the data - stemp = options().video(); - if (strcmp(stemp, "auto") == 0) - { -#if (defined SDLMAME_EMSCRIPTEN) - stemp = "soft"; -#else - stemp = "bgfx"; -#endif - } - if (strcmp(stemp, SDLOPTVAL_SOFT) == 0) - video_config.mode = VIDEO_MODE_SOFT; - else if (strcmp(stemp, OSDOPTVAL_NONE) == 0) - { - video_config.mode = VIDEO_MODE_SOFT; - video_config.novideo = 1; - - if (!emulator_info::standalone() && options().seconds_to_run() == 0) - osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n"); - } -#if (USE_OPENGL) - else if (strcmp(stemp, SDLOPTVAL_OPENGL) == 0) - video_config.mode = VIDEO_MODE_OPENGL; -#endif - else if ((strcmp(stemp, SDLOPTVAL_SDL2ACCEL) == 0)) - { - video_config.mode = VIDEO_MODE_SDL2ACCEL; - } - else if (strcmp(stemp, SDLOPTVAL_BGFX) == 0) - { - video_config.mode = VIDEO_MODE_BGFX; - } - else - { - osd_printf_warning("Invalid video value %s; reverting to software\n", stemp); - video_config.mode = VIDEO_MODE_SOFT; - } - video_config.switchres = options().switch_res(); video_config.centerh = options().centerh(); video_config.centerv = options().centerv(); @@ -185,64 +147,7 @@ void sdl_osd_interface::extract_video_config() osd_printf_warning("Invalid prescale option, reverting to '1'\n"); video_config.prescale = 1; } - #if (USE_OPENGL) - // default to working video please - video_config.forcepow2texture = options().gl_force_pow2_texture(); - video_config.allowtexturerect = !(options().gl_no_texture_rect()); - video_config.vbo = options().gl_vbo(); - video_config.pbo = options().gl_pbo(); - video_config.glsl = options().gl_glsl(); - if ( video_config.glsl ) - { - int i; - - video_config.glsl_filter = options().glsl_filter(); - - video_config.glsl_shader_mamebm_num=0; - - for(i=0; i<GLSL_SHADER_MAX; i++) - { - stemp = options().shader_mame(i); - if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0) - { - video_config.glsl_shader_mamebm[i] = (char *) malloc(strlen(stemp)+1); - strcpy(video_config.glsl_shader_mamebm[i], stemp); - video_config.glsl_shader_mamebm_num++; - } else { - video_config.glsl_shader_mamebm[i] = nullptr; - } - } - - video_config.glsl_shader_scrn_num=0; - - for(i=0; i<GLSL_SHADER_MAX; i++) - { - stemp = options().shader_screen(i); - if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0) - { - video_config.glsl_shader_scrn[i] = (char *) malloc(strlen(stemp)+1); - strcpy(video_config.glsl_shader_scrn[i], stemp); - video_config.glsl_shader_scrn_num++; - } else { - video_config.glsl_shader_scrn[i] = nullptr; - } - } - } else { - int i; - video_config.glsl_filter = 0; - video_config.glsl_shader_mamebm_num=0; - for(i=0; i<GLSL_SHADER_MAX; i++) - { - video_config.glsl_shader_mamebm[i] = nullptr; - } - video_config.glsl_shader_scrn_num=0; - for(i=0; i<GLSL_SHADER_MAX; i++) - { - video_config.glsl_shader_scrn[i] = nullptr; - } - } - - #endif /* USE_OPENGL */ + // misc options: sanity check values // global options: sanity check values @@ -251,19 +156,6 @@ void sdl_osd_interface::extract_video_config() osd_printf_warning("Invalid numscreens value %d; reverting to 1\n", video_config.numscreens); video_config.numscreens = 1; } - // yuv settings ... - stemp = options().scale_mode(); - video_config.scale_mode = drawsdl_scale_mode(stemp); - if (video_config.scale_mode < 0) - { - osd_printf_warning("Invalid yuvmode value %s; reverting to none\n", stemp); - video_config.scale_mode = VIDEO_SCALE_MODE_NONE; - } - if ( (video_config.mode != VIDEO_MODE_SOFT) && (video_config.scale_mode != VIDEO_SCALE_MODE_NONE) ) - { - osd_printf_warning("scalemode is only for -video soft, overriding\n"); - video_config.scale_mode = VIDEO_SCALE_MODE_NONE; - } } diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp index 08dfb5cddfc..dc7f3f2ad32 100644 --- a/src/osd/sdl/window.cpp +++ b/src/osd/sdl/window.cpp @@ -18,13 +18,7 @@ // OSD headers #include "window.h" #include "osdsdl.h" -#include "modules/render/drawbgfx.h" -#include "modules/render/drawsdl.h" -#include "modules/render/draw13.h" #include "modules/monitor/monitor_common.h" -#if (USE_OPENGL) -#include "modules/render/drawogl.h" -#endif // standard SDL headers #include <SDL2/SDL.h> @@ -83,60 +77,10 @@ bool sdl_osd_interface::window_init() { osd_printf_verbose("Enter sdlwindow_init\n"); - // 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 - }; - - 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; -#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()); - 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. - */ - const char * hints[] = { SDL_HINT_FRAMEBUFFER_ACCELERATION, + // We may want to set a number of the hints SDL2 provides. + // The code below will document which hints were set. + char const *const hints[] = { + SDL_HINT_FRAMEBUFFER_ACCELERATION, SDL_HINT_RENDER_DRIVER, SDL_HINT_RENDER_OPENGL_SHADERS, SDL_HINT_RENDER_SCALE_QUALITY, SDL_HINT_RENDER_VSYNC, @@ -158,14 +102,13 @@ bool sdl_osd_interface::window_init() SDL_HINT_WINRT_PRIVACY_POLICY_URL, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL, SDL_HINT_WINRT_HANDLE_BACK_BUTTON, #endif - nullptr - }; + }; osd_printf_verbose("\nHints:\n"); - for (int i = 0; hints[i] != nullptr; i++) + for (auto const hintname : hints) { - char const *const hint(SDL_GetHint(hints[i])); - osd_printf_verbose("\t%-40s %s\n", hints[i], hint ? hint : "(NULL)"); + char const *const hintvalue(SDL_GetHint(hintname)); + osd_printf_verbose("\t%-40s %s\n", hintname, hintvalue ? hintvalue : "(NULL)"); } // set up the window list @@ -176,7 +119,7 @@ bool sdl_osd_interface::window_init() void sdl_osd_interface::update_slider_list() { - for (auto window : osd_common_t::s_window_list) + for (auto const &window : osd_common_t::window_list()) { // check if any window has dirty sliders if (window->renderer().sliders_dirty()) @@ -191,7 +134,7 @@ void sdl_osd_interface::build_slider_list() { m_sliders.clear(); - for (auto window : osd_common_t::s_window_list) + for (auto const &window : osd_common_t::window_list()) { std::vector<ui::menu_item> window_sliders = window->renderer().get_slider_list(); m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end()); @@ -208,33 +151,14 @@ void sdl_osd_interface::window_exit() osd_printf_verbose("Enter sdlwindow_exit\n"); // free all the windows + m_focus_window = nullptr; while (!osd_common_t::s_window_list.empty()) { - auto window = osd_common_t::s_window_list.front(); - - // Part of destroy removes the window from the list + auto window = std::move(osd_common_t::s_window_list.back()); + s_window_list.pop_back(); window->destroy(); } - switch (video_config.mode) - { - case VIDEO_MODE_SDL2ACCEL: - renderer_sdl1::exit(); - break; - case VIDEO_MODE_SOFT: - renderer_sdl1::exit(); - break; - case VIDEO_MODE_BGFX: - renderer_bgfx::exit(); - break; -#if (USE_OPENGL) - case VIDEO_MODE_OPENGL: - renderer_ogl::exit(); - break; -#endif - default: - break; - } osd_printf_verbose("Leave sdlwindow_exit\n"); } @@ -336,11 +260,8 @@ void sdl_window_info::toggle_full_screen() } SDL_DestroyWindow(platform_window()); set_platform_window(nullptr); - downcast<sdl_osd_interface &>(machine().osd()).release_keys(); - set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this())); - // toggle the window mode set_fullscreen(!fullscreen()); @@ -368,8 +289,8 @@ void sdl_window_info::modify_prescale(int dir) } else { - notify_changed(); m_prescale = new_prescale; + notify_changed(); } machine().ui().popup_time(1, "Prescale %d", prescale()); } @@ -432,8 +353,6 @@ int sdl_window_info::window_init() create_target(); - set_renderer(osd_renderer::make_for_type(video_config.mode, static_cast<osd_window*>(this)->shared_from_this())); - int result = complete_create(); // handle error conditions @@ -465,8 +384,9 @@ void sdl_window_info::complete_destroy() SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN); // Try to set mode } + renderer_reset(); SDL_DestroyWindow(platform_window()); - // release all keys ... + set_platform_window(nullptr); downcast<sdl_osd_interface &>(machine().osd()).release_keys(); } @@ -666,13 +586,15 @@ int sdl_window_info::complete_create() * */ osd_printf_verbose("Enter sdl_info::create\n"); - if (renderer().has_flags(osd_renderer::FLAG_NEEDS_OPENGL) && !video_config.novideo) + if (renderer_sdl_needs_opengl()) { SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); m_extra_flags = SDL_WINDOW_OPENGL; } else + { m_extra_flags = 0; + } // We need to workaround an issue in SDL 2.0.4 for OS X where setting the // relative mode on the mouse in fullscreen mode makes mouse events stop @@ -771,7 +693,7 @@ int sdl_window_info::complete_create() if (sdlwindow == nullptr ) { - if (renderer().has_flags(osd_renderer::FLAG_NEEDS_OPENGL)) + if (renderer_sdl_needs_opengl()) osd_printf_error("OpenGL not supported on this driver: %s\n", SDL_GetError()); else osd_printf_error("Window creation failed: %s\n", SDL_GetError()); @@ -779,6 +701,7 @@ int sdl_window_info::complete_create() } set_platform_window(sdlwindow); + renderer_create(); if (fullscreen() && video_config.switchres) { @@ -817,24 +740,6 @@ int sdl_window_info::complete_create() SDL_SetWindowGrab(platform_window(), SDL_TRUE); #endif - // set main window - if (index() > 0) - { - for (auto w : osd_common_t::s_window_list) - { - if (w->index() == 0) - { - set_main_window(std::dynamic_pointer_cast<osd_window>(w)); - break; - } - } - } - else - { - // We must be the main window - set_main_window(shared_from_this()); - } - // update monitor resolution after mode change to ensure proper pixel aspect monitor()->refresh(); if (fullscreen() && video_config.switchres) @@ -1146,10 +1051,11 @@ osd_dim sdl_window_info::get_max_bounds(int constrain) sdl_window_info::sdl_window_info( running_machine &a_machine, + render_module &renderprovider, int index, - std::shared_ptr<osd_monitor_info> a_monitor, + const std::shared_ptr<osd_monitor_info> &a_monitor, const osd_window_config *config) - : osd_window_t(a_machine, index, std::move(a_monitor), *config) + : osd_window_t(a_machine, renderprovider, index, std::move(a_monitor), *config) , m_startmaximized(0) // Following three are used by input code to defer resizes , m_minimum_dim(0, 0) diff --git a/src/osd/sdl/window.h b/src/osd/sdl/window.h index f2e2905606f..77477176b51 100644 --- a/src/osd/sdl/window.h +++ b/src/osd/sdl/window.h @@ -37,7 +37,11 @@ typedef uintptr_t HashT; class sdl_window_info : public osd_window_t<SDL_Window*> { public: - sdl_window_info(running_machine &a_machine, int index, std::shared_ptr<osd_monitor_info> a_monitor, + sdl_window_info( + running_machine &a_machine, + render_module &renderprovider, + int index, + const std::shared_ptr<osd_monitor_info> &a_monitor, const osd_window_config *config); ~sdl_window_info(); @@ -98,37 +102,4 @@ private: }; -struct osd_draw_callbacks -{ - osd_renderer *(*create)(osd_window *window); -}; - -//============================================================ -// PROTOTYPES -//============================================================ - -//============================================================ -// PROTOTYPES - drawsdl.c -//============================================================ - -int drawsdl_scale_mode(const char *s); - -//============================================================ -// PROTOTYPES - drawogl.c -//============================================================ - -int drawogl_init(running_machine &machine, osd_draw_callbacks *callbacks); - -//============================================================ -// PROTOTYPES - draw13.c -//============================================================ - -int drawsdl2_init(running_machine &machine, osd_draw_callbacks *callbacks); - -//============================================================ -// PROTOTYPES - drawbgfx.c -//============================================================ - -int drawbgfx_init(running_machine &machine, osd_draw_callbacks *callbacks); - #endif // MAME_OSD_SDL_WINDOW_H diff --git a/src/osd/windows/video.cpp b/src/osd/windows/video.cpp index e5ed5b99e3d..d40da254ffe 100644 --- a/src/osd/windows/video.cpp +++ b/src/osd/windows/video.cpp @@ -6,8 +6,9 @@ // //============================================================ -#include "modules/monitor/monitor_module.h" #include "modules/osdwindow.h" +#include "modules/monitor/monitor_module.h" +#include "modules/render/render_module.h" // MAME headers #include "emu.h" @@ -62,11 +63,17 @@ bool windows_osd_interface::video_init() auto &options = downcast<windows_options &>(machine().options()); for (int index = 0; index < video_config.numscreens; index++) { - win_window_info::create(machine(), index, m_monitor_module->pick_monitor(options, index), &windows[index]); + auto window = win_window_info::create( + machine(), + *m_render, + index, + m_monitor_module->pick_monitor(options, index), + &windows[index]); + s_window_list.emplace_back(std::move(window)); } - if (video_config.mode != VIDEO_MODE_NONE) - SetForegroundWindow(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window()); + if (m_render->is_interactive()) + SetForegroundWindow(dynamic_cast<win_window_info &>(*osd_common_t::s_window_list.front()).platform_window()); return true; } @@ -146,8 +153,6 @@ void windows_osd_interface::check_osd_inputs() void windows_osd_interface::extract_video_config() { - const char *stemp; - // global options: extract the data video_config.windowed = options().window(); video_config.prescale = options().prescale(); @@ -165,31 +170,6 @@ void windows_osd_interface::extract_video_config() get_resolution(default_resolution, options().resolution(2), &windows[2], TRUE); get_resolution(default_resolution, options().resolution(3), &windows[3], TRUE); - // video options: extract the data - stemp = options().video(); - if (strcmp(stemp, "d3d") == 0) - video_config.mode = VIDEO_MODE_D3D; - else if (strcmp(stemp, "auto") == 0) - video_config.mode = VIDEO_MODE_D3D; - else if (strcmp(stemp, "gdi") == 0) - video_config.mode = VIDEO_MODE_GDI; - else if (strcmp(stemp, "bgfx") == 0) - video_config.mode = VIDEO_MODE_BGFX; - else if (strcmp(stemp, "none") == 0) - { - video_config.mode = VIDEO_MODE_NONE; - if (!emulator_info::standalone() && options().seconds_to_run() == 0) - osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n"); - } -#if (USE_OPENGL) - else if (strcmp(stemp, "opengl") == 0) - video_config.mode = VIDEO_MODE_OPENGL; -#endif - else - { - osd_printf_warning("Invalid video value %s; reverting to gdi\n", stemp); - video_config.mode = VIDEO_MODE_GDI; - } video_config.waitvsync = options().wait_vsync(); video_config.syncrefresh = options().sync_refresh(); video_config.triplebuf = options().triple_buffer(); @@ -200,65 +180,6 @@ void windows_osd_interface::extract_video_config() osd_printf_warning("Invalid prescale option, reverting to '1'\n"); video_config.prescale = 1; } - #if (USE_OPENGL) - // default to working video please - video_config.forcepow2texture = options().gl_force_pow2_texture(); - video_config.allowtexturerect = !(options().gl_no_texture_rect()); - video_config.vbo = options().gl_vbo(); - video_config.pbo = options().gl_pbo(); - video_config.glsl = options().gl_glsl(); - if ( video_config.glsl ) - { - int i; - - video_config.glsl_filter = options().glsl_filter(); - - video_config.glsl_shader_mamebm_num=0; - - for(i=0; i<GLSL_SHADER_MAX; i++) - { - stemp = options().shader_mame(i); - if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0) - { - video_config.glsl_shader_mamebm[i] = (char *) malloc(strlen(stemp)+1); - strcpy(video_config.glsl_shader_mamebm[i], stemp); - video_config.glsl_shader_mamebm_num++; - } else { - video_config.glsl_shader_mamebm[i] = nullptr; - } - } - - video_config.glsl_shader_scrn_num=0; - - for(i=0; i<GLSL_SHADER_MAX; i++) - { - stemp = options().shader_screen(i); - if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0) - { - video_config.glsl_shader_scrn[i] = (char *) malloc(strlen(stemp)+1); - strcpy(video_config.glsl_shader_scrn[i], stemp); - video_config.glsl_shader_scrn_num++; - } else { - video_config.glsl_shader_scrn[i] = nullptr; - } - } - } else { - int i; - video_config.glsl_filter = 0; - video_config.glsl_shader_mamebm_num=0; - for(i=0; i<GLSL_SHADER_MAX; i++) - { - video_config.glsl_shader_mamebm[i] = nullptr; - } - video_config.glsl_shader_scrn_num=0; - for(i=0; i<GLSL_SHADER_MAX; i++) - { - video_config.glsl_shader_scrn[i] = nullptr; - } - } - - #endif /* USE_OPENGL */ - } diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp index b0ab9f2eef0..a8a5b222c37 100644 --- a/src/osd/windows/window.cpp +++ b/src/osd/windows/window.cpp @@ -31,14 +31,6 @@ #include "modules/monitor/monitor_common.h" -#include "modules/render/drawbgfx.h" -#include "modules/render/drawnone.h" -#include "modules/render/drawd3d.h" -#include "modules/render/drawgdi.h" -#if (USE_OPENGL) -#include "modules/render/drawogl.h" -#endif - #define NOT_ALREADY_DOWN(x) (x & 0x40000000) == 0 #define SCAN_CODE(x) ((x >> 16) & 0xff) #define IS_EXTENDED(x) (0x01000000 & x) @@ -128,73 +120,12 @@ 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) - -1, // OPENGL -> no fallback -#endif - -1, // No SDL2ACCEL on Windows OSD -#if (USE_OPENGL) - VIDEO_MODE_OPENGL, // D3D -> OPENGL -#else - VIDEO_MODE_GDI, // D3D -> GDI -#endif - -1 // No SOFT on Windows OSD - }; - - int current_mode = video_config.mode; - while (current_mode != VIDEO_MODE_NONE) - { - bool error = false; - switch(current_mode) - { - case VIDEO_MODE_NONE: - error = renderer_none::init(machine()); - break; - case VIDEO_MODE_GDI: - error = renderer_gdi::init(machine()); - break; - case VIDEO_MODE_BGFX: - error = renderer_bgfx::init(machine()); - break; -#if (USE_OPENGL) - case VIDEO_MODE_OPENGL: - renderer_ogl::init(machine()); - break; -#endif - case VIDEO_MODE_SDL2ACCEL: - fatalerror("SDL2-Accel renderer unavailable on Windows OSD."); - break; - case VIDEO_MODE_D3D: - error = renderer_d3d9::init(machine()); - break; - case VIDEO_MODE_SOFT: - fatalerror("SDL1 renderer unavailable on Windows OSD."); - break; - default: - fatalerror("Unknown video mode."); - break; - } - if (error) - { - current_mode = fallbacks[current_mode]; - } - else - { - break; - } - } - video_config.mode = current_mode; - return true; } void windows_osd_interface::update_slider_list() { - for (const auto &window : osd_common_t::s_window_list) + for (const auto &window : osd_common_t::window_list()) { // check if any window has dirty sliders if (window->has_renderer() && window->renderer().sliders_dirty()) @@ -207,14 +138,14 @@ void windows_osd_interface::update_slider_list() int windows_osd_interface::window_count() { - return osd_common_t::s_window_list.size(); + return osd_common_t::window_list().size(); } void windows_osd_interface::build_slider_list() { m_sliders.clear(); - for (const auto &window : osd_common_t::s_window_list) + for (const auto &window : osd_common_t::window_list()) { if (window->has_renderer()) { @@ -227,11 +158,9 @@ void windows_osd_interface::build_slider_list() void windows_osd_interface::add_audio_to_recording(const int16_t *buffer, int samples_this_frame) { - auto window = osd_common_t::s_window_list.front(); // We only record on the first window - if (window != nullptr) - { + auto const &window = osd_common_t::window_list().front(); // We only record on the first window + if (window) window->renderer().add_audio_to_recording(buffer, samples_this_frame); - } } //============================================================ @@ -250,35 +179,11 @@ void windows_osd_interface::window_exit() // free all the windows while (!osd_common_t::s_window_list.empty()) { - auto window = osd_common_t::s_window_list.front(); - - // Destroy removes it from the list also + auto window = std::move(osd_common_t::s_window_list.back()); + s_window_list.pop_back(); window->destroy(); } - switch(video_config.mode) - { - case VIDEO_MODE_NONE: - renderer_none::exit(); - break; - case VIDEO_MODE_GDI: - renderer_gdi::exit(); - break; - case VIDEO_MODE_BGFX: - renderer_bgfx::exit(); - break; -#if (USE_OPENGL) - case VIDEO_MODE_OPENGL: - renderer_ogl::exit(); - break; -#endif - case VIDEO_MODE_D3D: - renderer_d3d9::exit(); - break; - default: - break; - } - // kill the UI pause event if (ui_pause_event) CloseHandle(ui_pause_event); @@ -287,10 +192,11 @@ void windows_osd_interface::window_exit() win_window_info::win_window_info( running_machine &machine, + render_module &renderprovider, int index, - std::shared_ptr<osd_monitor_info> monitor, + const std::shared_ptr<osd_monitor_info> &monitor, const osd_window_config *config) - : osd_window_t(machine, index, std::move(monitor), *config) + : osd_window_t(machine, renderprovider, index, std::move(monitor), *config) , m_init_state(0) , m_startmaximized(0) , m_isminimized(0) @@ -306,6 +212,7 @@ win_window_info::win_window_info( , m_lastclickx(0) , m_lastclicky(0) , m_last_surrogate(0) + , m_main(nullptr) , m_attached_mode(false) { m_non_fullscreen_bounds.left = 0; @@ -396,8 +303,8 @@ static LRESULT CALLBACK winwindow_video_window_proc_ui(HWND wnd, UINT message, W static bool is_mame_window(HWND hwnd) { - for (const auto &window : osd_common_t::s_window_list) - if (std::static_pointer_cast<win_window_info>(window)->platform_window() == hwnd) + for (const auto &window : osd_common_t::window_list()) + if (dynamic_cast<win_window_info &>(*window).platform_window() == hwnd) return true; return false; @@ -560,10 +467,8 @@ void winwindow_take_snap() assert(GetCurrentThreadId() == main_threadid); // iterate over windows and request a snap - for (const auto &window : osd_common_t::s_window_list) - { + for (const auto &window : osd_common_t::window_list()) window->renderer().save(); - } } @@ -578,10 +483,8 @@ void winwindow_toggle_fsfx() assert(GetCurrentThreadId() == main_threadid); // iterate over windows and request a snap - for (const auto &window : osd_common_t::s_window_list) - { + for (const auto &window : osd_common_t::window_list()) window->renderer().toggle_fsfx(); - } } @@ -596,10 +499,8 @@ void winwindow_take_video() assert(GetCurrentThreadId() == main_threadid); // iterate over windows and request a snap - for (const auto &window : osd_common_t::s_window_list) - { + for (const auto &window : osd_common_t::window_list()) window->renderer().record(); - } } @@ -614,19 +515,27 @@ void winwindow_toggle_full_screen() assert(GetCurrentThreadId() == main_threadid); // if we are in debug mode, never go full screen - for (const auto &window : osd_common_t::s_window_list) + for (const auto &window : osd_common_t::window_list()) + { if (window->machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) return; + } // toggle the window mode video_config.windowed = !video_config.windowed; // iterate over windows and toggle their fullscreen state - for (const auto &window : osd_common_t::s_window_list) - SendMessage(std::static_pointer_cast<win_window_info>(window)->platform_window(), WM_USER_SET_FULLSCREEN, !video_config.windowed, 0); + for (const auto &window : osd_common_t::window_list()) + { + SendMessage( + dynamic_cast<win_window_info &>(*window).platform_window(), + WM_USER_SET_FULLSCREEN, + !video_config.windowed, + 0); + } // Set the first window as foreground - SetForegroundWindow(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window()); + SetForegroundWindow(dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window()); } @@ -639,9 +548,9 @@ void winwindow_toggle_full_screen() bool winwindow_has_focus() { // see if one of the video windows has focus - for (const auto &window : osd_common_t::s_window_list) + for (const auto &window : osd_common_t::window_list()) { - switch (std::static_pointer_cast<win_window_info>(window)->focus()) + switch (dynamic_cast<win_window_info &>(*window).focus()) { case win_window_focus::NONE: break; @@ -682,10 +591,10 @@ void winwindow_update_cursor_state(running_machine &machine) assert(GetCurrentThreadId() == main_threadid); // If no windows, just return - if (osd_common_t::s_window_list.empty()) + if (osd_common_t::window_list().empty()) return; - auto &window = static_cast<win_window_info &>(*osd_common_t::s_window_list.front()); + auto &window = static_cast<win_window_info &>(*osd_common_t::window_list().front()); // if we should hide the mouse cursor, then do it // rules are: @@ -720,21 +629,26 @@ void winwindow_update_cursor_state(running_machine &machine) // (main thread) //============================================================ -void win_window_info::create(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config *config) +std::unique_ptr<win_window_info> win_window_info::create( + running_machine &machine, + render_module &renderprovider, + int index, + const std::shared_ptr<osd_monitor_info> &monitor, + const osd_window_config *config) { assert(GetCurrentThreadId() == main_threadid); // allocate a new window object - auto window = std::make_shared<win_window_info>(machine, index, monitor, config); + auto window = std::make_unique<win_window_info>(machine, renderprovider, index, monitor, config); // set main window if (window->index() > 0) { - for (const auto &w : osd_common_t::s_window_list) + for (const auto &w : osd_common_t::window_list()) { if (w->index() == 0) { - window->set_main_window(std::static_pointer_cast<osd_window>(w)); + window->set_main_window(dynamic_cast<win_window_info &>(*w)); break; } } @@ -742,12 +656,12 @@ void win_window_info::create(running_machine &machine, int index, std::shared_pt else { // We must be the main window - window->set_main_window(window); + window->set_main_window(*window); } // see if we are safe for fullscreen window->m_fullscreen_safe = TRUE; - for (const auto &win : osd_common_t::s_window_list) + for (const auto &win : osd_common_t::window_list()) if (win->monitor() == monitor.get()) window->m_fullscreen_safe = FALSE; @@ -767,6 +681,8 @@ void win_window_info::create(running_machine &machine, int index, std::shared_pt // handle error conditions if (window->m_init_state == -1) fatalerror("Unable to complete window creation\n"); + + return window; } //============================================================ @@ -1016,16 +932,16 @@ int win_window_info::complete_create() { // create the window, but don't show it yet hwnd = win_create_window_ex_utf8( - fullscreen() ? FULLSCREEN_STYLE_EX : WINDOW_STYLE_EX, - "MAME", - title().c_str(), - fullscreen() ? FULLSCREEN_STYLE : WINDOW_STYLE, - monitorbounds.left() + 20, monitorbounds.top() + 20, - monitorbounds.left() + 100, monitorbounds.top() + 100, - nullptr,//(osd_common_t::s_window_list != nullptr) ? osd_common_t::s_window_list->m_hwnd : nullptr, - nullptr, - GetModuleHandleUni(), - nullptr); + fullscreen() ? FULLSCREEN_STYLE_EX : WINDOW_STYLE_EX, + "MAME", + title().c_str(), + fullscreen() ? FULLSCREEN_STYLE : WINDOW_STYLE, + monitorbounds.left() + 20, monitorbounds.top() + 20, + monitorbounds.left() + 100, monitorbounds.top() + 100, + nullptr,//(osd_common_t::s_window_list != nullptr) ? osd_common_t::s_window_list->m_hwnd : nullptr, + nullptr, + GetModuleHandleUni(), + nullptr); } if (hwnd == nullptr) @@ -1038,9 +954,9 @@ int win_window_info::complete_create() SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); // skip the positioning stuff for '-video none' or '-attach_window' - if (video_config.mode == VIDEO_MODE_NONE || attached_mode()) + if (!renderer_interactive() || attached_mode()) { - set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this())); + renderer_create(); if (renderer().create()) return 1; return 0; @@ -1064,7 +980,7 @@ int win_window_info::complete_create() // show the window if (!fullscreen() || m_fullscreen_safe) { - set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this())); + renderer_create(); if (renderer().create()) return 1; @@ -1301,13 +1217,13 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR { if ((wparam == WA_ACTIVE) || (wparam == WA_CLICKACTIVE)) { - for (const auto &w : osd_common_t::s_window_list) - ShowWindow(std::static_pointer_cast<win_window_info>(w)->platform_window(), SW_RESTORE); + for (const auto &w : osd_common_t::window_list()) + ShowWindow(dynamic_cast<win_window_info &>(*w).platform_window(), SW_RESTORE); } else if ((wparam == WA_INACTIVE) && !is_mame_window(HWND(lparam))) { - for (const auto &w : osd_common_t::s_window_list) - ShowWindow(std::static_pointer_cast<win_window_info>(w)->platform_window(), SW_MINIMIZE); + for (const auto &w : osd_common_t::window_list()) + ShowWindow(dynamic_cast<win_window_info &>(*w).platform_window(), SW_MINIMIZE); } } @@ -1809,17 +1725,19 @@ void win_window_info::set_fullscreen(int fullscreen) // reset UI to main menu // FIXME: this cause crash if called when running_machine.m_ui not yet initialised. e.g. when trying to show error/warning messagebox at startup (during auto-switch from full screen to windowed mode). + // the menus need to be able to survive a fullscreen toggle anyway machine().ui().menu_reset(); - // kill off the drawers + // kill off the renderer renderer_reset(); // hide ourself ShowWindow(platform_window(), SW_HIDE); - // configure the window if non-fullscreen if (!fullscreen) { + // configure the window if non-fullscreen + // adjust the style SetWindowLong(platform_window(), GWL_STYLE, WINDOW_STYLE); SetWindowLong(platform_window(), GWL_EXSTYLE, WINDOW_STYLE_EX); @@ -1844,10 +1762,10 @@ void win_window_info::set_fullscreen(int fullscreen) maximize_window(); } } - - // configure the window if fullscreen else { + // configure the window if fullscreen + // save the bounds GetWindowRect(platform_window(), &m_non_fullscreen_bounds); @@ -1866,12 +1784,12 @@ void win_window_info::set_fullscreen(int fullscreen) // show ourself if (!this->fullscreen() || m_fullscreen_safe) { - if (video_config.mode != VIDEO_MODE_NONE) + if (renderer_interactive()) ShowWindow(platform_window(), SW_SHOW); - set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this())); + renderer_create(); if (renderer().create()) - exit(1); + exit(1); // FIXME: better error handling than just silently exiting on failure } // ensure we're still adjusted correctly @@ -1930,7 +1848,7 @@ bool winwindow_qt_filter(void *message) if(msg->hwnd) // get the machine associated with this window ptr = GetWindowLongPtr(msg->hwnd, GWLP_USERDATA); else // any one will have to do - ptr = (LONG_PTR)osd_common_t::s_window_list.front().get(); + ptr = (LONG_PTR)osd_common_t::window_list().front().get(); winwindow_dispatch_message(((win_window_info *)ptr)->machine(), msg); return true; diff --git a/src/osd/windows/window.h b/src/osd/windows/window.h index 3449a8ea1ac..aa56746a820 100644 --- a/src/osd/windows/window.h +++ b/src/osd/windows/window.h @@ -54,7 +54,7 @@ enum class win_window_focus class win_window_info : public osd_window_t<HWND> { public: - win_window_info(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config *config); + win_window_info(running_machine &machine, render_module &renderprovider, int index, const std::shared_ptr<osd_monitor_info> &monitor, const osd_window_config *config); bool attached_mode() const { return m_attached_mode; } win_window_focus focus() const; @@ -68,6 +68,9 @@ public: return osd_dim(client.right - client.left, client.bottom - client.top); } + win_window_info *main_window() const { return m_main; } + void set_main_window(win_window_info &main) { m_main = &main; } + void capture_pointer() override; void release_pointer() override; void show_pointer() override; @@ -77,7 +80,12 @@ public: // static - static void create(running_machine &machine, int index, std::shared_ptr<osd_monitor_info> monitor, const osd_window_config *config); + static std::unique_ptr<win_window_info> create( + running_machine &machine, + render_module &renderprovider, + int index, + const std::shared_ptr<osd_monitor_info> &monitor, + const osd_window_config *config); // static callbacks @@ -126,15 +134,10 @@ private: void adjust_window_position_after_major_change(); void set_fullscreen(int fullscreen); - static POINT s_saved_cursor_pos; - + win_window_info * m_main; bool m_attached_mode; -}; -struct osd_draw_callbacks -{ - osd_renderer *(*create)(osd_window *window); - void (*exit)(void); + static POINT s_saved_cursor_pos; }; diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp index 115853c15d9..6439da96a57 100644 --- a/src/osd/windows/winmain.cpp +++ b/src/osd/windows/winmain.cpp @@ -89,7 +89,7 @@ public: if (channel == OSD_OUTPUT_CHANNEL_ERROR) { // if we are in fullscreen mode, go to windowed mode - if ((video_config.windowed == 0) && !osd_common_t::s_window_list.empty()) + if ((video_config.windowed == 0) && !osd_common_t::window_list().empty()) winwindow_toggle_full_screen(); auto &state(get_state()); @@ -284,21 +284,6 @@ windows_osd_interface::~windows_osd_interface() //============================================================ -// video_register -//============================================================ - -void windows_osd_interface::video_register() -{ - video_options_add("gdi", nullptr); - video_options_add("d3d", nullptr); -#if USE_OPENGL - video_options_add("opengl", nullptr); -#endif - video_options_add("bgfx", nullptr); - //video_options_add("auto", nullptr); // making d3d video default one -} - -//============================================================ // init //============================================================ @@ -352,9 +337,9 @@ void windows_osd_interface::init(running_machine &machine) osd_common_t::init_subsystems(); // notify listeners of screen configuration - for (const auto &info : osd_common_t::s_window_list) + for (const auto &info : osd_common_t::window_list()) { - machine.output().set_value(string_format("Orientation(%s)", info->monitor()->devicename()), std::static_pointer_cast<win_window_info>(info)->m_targetorient); + machine.output().set_value(string_format("Orientation(%s)", info->monitor()->devicename()), dynamic_cast<win_window_info &>(*info).m_targetorient); } // hook up the debugger log diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index 7c4f746a943..b963cf09309 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -67,8 +67,6 @@ public: // video overridables virtual void add_audio_to_recording(const int16_t *buffer, int samples_this_frame) override; - virtual void video_register() override; - virtual bool video_init() override; virtual bool window_init() override; |