summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/render/drawbgfx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/render/drawbgfx.cpp')
-rw-r--r--src/osd/modules/render/drawbgfx.cpp1147
1 files changed, 783 insertions, 364 deletions
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index 3c15bc3cf96..ef90478e59e 100644
--- a/src/osd/modules/render/drawbgfx.cpp
+++ b/src/osd/modules/render/drawbgfx.cpp
@@ -5,10 +5,44 @@
// drawbgfx.cpp - BGFX renderer
//
//============================================================
+
+#include "drawbgfx.h"
+
+// render/bgfx
+#include "bgfx/effect.h"
+#include "bgfx/effectmanager.h"
+#include "bgfx/shadermanager.h"
+#include "bgfx/slider.h"
+#include "bgfx/target.h"
+#include "bgfx/target.h"
+#include "bgfx/targetmanager.h"
+#include "bgfx/texture.h"
+#include "bgfx/texturemanager.h"
+#include "bgfx/uniform.h"
+#include "bgfx/view.h"
+
+// render
+#include "aviwrite.h"
+#include "bgfxutil.h"
+#include "render_module.h"
+
+// emu
+#include "emu.h"
+#include "config.h"
+#include "render.h"
+#include "rendutil.h"
+
+// util
+#include "util/xmlfile.h"
+
+// OSD
+#include "modules/lib/osdobj_common.h"
+#include "window.h"
+
#include <bx/math.h>
#include <bx/readerwriter.h>
-#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) || defined(OSD_UWP)
+#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
// standard windows headers
#include <windows.h>
#if defined(SDLMAME_WIN32)
@@ -22,38 +56,415 @@ extern void *GetOSWindow(void *wincontroller);
#endif
#endif
-// MAMEOS headers
-#include "emu.h"
-#include "window.h"
-#include "rendutil.h"
-#include "aviwrite.h"
-
#include <bgfx/bgfx.h>
#include <bgfx/platform.h>
+
+#include "imgui/imgui.h"
+
#include <algorithm>
-#include "drawbgfx.h"
-#include "bgfxutil.h"
-#include "bgfx/texturemanager.h"
-#include "bgfx/targetmanager.h"
-#include "bgfx/shadermanager.h"
-#include "bgfx/effectmanager.h"
-#include "bgfx/chainmanager.h"
-#include "bgfx/effect.h"
-#include "bgfx/texture.h"
-#include "bgfx/target.h"
-#include "bgfx/chain.h"
-#include "bgfx/vertex.h"
-#include "bgfx/uniform.h"
-#include "bgfx/slider.h"
-#include "bgfx/target.h"
-#include "bgfx/view.h"
-#include "imgui/imgui.h"
+//============================================================
+// Renderer interface to parent module
+//============================================================
+
+class renderer_bgfx::parent_module
+{
+public:
+ util::xml::data_node &persistent_settings() { return *m_persistent_settings; }
+ osd_options const &options() const { return *m_options; }
+ uint32_t max_texture_size() const { return m_max_texture_size; }
+
+ template <typename T>
+ util::notifier_subscription subscribe_load(void (T::*func)(util::xml::data_node const &), T *obj)
+ {
+ return m_load_notifier.subscribe(delegate<void (util::xml::data_node const &)>(func, obj));
+ }
+
+ template <typename T>
+ util::notifier_subscription subscribe_save(void (T::*func)(util::xml::data_node &), T *obj)
+ {
+ return m_save_notifier.subscribe(delegate<void (util::xml::data_node &)>(func, obj));
+ }
+
+protected:
+ parent_module()
+ : m_options(nullptr)
+ , m_max_texture_size(0)
+ , m_renderer_count(0)
+ {
+ }
+ virtual ~parent_module()
+ {
+ assert(!m_renderer_count);
+ }
+
+ bool has_active_renderers() const
+ {
+ return 0 < m_renderer_count;
+ }
+
+ 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;
+
+private:
+ friend class parent_module_holder;
+
+ virtual void last_renderer_destroyed() = 0;
+
+ void renderer_created()
+ {
+ ++m_renderer_count;
+ }
+
+ void renderer_destroyed()
+ {
+ assert(m_renderer_count);
+ if (!--m_renderer_count)
+ last_renderer_destroyed();
+ }
+
+ unsigned m_renderer_count;
+};
+
+
+inline renderer_bgfx::parent_module_holder::parent_module_holder(parent_module &parent)
+ : m_parent(parent)
+{
+ m_parent.renderer_created();
+}
+
+
+inline renderer_bgfx::parent_module_holder::~parent_module_holder()
+{
+ m_parent.renderer_destroyed();
+}
+
+
+
+//============================================================
+// OSD MODULE
+//============================================================
+
+namespace osd {
+
+namespace {
+
+class video_bgfx : public osd_module, public render_module, protected renderer_bgfx::parent_module
+{
+public:
+ video_bgfx()
+ : osd_module(OSD_RENDERER_PROVIDER, "bgfx")
+ , 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:
+ virtual void last_renderer_destroyed() override;
+
+ 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);
+
+ bool m_bgfx_library_initialized;
+};
+
+
+//============================================================
+// video_bgfx::init
+//============================================================
+
+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;
+}
+
+
+//============================================================
+// video_bgfx::exit
+//============================================================
+
+void video_bgfx::exit()
+{
+ assert(!has_active_renderers());
+
+ 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;
+}
+
+
+//============================================================
+// video_bgfx::create
+//============================================================
+
+std::unique_ptr<osd_renderer> video_bgfx::create(osd_window &window)
+{
+ // start BGFX if this is the first window
+ if (!m_bgfx_library_initialized)
+ {
+ assert(window.index() == 0); // bad things will happen otherwise
+ assert(!has_active_renderers());
+
+ osd_printf_verbose("Initializing BGFX library\n");
+ if (!init_bgfx_library(window))
+ {
+ osd_printf_error("BGFX library initialization failed\n");
+ return nullptr;
+ }
+ m_bgfx_library_initialized = true;
+ }
+
+ return std::make_unique<renderer_bgfx>(window, static_cast<renderer_bgfx::parent_module &>(*this));
+}
+
+
+//============================================================
+// video_bgfx::last_renderer_destroyed
+//============================================================
+
+void video_bgfx::last_renderer_destroyed()
+{
+ if (m_bgfx_library_initialized)
+ {
+ osd_printf_verbose("No more renderers - shutting down BGFX library\n");
+ imguiDestroy();
+ bgfx::shutdown();
+ m_bgfx_library_initialized = false;
+ m_max_texture_size = 0;
+ }
+}
+
+
+//============================================================
+// video_bgfx::load_config
+//============================================================
+
+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);
+}
+
+
+//============================================================
+// video_bgfx::init_bgfx_library
//============================================================
-// DEBUGGING
+
+bool video_bgfx::init_bgfx_library(osd_window &window)
+{
+ osd_dim const wdim = window.get_size();
+
+ bgfx::Init init;
+ init.type = bgfx::RendererType::Count;
+ init.vendorId = BGFX_PCI_ID_NONE;
+ init.resolution.width = wdim.width();
+ init.resolution.height = wdim.height();
+ init.resolution.numBackBuffers = 1;
+ init.resolution.reset = video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE;
+ 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_warning("Unknown BGFX backend type '%s', going with auto-detection.\n", backend);
+
+ if (!bgfx::init(init))
+ return false;
+
+ 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);
+
+ // Get actual maximum texture size
+ bgfx::Caps const *const caps = bgfx::getCaps();
+ m_max_texture_size = caps->limits.maxTextureSize;
+
+ ScreenVertex::init();
+
+ imguiCreate();
+
+ return true;
+}
+
+
//============================================================
+// Utility for setting up window handle
+//============================================================
+
+bool video_bgfx::set_platform_data(bgfx::PlatformData &platform_data, osd_window const &window)
+{
+#if defined(OSD_WINDOWS)
+ platform_data.ndt = nullptr;
+ platform_data.nwh = dynamic_cast<win_window_info const &>(window).platform_window();
+#elif defined(OSD_MAC)
+ platform_data.ndt = nullptr;
+ platform_data.nwh = GetOSWindow(dynamic_cast<mac_window_info const &>(window).platform_window());
+#elif defined(SDLMAME_EMSCRIPTEN)
+ platform_data.ndt = nullptr;
+ platform_data.nwh = (void *)"#canvas"; // HTML5 target selector
+#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("BGFX: Error getting SDL window info: %s\n", SDL_GetError());
+ return false;
+ }
+
+ switch (wmi.subsystem)
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ case SDL_SYSWM_WINDOWS:
+ platform_data.ndt = nullptr;
+ platform_data.nwh = wmi.info.win.window;
+ break;
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ case SDL_SYSWM_X11:
+ platform_data.ndt = wmi.info.x11.display;
+ platform_data.nwh = (void *)uintptr_t(wmi.info.x11.window);
+ break;
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ case SDL_SYSWM_COCOA:
+ platform_data.ndt = nullptr;
+ platform_data.nwh = wmi.info.cocoa.window;
+ break;
+#endif
+#if defined(SDL_VIDEO_DRIVER_WAYLAND) && SDL_VERSION_ATLEAST(2, 0, 16)
+ case SDL_SYSWM_WAYLAND:
+ platform_data.ndt = wmi.info.wl.display;
+ platform_data.nwh = wmi.info.wl.surface;
+ if (!platform_data.nwh)
+ {
+ osd_printf_error("BGFX: Error creating a Wayland window\n");
+ return false;
+ }
+ platform_data.type = bgfx::NativeWindowHandleType::Wayland;
+ break;
+#endif
+#if defined(SDL_VIDEO_DRIVER_ANDROID)
+ case SDL_SYSWM_ANDROID:
+ platform_data.ndt = nullptr;
+ platform_data.nwh = wmi.info.android.window;
+ break;
+#endif
+ default:
+ osd_printf_error("BGFX: Unsupported SDL window manager type %u\n", wmi.subsystem);
+ return false;
+ }
+#endif // defined(OSD_*)
+
+ platform_data.context = nullptr;
+ platform_data.backBuffer = nullptr;
+ platform_data.backBufferDS = nullptr;
+ bgfx::setPlatformData(platform_data);
+
+ return true;
+}
+
+} // anonymous namespace
+
+} // namespace osd
+
+MODULE_DEFINITION(RENDERER_BGFX, osd::video_bgfx)
+
+
//============================================================
// CONSTANTS
@@ -64,6 +475,8 @@ 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
//============================================================
@@ -71,45 +484,113 @@ char const *const renderer_bgfx::WINDOW_PREFIX = "Window 0, ";
#define GIBBERISH (0)
#define SCENE_VIEW (0)
+
+
//============================================================
// STATICS
//============================================================
-bool renderer_bgfx::s_window_set = false;
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 std::pair<void *, bool> sdlNativeWindowHandle(SDL_Window *window)
+{
+ SDL_SysWMinfo wmi;
+ SDL_VERSION(&wmi.version);
+ if (!SDL_GetWindowWMInfo(window, &wmi))
+ return std::make_pair(nullptr, false);
+
+ switch (wmi.subsystem)
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ case SDL_SYSWM_WINDOWS:
+ return std::make_pair(wmi.info.win.window, true);
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ case SDL_SYSWM_X11:
+ return std::make_pair((void *)uintptr_t(wmi.info.x11.window), true);
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ case SDL_SYSWM_COCOA:
+ return std::make_pair(wmi.info.cocoa.window, true);
+#endif
+#if defined(SDL_VIDEO_DRIVER_WAYLAND) && SDL_VERSION_ATLEAST(2, 0, 16)
+ case SDL_SYSWM_WAYLAND:
+ return std::make_pair(wmi.info.wl.surface, true);
+#endif
+#if defined(SDL_VIDEO_DRIVER_ANDROID)
+ case SDL_SYSWM_ANDROID:
+ return std::make_pair(wmi.info.android.window, true);
+#endif
+ default:
+ return std::make_pair(nullptr, false);
+ }
+}
+#endif // OSD_SDL
+
+
//============================================================
// renderer_bgfx - constructor
//============================================================
-renderer_bgfx::renderer_bgfx(std::shared_ptr<osd_window> w)
- : osd_renderer(w, FLAG_NONE)
- , m_options(downcast<osd_options &>(w->machine().options()))
+renderer_bgfx::renderer_bgfx(osd_window &window, parent_module &parent)
+ : osd_renderer(window)
+ , m_module(parent)
, 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_avi_view(nullptr)
, m_avi_writer(nullptr)
, m_avi_target(nullptr)
+ , m_load_sub(parent.subscribe_load(&renderer_bgfx::load_config, this))
+ , m_save_sub(parent.subscribe_save(&renderer_bgfx::save_config, this))
{
+ // load settings if recreated after fullscreen toggle
+ util::xml::data_node *windownode = m_module().persistent_settings().get_child("window");
+ while (windownode)
+ {
+ 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();
+ }
+ }
}
+
+
//============================================================
// renderer_bgfx - destructor
//============================================================
renderer_bgfx::~renderer_bgfx()
{
+ // persist settings across fullscreen toggle
+ if (m_config)
+ m_config->get_first_child()->copy_into(m_module().persistent_settings());
+ else if (m_chains)
+ m_chains->save_config(m_module().persistent_settings());
+
bgfx::reset(0, 0, BGFX_RESET_NONE);
- bgfx::touch(0);
- bgfx::frame();
+
if (m_avi_writer != nullptr && m_avi_writer->recording())
{
m_avi_writer->stop();
@@ -123,257 +604,99 @@ renderer_bgfx::~renderer_bgfx()
delete [] m_avi_data;
delete m_avi_view;
}
-
- // Cleanup.
- delete m_chains;
- delete m_effects;
- delete m_shaders;
- delete m_textures;
- delete m_targets;
}
+
+
//============================================================
// renderer_bgfx::create
//============================================================
-#ifdef OSD_WINDOWS
-inline void winSetHwnd(::HWND _window)
-{
- bgfx::PlatformData pd;
- pd.ndt = NULL;
- pd.nwh = _window;
- pd.context = NULL;
- pd.backBuffer = NULL;
- pd.backBufferDS = NULL;
- bgfx::setPlatformData(pd);
-}
-#elif defined(OSD_MAC)
-inline void macSetWindow(void *_window)
-{
- bgfx::PlatformData pd;
- pd.ndt = NULL;
- pd.nwh = GetOSWindow(_window);
- pd.context = NULL;
- pd.backBuffer = NULL;
- pd.backBufferDS = NULL;
- bgfx::setPlatformData(pd);
-}
-#elif defined(OSD_SDL)
-static void* sdlNativeWindowHandle(SDL_Window* _window)
-{
- SDL_SysWMinfo wmi;
- SDL_VERSION(&wmi.version);
- if (!SDL_GetWindowWMInfo(_window, &wmi))
- {
- return nullptr;
- }
-
-# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD || BX_PLATFORM_RPI
- return (void*)wmi.info.x11.window;
-# elif BX_PLATFORM_OSX
- return wmi.info.cocoa.window;
-# elif BX_PLATFORM_WINDOWS
- return wmi.info.win.window;
-# elif BX_PLATFORM_STEAMLINK
- return wmi.info.vivante.window;
-# elif BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_ANDROID
- return nullptr;
-# endif // BX_PLATFORM_
-}
-
-inline bool sdlSetWindow(SDL_Window* _window)
-{
- SDL_SysWMinfo wmi;
- SDL_VERSION(&wmi.version);
- if (!SDL_GetWindowWMInfo(_window, &wmi) )
- {
- return false;
- }
-
- bgfx::PlatformData pd;
-# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD
- pd.ndt = wmi.info.x11.display;
- pd.nwh = (void*)(uintptr_t)wmi.info.x11.window;
-# elif BX_PLATFORM_OSX
- pd.ndt = NULL;
- pd.nwh = wmi.info.cocoa.window;
-# elif BX_PLATFORM_WINDOWS
- pd.ndt = NULL;
- pd.nwh = wmi.info.win.window;
-# elif BX_PLATFORM_STEAMLINK
- pd.ndt = wmi.info.vivante.display;
- pd.nwh = wmi.info.vivante.window;
-# endif // BX_PLATFORM_
- pd.context = NULL;
- pd.backBuffer = NULL;
- pd.backBufferDS = NULL;
- bgfx::setPlatformData(pd);
-
- return true;
-}
-#elif defined(OSD_UWP)
-inline void winrtSetWindow(::IUnknown* _window)
-{
- bgfx::PlatformData pd;
- pd.ndt = NULL;
- pd.nwh = _window;
- pd.context = NULL;
- pd.backBuffer = NULL;
- pd.backBufferDS = NULL;
- bgfx::setPlatformData(pd);
-}
-
-IInspectable* AsInspectable(Platform::Agile<Windows::UI::Core::CoreWindow> win)
-{
- return reinterpret_cast<IInspectable*>(win.Get());
-}
-#endif
-
int renderer_bgfx::create()
{
- // create renderer
- std::shared_ptr<osd_window> win = assert_window();
- osd_dim wdim = win->get_size();
- m_width[win->m_index] = wdim.width();
- m_height[win->m_index] = wdim.height();
- if (win->m_index == 0)
- {
- if (!s_window_set)
- {
- s_window_set = true;
- ScreenVertex::init();
- }
- else
- {
- bgfx::shutdown();
- bgfx::PlatformData blank_pd;
- memset(&blank_pd, 0, sizeof(bgfx::PlatformData));
- bgfx::setPlatformData(blank_pd);
- }
-#ifdef OSD_WINDOWS
- winSetHwnd(std::static_pointer_cast<win_window_info>(win)->platform_window());
-#elif defined(OSD_UWP)
+ const osd_dim wdim = window().get_size();
+ s_width[window().index()] = wdim.width();
+ s_height[window().index()] = wdim.height();
+ m_dimensions = wdim;
- winrtSetWindow(AsInspectable(std::static_pointer_cast<uwp_window_info>(win)->platform_window()));
-#elif defined(OSD_MAC)
- macSetWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window());
-#else
- sdlSetWindow(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window());
-#endif
- std::string backend(m_options.bgfx_backend());
- bgfx::Init init;
- init.type = bgfx::RendererType::Count;
- init.vendorId = BGFX_PCI_ID_NONE;
- init.resolution.width = wdim.width();
- init.resolution.height = wdim.height();
- init.resolution.reset = BGFX_RESET_NONE;
- if (backend == "auto")
- {
- }
- else if (backend == "dx9" || backend == "d3d9")
- {
- init.type = bgfx::RendererType::Direct3D9;
- }
- else if (backend == "dx11" || backend == "d3d11")
- {
- init.type = bgfx::RendererType::Direct3D11;
- }
- else if (backend == "gles")
- {
- init.type = bgfx::RendererType::OpenGLES;
- }
- else if (backend == "glsl" || backend == "opengl")
- {
- init.type = bgfx::RendererType::OpenGL;
- }
- else if (backend == "metal")
- {
- init.type = bgfx::RendererType::Metal;
- }
- else
- {
- printf("Unknown backend type '%s', going with auto-detection\n", backend.c_str());
- }
- bgfx::init(init);
- bgfx::reset(m_width[win->m_index], m_height[win->m_index], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
- // Enable debug text.
- bgfx::setDebug(m_options.bgfx_debug() ? BGFX_DEBUG_STATS : BGFX_DEBUG_TEXT);
- m_dimensions = osd_dim(m_width[0], m_height[0]);
- }
-
- m_textures = new texture_manager();
- m_targets = new target_manager(*m_textures);
-
- m_shaders = new shader_manager(m_options);
- m_effects = new effect_manager(m_options, *m_shaders);
+ // finish creating the renderer
+ m_textures = std::make_unique<texture_manager>();
+ m_targets = std::make_unique<target_manager>(*m_textures);
- if (win->m_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(), m_width[win->m_index], m_height[win->m_index]);
-#elif defined(OSD_UWP)
- m_framebuffer = m_targets->create_backbuffer(AsInspectable(std::static_pointer_cast<uwp_window_info>(win)->platform_window()), m_width[win->m_index], m_height[win->m_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()), m_width[win->m_index], m_height[win->m_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()), m_width[win->m_index], m_height[win->m_index]);
+ auto const [winhdl, success] = sdlNativeWindowHandle(dynamic_cast<sdl_window_info &>(window()).platform_window());
+ if (!success)
+ {
+ m_targets.reset();
+ m_textures.reset();
+ return -1;
+ }
+ m_framebuffer = m_targets->create_backbuffer(winhdl, s_width[window().index()], s_height[window().index()]);
#endif
- bgfx::touch(win->m_index);
+ bgfx::touch(window().index());
- if (m_ortho_view) {
+ if (m_ortho_view)
m_ortho_view->set_backbuffer(m_framebuffer);
- }
}
- // Create program from shaders.
- m_gui_effect[0] = m_effects->effect("gui_opaque");
- m_gui_effect[1] = m_effects->effect("gui_blend");
- m_gui_effect[2] = m_effects->effect("gui_multiply");
- m_gui_effect[3] = m_effects->effect("gui_add");
-
- m_screen_effect[0] = m_effects->effect("screen_opaque");
- m_screen_effect[1] = m_effects->effect("screen_blend");
- m_screen_effect[2] = m_effects->effect("screen_multiply");
- m_screen_effect[3] = m_effects->effect("screen_add");
-
- if ( m_gui_effect[0] == nullptr || m_gui_effect[1] == nullptr || m_gui_effect[2] == nullptr || m_gui_effect[3] == nullptr ||
- m_screen_effect[0] == nullptr || m_screen_effect[1] == nullptr || m_screen_effect[2] == nullptr || m_screen_effect[3] == nullptr)
- {
- fatalerror("BGFX: Unable to load required shaders. Please check and reinstall the %s folder\n", m_options.bgfx_path());
- }
+ m_shaders = std::make_unique<shader_manager>();
+ m_effects = std::make_unique<effect_manager>(*m_shaders);
- m_chains = new chain_manager(win->machine(), m_options, *m_textures, *m_targets, *m_effects, win->m_index, *this);
+ // Create program from shaders.
+ m_gui_effect[0] = m_effects->get_or_load_effect(m_module().options(), "gui_opaque");
+ m_gui_effect[1] = m_effects->get_or_load_effect(m_module().options(), "gui_blend");
+ m_gui_effect[2] = m_effects->get_or_load_effect(m_module().options(), "gui_multiply");
+ m_gui_effect[3] = m_effects->get_or_load_effect(m_module().options(), "gui_add");
+
+ m_screen_effect[0] = m_effects->get_or_load_effect(m_module().options(), "screen_opaque");
+ m_screen_effect[1] = m_effects->get_or_load_effect(m_module().options(), "screen_blend");
+ m_screen_effect[2] = m_effects->get_or_load_effect(m_module().options(), "screen_multiply");
+ m_screen_effect[3] = m_effects->get_or_load_effect(m_module().options(), "screen_add");
+
+ const uint32_t max_prescale_size = std::min(2u * std::max(wdim.width(), wdim.height()), m_module().max_texture_size());
+ m_chains = std::make_unique<chain_manager>(
+ window().machine(),
+ m_module().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;
- m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::RGBA8, CACHE_SIZE, CACHE_SIZE, nullptr, flags);
+ m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::BGRA8, CACHE_SIZE, 0, CACHE_SIZE, nullptr, flags);
memset(m_white, 0xff, sizeof(uint32_t) * 16 * 16);
m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white));
- imguiCreate();
-
return 0;
}
+
+
//============================================================
// renderer_bgfx::record
//============================================================
void renderer_bgfx::record()
{
- std::shared_ptr<osd_window> win = assert_window();
-
- if (win->m_index > 0)
- {
+ if (window().index() > 0)
return;
- }
if (m_avi_writer == nullptr)
{
- m_avi_writer = new avi_write(win->machine(), m_width[0], m_height[0]);
- m_avi_data = new uint8_t[m_width[0] * m_height[0] * 4];
- m_avi_bitmap.allocate(m_width[0], m_height[0]);
+ m_avi_writer = new avi_write(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]);
}
if (m_avi_writer->recording())
@@ -387,9 +710,9 @@ void renderer_bgfx::record()
}
else
{
- m_avi_writer->record(m_options.bgfx_avi_name());
- m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::RGBA8, m_width[0], m_height[0], TARGET_STYLE_CUSTOM, false, true, 1, 0);
- m_avi_texture = bgfx::createTexture2D(m_width[0], m_height[0], false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK);
+ m_avi_writer->record(m_module().options().bgfx_avi_name());
+ m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::BGRA8, s_width[0], s_height[0], 1, 1, TARGET_STYLE_CUSTOM, false, true, 1, 0);
+ m_avi_texture = bgfx::createTexture2D(s_width[0], s_height[0], false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK);
if (m_avi_view == nullptr)
{
@@ -398,28 +721,6 @@ void renderer_bgfx::record()
}
}
-bool renderer_bgfx::init(running_machine &machine)
-{
- const char *bgfx_path = downcast<osd_options &>(machine.options()).bgfx_path();
-
- osd::directory::ptr directory = osd::directory::open(bgfx_path);
- if (directory == nullptr)
- {
- osd_printf_verbose("Unable to find the %s folder. Please reinstall it to use the BGFX renderer\n", bgfx_path);
- return true;
- }
-
- return false;
-}
-
-void renderer_bgfx::exit()
-{
- imguiDestroy();
-
- bgfx::shutdown();
- s_window_set = false;
-}
-
//============================================================
// drawsdl_xy_to_render_target
//============================================================
@@ -441,12 +742,12 @@ int renderer_bgfx::xy_to_render_target(int x, int y, int *xt, int *yt)
// drawbgfx_window_draw
//============================================================
-bgfx::VertexDecl ScreenVertex::ms_decl;
+bgfx::VertexLayout ScreenVertex::ms_decl;
void renderer_bgfx::put_packed_quad(render_primitive *prim, uint32_t hash, ScreenVertex* vertices)
{
rectangle_packer::packed_rectangle& rect = m_hash_to_entry[hash];
- float size = float(CACHE_SIZE);
+ auto size = float(CACHE_SIZE);
float u0 = (float(rect.x()) + 0.5f) / size;
float v0 = (float(rect.y()) + 0.5f) / size;
float u1 = u0 + (float(rect.width()) - 1.0f) / size;
@@ -498,9 +799,9 @@ void renderer_bgfx::vertex(ScreenVertex* vertex, float x, float y, float z, uint
vertex->m_v = v;
}
-void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen)
+void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index)
{
- ScreenVertex* vertices = reinterpret_cast<ScreenVertex*>(buffer->data);
+ auto* vertices = reinterpret_cast<ScreenVertex*>(buffer->data);
float x[4] = { prim->bounds.x0, prim->bounds.x1, prim->bounds.x0, prim->bounds.x1 };
float y[4] = { prim->bounds.y0, prim->bounds.y0, prim->bounds.y1, prim->bounds.y1 };
@@ -514,15 +815,24 @@ void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bg
vertex(&vertices[4], x[2], y[2], 0, 0xffffffff, u[2], v[2]);
vertex(&vertices[5], x[0], y[0], 0, 0xffffffff, u[0], v[0]);
- uint32_t texture_flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP;
+ uint32_t texture_flags = 0U;
+ if (!PRIMFLAG_GET_TEXWRAP(prim->flags))
+ texture_flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP;
if (video_config.filter == 0)
- {
texture_flags |= BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT;
- }
uint32_t blend = PRIMFLAG_GET_BLENDMODE(prim->flags);
bgfx::setVertexBuffer(0,buffer);
bgfx::setTexture(0, m_screen_effect[blend]->uniform("s_tex")->handle(), m_targets->target(screen, "output")->texture(), texture_flags);
+
+ bgfx_uniform* inv_view_dims = m_screen_effect[blend]->uniform("u_inv_view_dims");
+ if (inv_view_dims)
+ {
+ float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ inv_view_dims->upload();
+ }
+
m_screen_effect[blend]->submit(m_ortho_view->get_index());
}
@@ -531,15 +841,15 @@ void renderer_bgfx::render_avi_quad()
m_avi_view->set_index(s_current_view);
m_avi_view->setup();
- bgfx::setViewRect(s_current_view, 0, 0, m_width[0], m_height[0]);
- bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
+ bgfx::setViewRect(s_current_view, 0, 0, s_width[0], s_height[0]);
+ bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0);
bgfx::TransientVertexBuffer buffer;
bgfx::allocTransientVertexBuffer(&buffer, 6, ScreenVertex::ms_decl);
- ScreenVertex* vertices = reinterpret_cast<ScreenVertex*>(buffer.data);
+ auto* vertices = reinterpret_cast<ScreenVertex*>(buffer.data);
- float x[4] = { 0.0f, float(m_width[0]), 0.0f, float(m_width[0]) };
- float y[4] = { 0.0f, 0.0f, float(m_height[0]), float(m_height[0]) };
+ float x[4] = { 0.0f, float(s_width[0]), 0.0f, float(s_width[0]) };
+ float y[4] = { 0.0f, 0.0f, float(s_height[0]), float(s_height[0]) };
float u[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
float v[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
uint32_t rgba = 0xffffffff;
@@ -553,13 +863,23 @@ void renderer_bgfx::render_avi_quad()
bgfx::setVertexBuffer(0,&buffer);
bgfx::setTexture(0, m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]->uniform("s_tex")->handle(), m_avi_target->texture());
- m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]->submit(s_current_view);
+
+ bgfx_effect* effect = m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)];
+ bgfx_uniform* inv_view_dims = effect->uniform("u_inv_view_dims");
+ if (inv_view_dims)
+ {
+ float values[2] = { -1.0f / s_width[0], 1.0f / s_height[0] };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ inv_view_dims->upload();
+ }
+
+ effect->submit(s_current_view);
s_current_view++;
}
-void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer)
+void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int window_index)
{
- ScreenVertex* vertices = reinterpret_cast<ScreenVertex*>(buffer->data);
+ auto* vertices = reinterpret_cast<ScreenVertex*>(buffer->data);
uint32_t rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255);
float x[4] = { prim->bounds.x0, prim->bounds.x1, prim->bounds.x0, prim->bounds.x1 };
@@ -574,25 +894,50 @@ void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::Transient
vertex(&vertices[4], x[2], y[2], 0, rgba, u[2], v[2]);
vertex(&vertices[5], x[0], y[0], 0, rgba, u[0], v[0]);
- uint32_t texture_flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP;
- if (video_config.filter == 0)
- {
+ uint32_t texture_flags = 0U;
+ if (!PRIMFLAG_GET_TEXWRAP(prim->flags))
+ texture_flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP;
+ if (!PRIMFLAG_GET_ANTIALIAS(prim->flags))
texture_flags |= BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT;
- }
+ const bool is_screen = PRIMFLAG_GET_SCREENTEX(prim->flags);
uint16_t tex_width(prim->texture.width);
uint16_t tex_height(prim->texture.height);
- bgfx::TextureHandle texture = m_textures->create_or_update_mame_texture(prim->flags & PRIMFLAG_TEXFORMAT_MASK
- , tex_width, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base, prim->texture.seqid
- , texture_flags, prim->texture.unique_id, prim->texture.old_id);
+ bgfx::TextureHandle texture = BGFX_INVALID_HANDLE;
+ if (is_screen)
+ {
+ const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgra32(prim->flags & PRIMFLAG_TEXFORMAT_MASK
+ , tex_width, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base);
+ texture = bgfx::createTexture2D(tex_width, tex_height, false, 1, bgfx::TextureFormat::BGRA8, texture_flags, mem);
+ }
+ else
+ {
+ texture = m_textures->create_or_update_mame_texture(prim->flags & PRIMFLAG_TEXFORMAT_MASK
+ , tex_width, prim->texture.width_margin, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base, prim->texture.seqid
+ , texture_flags, prim->texture.unique_id, prim->texture.old_id);
+ }
- bgfx_effect** effects = PRIMFLAG_GET_SCREENTEX(prim->flags) ? m_screen_effect : m_gui_effect;
+ bgfx_effect** effects = is_screen ? m_screen_effect : m_gui_effect;
uint32_t blend = PRIMFLAG_GET_BLENDMODE(prim->flags);
bgfx::setVertexBuffer(0,buffer);
bgfx::setTexture(0, effects[blend]->uniform("s_tex")->handle(), texture);
+
+ bgfx_uniform* inv_view_dims = effects[blend]->uniform("u_inv_view_dims");
+ if (inv_view_dims)
+ {
+ float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ inv_view_dims->upload();
+ }
+
effects[blend]->submit(m_ortho_view->get_index());
+
+ if (is_screen)
+ {
+ bgfx::destroy(texture);
+ }
}
#define MAX_TEMP_COORDS 100
@@ -805,18 +1150,15 @@ 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->m_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();
- m_width[window_index] = wdim.width();
- m_height[window_index] = wdim.height();
+ osd_dim wdim = window().get_size();
+ s_width[window_index] = wdim.width();
+ s_height[window_index] = wdim.height();
// Set view 0 default viewport.
if (window_index == 0)
@@ -824,9 +1166,9 @@ int renderer_bgfx::draw(int update)
s_current_view = 0;
}
- win->m_primlist->acquire_lock();
- s_current_view += m_chains->handle_screen_chains(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)
@@ -834,6 +1176,26 @@ int renderer_bgfx::draw(int update)
return 0;
}
+ if (num_screens)
+ {
+ // Restore config after counting screens the first time
+ // Doing this here is hacky - it means config is restored at the wrong
+ // time if the initial view has no screens and the user switches to a
+ // view with screens. The trouble is there's no real interface between
+ // the render targets and the renderer so we don't actually know when
+ // we're first called on to render a live view (as opposed to an info
+ // screen).
+ if (m_config)
+ {
+ osd_printf_verbose("BGFX: Applying configuration for window %d\n", window().index());
+ m_chains->load_config(*m_config->get_first_child());
+ m_config.reset();
+ }
+
+ uint32_t chain_view_count = m_chains->process_screen_chains(s_current_view, window());
+ s_current_view += chain_view_count;
+ }
+
if (s_current_view > m_max_view)
{
m_max_view = s_current_view;
@@ -843,12 +1205,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)
{
@@ -873,12 +1235,21 @@ int renderer_bgfx::draw(int update)
}
}
- buffer_status status = buffer_primitives(atlas_valid, &prim, &buffer, screen);
+ buffer_status status = buffer_primitives(atlas_valid, &prim, &buffer, screen, window_index);
if (status != BUFFER_EMPTY && status != BUFFER_SCREEN)
{
- bgfx::setVertexBuffer(0,&buffer);
+ bgfx::setVertexBuffer(0, &buffer);
bgfx::setTexture(0, m_gui_effect[blend]->uniform("s_tex")->handle(), m_texture_cache->texture());
+
+ bgfx_uniform* inv_view_dims = m_gui_effect[blend]->uniform("u_inv_view_dims");
+ if (inv_view_dims)
+ {
+ float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] };
+ inv_view_dims->set(values, sizeof(float) * 2);
+ inv_view_dims->upload();
+ }
+
m_gui_effect[blend]->submit(m_ortho_view->get_index());
}
@@ -888,11 +1259,11 @@ 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.
- bgfx::touch(s_current_view > 0 ? s_current_view - 1 : 0);
+ //bgfx::touch(s_current_view > 0 ? s_current_view - 1 : 0);
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
@@ -904,7 +1275,10 @@ int renderer_bgfx::draw(int update)
bgfx::touch(s_current_view);
update_recording();
}
+ }
+ if (window().index() == osd_common_t::window_list().size() - 1)
+ {
bgfx::frame();
}
@@ -919,7 +1293,7 @@ void renderer_bgfx::update_recording()
int i = 0;
for (int y = 0; y < m_avi_bitmap.height(); y++)
{
- uint32_t *dst = &m_avi_bitmap.pix32(y);
+ uint32_t *dst = &m_avi_bitmap.pix(y);
for (int x = 0; x < m_avi_bitmap.width(); x++)
{
@@ -933,8 +1307,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->m_index == 0)
+ if (m_avi_writer != nullptr && m_avi_writer->recording() && window().index() == 0)
{
m_avi_writer->audio_frame(buffer, samples_this_frame);
}
@@ -942,47 +1315,36 @@ 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->m_index;
- const uint32_t width = m_width[window_index];
- const uint32_t height = m_height[window_index];
+ const uint32_t window_index = window().index();
+ const uint32_t width = s_width[window_index];
+ const uint32_t height = s_height[window_index];
- if (window_index == 0)
+ if (m_dimensions != osd_dim(width, height))
{
- if ((m_dimensions != osd_dim(width, height)))
- {
- bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
- m_dimensions = osd_dim(width, height);
- }
- }
- else
- {
- if ((m_dimensions != osd_dim(width, height)))
- {
- bgfx::reset(win->main_window()->get_size().width(), win->main_window()->get_size().height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
- m_dimensions = osd_dim(width, height);
+ bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
+ m_dimensions = osd_dim(width, height);
- delete m_framebuffer;
+ if (window().index() != 0)
+ {
#ifdef OSD_WINDOWS
- m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), width, height);
-#elif defined(OSD_UWP)
- m_framebuffer = m_targets->create_backbuffer(AsInspectable(std::static_pointer_cast<uwp_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()).first, width, height);
#endif
if (m_ortho_view)
+ {
m_ortho_view->set_backbuffer(m_framebuffer);
-
+ }
bgfx::setViewFrameBuffer(s_current_view, m_framebuffer->target());
- bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
- bgfx::setViewMode(s_current_view, bgfx::ViewMode::Sequential);
- bgfx::touch(s_current_view);
- bgfx::frame();
- return true;
}
+
+ bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0);
+ bgfx::setViewMode(s_current_view, bgfx::ViewMode::Sequential);
+ bgfx::touch(s_current_view);
+ bgfx::frame();
+ return true;
}
return false;
}
@@ -991,17 +1353,38 @@ void renderer_bgfx::setup_ortho_view()
{
if (!m_ortho_view)
{
- m_ortho_view = new bgfx_ortho_view(this, s_current_view, m_framebuffer, m_seen_views);
+ m_ortho_view = std::make_unique<bgfx_ortho_view>(this, 0, m_framebuffer, m_seen_views);
}
- m_ortho_view->update();
- if (m_ortho_view->get_index() == UINT_MAX) {
+ if (m_ortho_view->get_index() == UINT_MAX)
+ {
m_ortho_view->set_index(s_current_view);
m_ortho_view->setup();
s_current_view++;
}
+ m_ortho_view->update();
}
-renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen)
+render_primitive_list *renderer_bgfx::get_primitives()
+{
+ // determines whether the screen container is transformed by the chain's shaders
+ bool chain_transform = false;
+
+ // check the first chain
+ bgfx_chain* chain = this->m_chains->screen_chain(0);
+ if (chain != nullptr)
+ {
+ chain_transform = chain->transform();
+ }
+
+ osd_dim wdim = window().get_size();
+ if (wdim.width() > 0 && wdim.height() > 0)
+ window().target()->set_bounds(wdim.width(), wdim.height(), window().pixel_aspect());
+
+ 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)
{
int vertices = 0;
@@ -1043,18 +1426,18 @@ renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid,
{
#if SCENE_VIEW
setup_view(s_current_view, true);
- render_post_screen_quad(s_current_view, *prim, buffer, screen);
+ render_post_screen_quad(s_current_view, *prim, buffer, screen, window_index);
s_current_view++;
#else
setup_ortho_view();
- render_post_screen_quad(m_ortho_view->get_index(), *prim, buffer, screen);
+ render_post_screen_quad(m_ortho_view->get_index(), *prim, buffer, screen, window_index);
#endif
return BUFFER_SCREEN;
}
else
{
setup_ortho_view();
- render_textured_quad(*prim, buffer);
+ render_textured_quad(*prim, buffer, window_index);
return BUFFER_EMPTY;
}
}
@@ -1131,8 +1514,12 @@ void renderer_bgfx::process_atlas_packs(std::vector<std::vector<rectangle_packer
continue;
}
m_hash_to_entry[rect.hash()] = rect;
- const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(rect.format(), rect.width(), rect.height(), rect.rowpixels(), rect.palette(), rect.base());
- bgfx::updateTexture2D(m_texture_cache->texture(), 0, 0, rect.x(), rect.y(), rect.width(), rect.height(), mem);
+ bgfx::TextureFormat::Enum dst_format = bgfx::TextureFormat::BGRA8;
+ uint16_t pitch = rect.width();
+ int width_div_factor = 1;
+ int width_mul_factor = 1;
+ const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, rect.format(), rect.rowpixels(), 0, rect.height(), rect.palette(), rect.base(), pitch, width_div_factor, width_mul_factor);
+ bgfx::updateTexture2D(m_texture_cache->texture(), 0, 0, rect.x(), rect.y(), (rect.width() * width_mul_factor) / width_div_factor, rect.height(), mem, pitch);
}
}
}
@@ -1160,7 +1547,8 @@ uint32_t renderer_bgfx::get_texture_hash(render_primitive *prim)
}
return hash;
#else
- return (reinterpret_cast<size_t>(prim->texture.base)) & 0xffffffff;
+ //return (reinterpret_cast<size_t>(prim->texture.base)) & 0xffffffff;
+ return (reinterpret_cast<size_t>(prim->texture.base) ^ reinterpret_cast<size_t>(prim->texture.palette)) & 0xffffffff;
#endif
}
@@ -1168,9 +1556,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)
@@ -1183,8 +1570,7 @@ bool renderer_bgfx::check_for_dirty_atlas()
atlas_dirty = true;
m_texinfo.push_back(rectangle_packer::packable_rectangle(hash, prim.flags & PRIMFLAG_TEXFORMAT_MASK,
- prim.texture.width, prim.texture.height,
- prim.texture.rowpixels, prim.texture.palette, prim.texture.base));
+ prim.texture.width, prim.texture.height, prim.texture.rowpixels, prim.texture.palette, prim.texture.base));
acquired_infos[hash] = m_texinfo[m_texinfo.size() - 1];
}
}
@@ -1261,11 +1647,44 @@ void renderer_bgfx::set_sliders_dirty()
m_sliders_dirty = true;
}
-uint32_t renderer_bgfx::get_window_width(uint32_t index) const {
- return m_width[index];
+uint32_t renderer_bgfx::get_window_width(uint32_t index) const
+{
+ return s_width[index];
+}
+
+uint32_t renderer_bgfx::get_window_height(uint32_t index) const
+{
+ return s_height[index];
}
-uint32_t renderer_bgfx::get_window_height(uint32_t index) const {
- return m_height[index];
+
+void renderer_bgfx::load_config(util::xml::data_node const &parentnode)
+{
+ util::xml::data_node const *windownode = parentnode.get_child("window");
+ while (windownode)
+ {
+ if (windownode->get_attribute_int("index", -1) != window().index())
+ {
+ 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);
+ m_config->get_first_child()->set_attribute("persist", "0");
+ osd_printf_verbose("BGFX: Found configuration for window %d\n", window().index());
+ break;
+ }
}
+
+void renderer_bgfx::save_config(util::xml::data_node &parentnode)
+{
+ if (m_config)
+ m_config->get_first_child()->copy_into(parentnode);
+ else
+ m_chains->save_config(parentnode);
+}