From c0a67e73102f0f21bb4e369a051a01a6df27a89f Mon Sep 17 00:00:00 2001 From: "therealmogminer@gmail.com" Date: Tue, 22 Mar 2016 16:54:01 +0100 Subject: [PATCH] Fix housemnq crash, nw --- src/osd/modules/render/bgfx/chainentry.cpp | 14 +- src/osd/modules/render/bgfx/inputpair.cpp | 5 +- src/osd/modules/render/bgfx/inputpair.h | 3 +- src/osd/modules/render/bgfx/target.cpp | 23 ++- src/osd/modules/render/bgfx/target.h | 4 +- src/osd/modules/render/bgfx/targetmanager.cpp | 186 +++++++++++++----- src/osd/modules/render/bgfx/targetmanager.h | 23 ++- src/osd/modules/render/bgfx/targetreader.cpp | 2 - src/osd/modules/render/drawbgfx.cpp | 28 +-- 9 files changed, 196 insertions(+), 92 deletions(-) diff --git a/src/osd/modules/render/bgfx/chainentry.cpp b/src/osd/modules/render/bgfx/chainentry.cpp index 84dc728af73..3826b4999b2 100644 --- a/src/osd/modules/render/bgfx/chainentry.cpp +++ b/src/osd/modules/render/bgfx/chainentry.cpp @@ -55,7 +55,7 @@ void bgfx_chain_entry::submit(int view, render_primitive* prim, texture_manager& for (bgfx_input_pair input : m_inputs) { - input.bind(m_effect, textures, screen); + input.bind(m_effect, m_targets, textures, screen); } bgfx::TransientVertexBuffer buffer; @@ -74,11 +74,7 @@ void bgfx_chain_entry::submit(int view, render_primitive* prim, texture_manager& m_effect->submit(view, blend); - std::string output_name = m_output; - if (output_name == "output" || output_name == "previous") - { - output_name = output_name + std::to_string(screen); - } + std::string output_name = m_output + std::to_string(screen); if (m_targets.target(output_name) != nullptr) { m_targets.target(output_name)->page_flip(); @@ -158,11 +154,7 @@ bool bgfx_chain_entry::setup_view(int view, uint16_t screen_width, uint16_t scre bgfx::FrameBufferHandle handle = BGFX_INVALID_HANDLE; uint16_t width = screen_width; uint16_t height = screen_height; - std::string output_name = m_output; - if (output_name == "output" || output_name == "previous") - { - output_name = output_name + std::to_string(screen); - } + std::string output_name = m_output + std::to_string(screen); if (m_targets.target(output_name) != nullptr) { bgfx_target* output = m_targets.target(output_name); diff --git a/src/osd/modules/render/bgfx/inputpair.cpp b/src/osd/modules/render/bgfx/inputpair.cpp index 24a4b101c5c..d04c77e8a92 100644 --- a/src/osd/modules/render/bgfx/inputpair.cpp +++ b/src/osd/modules/render/bgfx/inputpair.cpp @@ -17,6 +17,7 @@ #include "effect.h" #include "uniform.h" #include "texturemanager.h" +#include "targetmanager.h" bgfx_input_pair::bgfx_input_pair(int index, std::string sampler, std::string texture) : m_index(index) @@ -25,11 +26,11 @@ bgfx_input_pair::bgfx_input_pair(int index, std::string sampler, std::string tex { } -void bgfx_input_pair::bind(bgfx_effect *effect, texture_manager& textures, const int32_t screen) const +void bgfx_input_pair::bind(bgfx_effect *effect, target_manager& targets, texture_manager& textures, const int32_t screen) const { assert(effect->uniform(m_sampler) != nullptr); std::string texture = m_texture; - if (m_texture == "previous") + if (targets.target(m_texture + std::to_string(screen)) != nullptr) { texture = m_texture + std::to_string(screen); } diff --git a/src/osd/modules/render/bgfx/inputpair.h b/src/osd/modules/render/bgfx/inputpair.h index c4664beb2b9..ad497e89bf2 100644 --- a/src/osd/modules/render/bgfx/inputpair.h +++ b/src/osd/modules/render/bgfx/inputpair.h @@ -18,13 +18,14 @@ class bgfx_effect; class texture_manager; +class target_manager; class bgfx_input_pair { public: bgfx_input_pair(int index, std::string sampler, std::string texture); - void bind(bgfx_effect *effect, texture_manager& textures, const int32_t screen) const; + void bind(bgfx_effect *effect, target_manager& targets, texture_manager& textures, const int32_t screen) const; // Getters std::string sampler() const { return m_sampler; } diff --git a/src/osd/modules/render/bgfx/target.cpp b/src/osd/modules/render/bgfx/target.cpp index e29cbc810d9..a9a8238c0e8 100644 --- a/src/osd/modules/render/bgfx/target.cpp +++ b/src/osd/modules/render/bgfx/target.cpp @@ -6,9 +6,11 @@ // //============================================================ +#include "emu.h" + #include "target.h" -bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, bool double_buffer, bool filter, bool init, bool output) +bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, int32_t index, bool double_buffer, bool filter, bool init, bool output) : m_name(name) , m_format(format) , m_targets(nullptr) @@ -21,7 +23,8 @@ bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uin , m_style(style) , m_filter(filter) , m_output(output) - , m_current_page(0) + , m_index(index) + , m_current_page(0) , m_initialized(false) , m_page_count(double_buffer ? 2 : 1) { @@ -35,8 +38,10 @@ bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uin for (int page = 0; page < m_page_count; page++) { m_textures[page] = bgfx::createTexture2D(width * prescale_x, height * prescale_y, 1, format, wrap_mode | filter_mode | BGFX_TEXTURE_RT); + assert(m_textures[page].idx != 0xffff); m_targets[page] = bgfx::createFrameBuffer(1, &m_textures[page], false); - } + assert(m_targets[page].idx != 0xffff); + } m_initialized = true; } @@ -55,7 +60,8 @@ bgfx_target::bgfx_target(void *handle, uint16_t width, uint16_t height) , m_style(TARGET_STYLE_CUSTOM) , m_filter(false) , m_current_page(0) - , m_initialized(true) + , m_index(-1) + , m_initialized(true) , m_page_count(0) { m_targets = new bgfx::FrameBufferHandle[1]; @@ -66,15 +72,18 @@ bgfx_target::bgfx_target(void *handle, uint16_t width, uint16_t height) bgfx_target::~bgfx_target() { - if (!m_initialized) return; + if (!m_initialized) + { + return; + } if (m_page_count > 0) { for (int page = 0; page < m_page_count; page++) { bgfx::destroyFrameBuffer(m_targets[page]); - bgfx::destroyTexture(m_textures[page]); - } + bgfx::destroyTexture(m_textures[page]); + } delete [] m_textures; delete [] m_targets; } diff --git a/src/osd/modules/render/bgfx/target.h b/src/osd/modules/render/bgfx/target.h index ad8efbde2cb..a80db0f8789 100644 --- a/src/osd/modules/render/bgfx/target.h +++ b/src/osd/modules/render/bgfx/target.h @@ -27,7 +27,7 @@ enum class bgfx_target : public bgfx_texture_handle_provider { public: - bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, bool double_buffer, bool filter, bool init = true, bool output = false); + bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, int32_t index, bool double_buffer, bool filter, bool init = true, bool output = false); bgfx_target(void *handle, uint16_t width, uint16_t height); virtual ~bgfx_target(); @@ -43,6 +43,7 @@ public: uint32_t prescale_x() const { return m_prescale_x; } uint32_t prescale_y() const { return m_prescale_y; } bool output() const { return m_output; } + int32_t index() const { return m_index; } // bgfx_texture_handle_provider virtual uint16_t width() const override { return m_width; } @@ -67,6 +68,7 @@ private: uint32_t m_style; bool m_filter; bool m_output; + int32_t m_index; uint32_t m_current_page; diff --git a/src/osd/modules/render/bgfx/targetmanager.cpp b/src/osd/modules/render/bgfx/targetmanager.cpp index 3e5828efabc..185a99a2fb7 100644 --- a/src/osd/modules/render/bgfx/targetmanager.cpp +++ b/src/osd/modules/render/bgfx/targetmanager.cpp @@ -19,18 +19,36 @@ #include "target.h" +const int32_t target_manager::MAX_SCREENS = 100; + +target_manager::target_manager(osd_options& options, texture_manager& textures) + : m_textures(textures) + , m_options(options) + , m_screen_count(0) +{ + m_guest_width = new uint16_t[MAX_SCREENS]; + m_guest_height = new uint16_t[MAX_SCREENS]; + memset(m_guest_width, 0, sizeof(uint16_t) * MAX_SCREENS); + memset(m_guest_height, 0, sizeof(uint16_t) * MAX_SCREENS); +} + target_manager::~target_manager() { for (std::pair target : m_targets) { - delete target.second; + if (target.second != nullptr) + { + delete target.second; + } } m_targets.clear(); + delete [] m_guest_width; + delete [] m_guest_height; } bgfx_target* target_manager::create_target(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, bool double_buffer, bool filter, bool output) { - bgfx_target* target = new bgfx_target(name, format, width, height, prescale_x, prescale_y, style, double_buffer, filter, width > 0 && height > 0, output); + bgfx_target* target = new bgfx_target(name, format, width, height, prescale_x, prescale_y, style, -1, double_buffer, filter, width > 0 && height > 0, output); m_targets[name] = target; m_textures.add_provider(name, target); @@ -55,62 +73,140 @@ bgfx_target* target_manager::target(std::string name) return nullptr; } -void target_manager::update_guest_targets(uint16_t width, uint16_t height) +void target_manager::update_guest_targets(int32_t screen, uint16_t width, uint16_t height) { - if (width != m_guest_width || height != m_guest_height) + if (screen < 0 || screen >= MAX_SCREENS) + { + return; + } + + if (width != m_guest_width[screen] || height != m_guest_height[screen]) { - m_guest_width = width; - m_guest_height = height; - - std::vector to_resize; - for (std::pair target : m_targets) - { - if ((target.second)->style() == TARGET_STYLE_GUEST) - { - to_resize.push_back(target.second); - } - } - - for (bgfx_target* target : to_resize) - { - std::string name = target->name(); - const bgfx::TextureFormat::Enum format = target->format(); - const bool double_buffered = target->double_buffered(); - const bool filter = target->filter(); - const uint32_t prescale_x = target->prescale_x(); - const uint32_t prescale_y = target->prescale_y(); - delete target; - - m_targets[name] = new bgfx_target(name, format, m_guest_width, m_guest_height, prescale_x, prescale_y, TARGET_STYLE_GUEST, double_buffered, filter); - m_textures.add_provider(name, m_targets[name]); - } + m_guest_width[screen] = width; + m_guest_height[screen] = height; + ensure_guest_targets(); + rebuild_guest_targets(screen); } } -void target_manager::update_window_count(uint32_t count) +void target_manager::ensure_guest_targets() { - if (count != m_window_count) + // Build a list of all guest targets that end in 0 *or* don't end in a number + std::vector existing_names; + for (std::pair target_pair : m_targets) { - m_window_count = count; - rebuild_outputs(); + bgfx_target* target = target_pair.second; + if (target == nullptr || target->style() != TARGET_STYLE_GUEST) + { + continue; + } + + // If the last character is not a digit, add it to the list + std::string name = target->name(); + char last_char = name[name.length() - 1]; + if ((last_char & 0xf0) != 0x30) { + existing_names.push_back(name); + } + + // If the last character is a zero, and the stripped name isn't already in the list, strip it off and add it to the list + if (last_char == 0x30) + { + std::string shortened_name = name.substr(0, name.length() - 1); + bool exists = false; + for (std::string other_name : existing_names) + { + if (other_name == shortened_name) + { + exists = true; + break; + } + } + if (!exists) + { + existing_names.push_back(shortened_name); + } + } + } + + for (std::string name : existing_names) + { + create_nonexistent_targets(name); } } -void target_manager::rebuild_outputs() +void target_manager::rebuild_guest_targets(int32_t screen) { - for (uint32_t i = 0; i < m_window_count; i++) - { - rebuild_target("output" + std::to_string(i)); - rebuild_target("previous" + std::to_string(i)); + std::vector to_resize; + for (std::pair target : m_targets) { + bgfx_target* target_ptr = target.second; + if (target_ptr == nullptr) { + continue; + } + bool is_guest = target_ptr->style() == TARGET_STYLE_GUEST; + bool is_desired_screen = target_ptr->index() == screen || target_ptr->index() == -1; + std::string name = target_ptr->name(); + bool is_indexed = (name[name.length() - 1] & 0xf0) == 0x30; + if (is_guest && is_desired_screen && is_indexed) { + to_resize.push_back(target.second); + } } -} -void target_manager::rebuild_target(std::string name) -{ - bgfx_target* target = m_targets[name]; - if (target != nullptr) { + for (bgfx_target* target : to_resize) { + std::string name = target->name(); + const bgfx::TextureFormat::Enum format = target->format(); + const bool double_buffered = target->double_buffered(); + const bool filter = target->filter(); + const uint32_t prescale_x = target->prescale_x(); + const uint32_t prescale_y = target->prescale_y(); delete target; + + const uint16_t width = m_guest_width[screen]; + const uint16_t height = m_guest_height[screen]; + const bool init = width > 0 && height > 0; + m_targets[name] = new bgfx_target(name, format, width, height, prescale_x, prescale_y, TARGET_STYLE_GUEST, screen, double_buffered, filter, init); + m_textures.add_provider(name, m_targets[name]); } - m_targets[name] = new bgfx_target(name, bgfx::TextureFormat::RGBA8, m_guest_width, m_guest_height, m_options.bgfx_prescale_x(), m_options.bgfx_prescale_y(), TARGET_STYLE_GUEST, true, true); - m_textures.add_provider(name, m_targets[name]); +} + +void target_manager::update_screen_count(uint32_t count) +{ + if (count != m_screen_count) + { + uint32_t old_count = m_screen_count; + m_screen_count = count; + if (m_screen_count > old_count) + { + create_nonexistent_targets("output"); + create_nonexistent_targets("previous"); + } + } +} + +void target_manager::create_nonexistent_targets(std::string name) +{ + bool double_buffered = true; + bool filter = true; + if (m_targets[name + "0"] != nullptr) + { + double_buffered = m_targets[name + "0"]->double_buffered(); + filter = m_targets[name + "0"]->filter(); + } + + for (uint32_t screen = 0; screen < m_screen_count; screen++) + { + create_guest_if_nonexistent(name, screen, double_buffered, filter); + } +} + +bool target_manager::create_guest_if_nonexistent(std::string name, int32_t screen, bool double_buffered, bool filter) +{ + std::string full_name = name + std::to_string(screen); + if (m_targets[full_name] != nullptr) + { + return false; + } + + bool init = m_guest_width[screen] > 0 && m_guest_height[screen] > 0; + m_targets[full_name] = new bgfx_target(full_name, bgfx::TextureFormat::RGBA8, m_guest_width[screen], m_guest_height[screen], m_options.bgfx_prescale_x(), m_options.bgfx_prescale_y(), TARGET_STYLE_GUEST, screen, double_buffered, filter, init); + return true; } \ No newline at end of file diff --git a/src/osd/modules/render/bgfx/targetmanager.h b/src/osd/modules/render/bgfx/targetmanager.h index f017119502c..23186f16ad5 100644 --- a/src/osd/modules/render/bgfx/targetmanager.h +++ b/src/osd/modules/render/bgfx/targetmanager.h @@ -26,31 +26,36 @@ class osd_options; class target_manager { public: - target_manager(osd_options& options, texture_manager& textures) : m_textures(textures), m_options(options), m_guest_width(0), m_guest_height(0), m_window_count(0) { } + target_manager(osd_options& options, texture_manager& textures); ~target_manager(); bgfx_target* create_target(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, bool double_buffer, bool filter, bool output); bgfx_target* create_backbuffer(void *handle, uint32_t width, uint32_t height); - void update_guest_targets(uint16_t width, uint16_t height); - void update_window_count(uint32_t count); + void update_guest_targets(int32_t screen, uint16_t width, uint16_t height); + void update_screen_count(uint32_t count); // Getters bgfx_target* target(std::string name); - uint16_t guest_width() const { return m_guest_width; } - uint16_t guest_height() const { return m_guest_height; } + uint16_t guest_width(int32_t screen) const { return m_guest_width[screen]; } + uint16_t guest_height(int32_t screen) const { return m_guest_height[screen]; } private: + void rebuild_guest_targets(int32_t screen); void rebuild_outputs(); - void rebuild_target(std::string name); + void ensure_guest_targets(); + void create_nonexistent_targets(std::string name); + bool create_guest_if_nonexistent(std::string name, int32_t screen, bool double_buffered, bool filter); std::map m_targets; texture_manager& m_textures; osd_options& m_options; - uint16_t m_guest_width; - uint16_t m_guest_height; - uint32_t m_window_count; + uint16_t *m_guest_width; + uint16_t *m_guest_height; + uint32_t m_screen_count; + + static const int32_t MAX_SCREENS; }; #endif // __DRAWBGFX_TARGET_MANAGER__ diff --git a/src/osd/modules/render/bgfx/targetreader.cpp b/src/osd/modules/render/bgfx/targetreader.cpp index 1f375155751..0ce1e76335f 100644 --- a/src/osd/modules/render/bgfx/targetreader.cpp +++ b/src/osd/modules/render/bgfx/targetreader.cpp @@ -40,8 +40,6 @@ bool target_reader::read_from_value(const Value& value, std::string prefix, targ switch (mode) { case TARGET_STYLE_GUEST: - width = targets.guest_width(); - height = targets.guest_height(); break; case TARGET_STYLE_NATIVE: width = screen_width; diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp index a2cd2092168..ccfd6cdd642 100644 --- a/src/osd/modules/render/drawbgfx.cpp +++ b/src/osd/modules/render/drawbgfx.cpp @@ -331,7 +331,7 @@ void renderer_bgfx::put_packed_quad(render_primitive *prim, UINT32 hash, ScreenV vertex[5].m_v = v[0]; } -void renderer_bgfx::process_screen_quad(int view, render_primitive* prim) +void renderer_bgfx::process_screen_quad(int screen, render_primitive* prim) { uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP; if (video_config.filter == 0) @@ -348,16 +348,9 @@ void renderer_bgfx::process_screen_quad(int view, render_primitive* prim) bgfx_texture *texture = new bgfx_texture("screen", bgfx::TextureFormat::RGBA8, tex_width, tex_height, mem); m_textures->add_provider("screen", texture); - int screens = 0; - screen_device_iterator iter(window().machine().root_device()); - for (const screen_device *screen = iter.first(); screen != nullptr; screen = iter.next()) - { - screens++; - } - m_targets->update_guest_targets(tex_width, tex_height); - m_targets->update_window_count(screens); + m_targets->update_guest_targets(screen, tex_width, tex_height); - m_screen_chain->process(prim, view, view / m_screen_chain->applicable_passes(), *m_textures, window(), get_blend_state(PRIMFLAG_GET_BLENDMODE(prim->flags))); + m_screen_chain->process(prim, screen * m_screen_chain->applicable_passes(), screen, *m_textures, window(), get_blend_state(PRIMFLAG_GET_BLENDMODE(prim->flags))); m_textures->add_provider("screen", nullptr); delete texture; @@ -744,20 +737,27 @@ int renderer_bgfx::handle_screen_chains() // process render_primitive *prim = window().m_primlist->first(); - int seen = 0; + int screens = 0; + screen_device_iterator iter(window().machine().root_device()); + for (const screen_device *screen = iter.first(); screen != nullptr; screen = iter.next()) { + screens++; + } + m_targets->update_screen_count(screens); + + int seen_screen_quads = 0; while (prim != nullptr) { if (PRIMFLAG_GET_SCREENTEX(prim->flags)) { - process_screen_quad(m_screen_chain->applicable_passes() * seen, prim); - seen++; + process_screen_quad(seen_screen_quads, prim); + seen_screen_quads++; } prim = prim->next(); } window().m_primlist->release_lock(); - uint32_t total_passes = seen * m_screen_chain->applicable_passes(); + uint32_t total_passes = seen_screen_quads * m_screen_chain->applicable_passes(); bgfx::setViewFrameBuffer(total_passes, BGFX_INVALID_HANDLE); return total_passes;