Fix housemnq crash, nw

This commit is contained in:
therealmogminer@gmail.com 2016-03-22 16:54:01 +01:00
parent 124b4ab8a7
commit c0a67e7310
9 changed files with 196 additions and 92 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<std::string, bgfx_target*> 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<bgfx_target*> to_resize;
for (std::pair<std::string, bgfx_target*> 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<std::string> existing_names;
for (std::pair<std::string, bgfx_target*> 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<bgfx_target*> to_resize;
for (std::pair<std::string, bgfx_target*> 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;
}

View File

@ -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<std::string, bgfx_target*> 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__

View File

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

View File

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