diff options
Diffstat (limited to 'src')
112 files changed, 3964 insertions, 987 deletions
diff --git a/src/emu/ui/dsplmenu.cpp b/src/emu/ui/dsplmenu.cpp index 5ee2bfd0ca2..5c745e40383 100644 --- a/src/emu/ui/dsplmenu.cpp +++ b/src/emu/ui/dsplmenu.cpp @@ -44,7 +44,6 @@ ui_menu_display_options::dspl_option ui_menu_display_options::m_options[] = { { 0, __("GLSL"), OSDOPTION_GL_GLSL }, { 0, __("Bilinear Filtering"), OSDOPTION_FILTER }, { 0, __("Bitmap Prescaling"), OSDOPTION_PRESCALE }, - { 0, __("Multi-Threaded Rendering"), OSDOPTION_MULTITHREADING }, { 0, __("Window Mode"), OSDOPTION_WINDOW }, { 0, __("Enforce Aspect Ratio"), OSDOPTION_KEEPASPECT }, { 0, __("Start Out Maximized"), OSDOPTION_MAXIMIZE }, diff --git a/src/emu/ui/sliders.cpp b/src/emu/ui/sliders.cpp index b339eaef37b..86f85bd0026 100644 --- a/src/emu/ui/sliders.cpp +++ b/src/emu/ui/sliders.cpp @@ -108,20 +108,14 @@ void ui_menu_sliders::handle() /* if we got here via up or page up, select the previous item */ if (menu_event->iptkey == IPT_UI_UP || menu_event->iptkey == IPT_UI_PAGE_UP) { - do - { - selected = (selected + item.size() - 1) % item.size(); - } while(((slider_state&)item[selected]).hidden); - validate_selection(-1); + selected = (selected + item.size() - 1) % item.size(); + validate_selection(-1); } /* otherwise select the next item */ else if (menu_event->iptkey == IPT_UI_DOWN || menu_event->iptkey == IPT_UI_PAGE_DOWN) { - do - { - selected = (selected + 1) % item.size(); - } while(((slider_state&)item[selected]).hidden); + selected = (selected + 1) % item.size(); validate_selection(1); } } diff --git a/src/emu/ui/ui.cpp b/src/emu/ui/ui.cpp index 549784cf971..cc8b18c8154 100644 --- a/src/emu/ui/ui.cpp +++ b/src/emu/ui/ui.cpp @@ -1941,7 +1941,6 @@ static slider_state *slider_alloc(running_machine &machine, const char *title, I state->incval = incval; state->update = update; state->arg = arg; - state->hidden = false; state->id = -1; strcpy(state->description, title); diff --git a/src/emu/ui/ui.h b/src/emu/ui/ui.h index 1e7751e8118..c50d444120e 100644 --- a/src/emu/ui/ui.h +++ b/src/emu/ui/ui.h @@ -103,8 +103,7 @@ struct slider_state INT32 defval; /* default value */ INT32 maxval; /* maximum value */ INT32 incval; /* increment value */ - bool hidden; /* hidden or not */ - INT32 id; /* unique identifier */ + int id; char description[1]; /* textual description */ }; diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index 30c77a12211..abbb9241049 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -42,7 +42,6 @@ const options_entry osd_options::s_option_entries[] = { OSDOPTION_WATCHDOG ";wdog", "0", OPTION_INTEGER, "force the program to terminate if no updates within specified number of seconds" }, { nullptr, nullptr, OPTION_HEADER, "OSD PERFORMANCE OPTIONS" }, - { OSDOPTION_MULTITHREADING ";mt", "0", OPTION_BOOLEAN, "enable multithreading; this enables rendering and blitting on a separate thread" }, { OSDOPTION_NUMPROCESSORS ";np", OSDOPTVAL_AUTO, OPTION_STRING, "number of processors; this overrides the number the system reports" }, { OSDOPTION_BENCH, "0", OPTION_INTEGER, "benchmark for the given number of emulated seconds; implies -video none -sound none -nothrottle" }, @@ -141,7 +140,16 @@ const options_entry osd_options::s_option_entries[] = { OSDOPTION_AUDIO_EFFECT "9", OSDOPTVAL_NONE, OPTION_STRING, "AudioUnit effect 9" }, #endif - // End of list + { nullptr, nullptr, OPTION_HEADER, "BGFX POST-PROCESSING OPTIONS" }, + { OSDOPTION_BGFX_PATH, "bgfx", OPTION_STRING, "path to BGFX-related files" }, + { OSDOPTION_BGFX_BACKEND, "auto", OPTION_STRING, "BGFX backend to use (d3d9, d3d11, metal, opengl, gles)" }, + { OSDOPTION_BGFX_DEBUG, "0", OPTION_BOOLEAN, "enable BGFX debugging statistics" }, + { OSDOPTION_BGFX_SCREEN_CHAIN, "default", OPTION_STRING, "screen chain JSON file to use" }, + { OSDOPTION_BGFX_SHADOW_MASK, "shadow-mask.png", OPTION_STRING, "shadow mask texture name" }, + { OSDOPTION_BGFX_PRESCALE_X, "2", OPTION_INTEGER, "x prescale" }, + { OSDOPTION_BGFX_PRESCALE_Y, "2", OPTION_INTEGER, "y prescale" }, + + // End of list { nullptr } }; @@ -516,7 +524,6 @@ void osd_common_t::customize_input_type_list(simple_list<input_type_entry> &type slider_state* osd_common_t::get_slider_list() { - printf("Core get_slider_list\n"); return nullptr; } diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h index 27e8d29d4a5..0b08745a22d 100644 --- a/src/osd/modules/lib/osdobj_common.h +++ b/src/osd/modules/lib/osdobj_common.h @@ -37,7 +37,6 @@ #define OSDOPTION_DEBUGGER_FONT_SIZE "debugger_font_size" #define OSDOPTION_WATCHDOG "watchdog" -#define OSDOPTION_MULTITHREADING "multithreading" #define OSDOPTION_NUMPROCESSORS "numprocessors" #define OSDOPTION_BENCH "bench" @@ -78,7 +77,13 @@ #define OSDOPTVAL_AUTO "auto" #define OSDOPTVAL_NONE "none" - +#define OSDOPTION_BGFX_PATH "bgfx_path" +#define OSDOPTION_BGFX_BACKEND "bgfx_backend" +#define OSDOPTION_BGFX_DEBUG "bgfx_debug" +#define OSDOPTION_BGFX_SCREEN_CHAIN "bgfx_screen_chain" +#define OSDOPTION_BGFX_SHADOW_MASK "bgfx_shadow_mask" +#define OSDOPTION_BGFX_PRESCALE_X "bgfx_prescale_x" +#define OSDOPTION_BGFX_PRESCALE_Y "bgfx_prescale_y" //============================================================ // TYPE DEFINITIONS @@ -100,7 +105,6 @@ public: int watchdog() const { return int_value(OSDOPTION_WATCHDOG); } // performance options - bool multithreading() const { return bool_value(OSDOPTION_MULTITHREADING); } const char *numprocessors() const { return value(OSDOPTION_NUMPROCESSORS); } int bench() const { return int_value(OSDOPTION_BENCH); } @@ -149,6 +153,15 @@ public: const char *audio_output() const { return value(OSDOPTION_AUDIO_OUTPUT); } const char *audio_effect(int index) const { return value(string_format("%s%d", OSDOPTION_AUDIO_EFFECT, index).c_str()); } + // BGFX specific options + const char *bgfx_path() const { return value(OSDOPTION_BGFX_PATH); } + const char *bgfx_backend() const { return value(OSDOPTION_BGFX_BACKEND); } + const bool bgfx_debug() const { return bool_value(OSDOPTION_BGFX_DEBUG); } + const char *bgfx_screen_chain() const { return value(OSDOPTION_BGFX_SCREEN_CHAIN); } + const char *bgfx_shadow_mask() const { return value(OSDOPTION_BGFX_SHADOW_MASK); } + const uint32_t bgfx_prescale_x() const { return int_value(OSDOPTION_BGFX_PRESCALE_X); } + const uint32_t bgfx_prescale_y() const { return int_value(OSDOPTION_BGFX_PRESCALE_Y); } + private: static const options_entry s_option_entries[]; }; @@ -231,6 +244,9 @@ protected: virtual bool input_init(); virtual void input_pause(); + virtual void build_slider_list() { } + virtual void update_slider_list() { } + private: // internal state running_machine * m_machine; diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h index 6081d47c010..3d46a273569 100644 --- a/src/osd/modules/osdwindow.h +++ b/src/osd/modules/osdwindow.h @@ -235,6 +235,7 @@ public: virtual void record() { }; virtual void toggle_fsfx() { }; virtual bool sliders_dirty() { return m_sliders_dirty; } + virtual bool multi_window_sliders() { return false; } static osd_renderer* make_for_type(int mode, osd_window *window, int extra_flags = FLAG_NONE); diff --git a/src/osd/modules/render/bgfx/chain.cpp b/src/osd/modules/render/bgfx/chain.cpp index 6827864df7e..44cc000c8fa 100644 --- a/src/osd/modules/render/bgfx/chain.cpp +++ b/src/osd/modules/render/bgfx/chain.cpp @@ -6,9 +6,16 @@ // //============================================================ +#include "emu.h" + +#include <bx/timer.h> + #include "slider.h" #include "parameter.h" -#include "chainentry.h" +#include "entryuniform.h" +#include "texturemanager.h" +#include "vertex.h" +#include "window.h" #include "chain.h" @@ -18,7 +25,12 @@ bgfx_chain::bgfx_chain(std::string name, std::string author, std::vector<bgfx_sl , m_sliders(sliders) , m_params(params) , m_entries(entries) + , m_current_time(0) { + for (bgfx_slider* slider : m_sliders) + { + m_slider_map[slider->name()] = slider; + } } bgfx_chain::~bgfx_chain() @@ -37,9 +49,52 @@ bgfx_chain::~bgfx_chain() } } -void bgfx_chain::submit(render_primitive* prim, int view) +void bgfx_chain::process(render_primitive* prim, int view, int screen, texture_manager& textures, osd_window& window, uint64_t blend) { - //for (bgfx_chain_entry* entry : m_entries) - //{ - //} + int current_view = view; + uint16_t screen_width = window.get_size().width(); + uint16_t screen_height = window.get_size().height(); + uint32_t rotation_type = (window.target()->orientation() & ROT90) == ROT90 ? + 1 : (window.target()->orientation() & ROT180) == ROT180 ? + 2 : (window.target()->orientation() & ROT270) == ROT270 ? + 3 : 0; + bool orientation_swap_xy = (window.machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; + bool rotation_swap_xy = (window.target()->orientation() & ROT90) == ROT90 || (window.target()->orientation() & ROT270) == ROT270; + bool swap_xy = orientation_swap_xy ^ rotation_swap_xy; + + for (bgfx_chain_entry* entry : m_entries) + { + if (!entry->skip()) + { + entry->submit(current_view, prim, textures, screen_width, screen_height, rotation_type, swap_xy, blend, screen); + current_view++; + } + } + + m_current_time = bx::getHPCounter(); + static int64_t last = m_current_time; + const int64_t frameTime = m_current_time - last; + last = m_current_time; + const double freq = double(bx::getHPFrequency()); + const double toMs = 1000.0 / freq; + const double frameTimeInSeconds = (double)frameTime / 1000000.0; + + for (bgfx_parameter* param : m_params) + { + param->tick(frameTimeInSeconds* toMs); + } } + +uint32_t bgfx_chain::applicable_passes() +{ + int applicable_passes = 0; + for (bgfx_chain_entry* entry : m_entries) + { + if (!entry->skip()) + { + applicable_passes++; + } + } + + return applicable_passes; +}
\ No newline at end of file diff --git a/src/osd/modules/render/bgfx/chain.h b/src/osd/modules/render/bgfx/chain.h index 7721bbaf74b..13283f9ba08 100644 --- a/src/osd/modules/render/bgfx/chain.h +++ b/src/osd/modules/render/bgfx/chain.h @@ -13,11 +13,15 @@ #include <string> #include <vector> +#include <map> +#include "chainentry.h" + +class render_primitive; class bgfx_slider; class bgfx_parameter; -class bgfx_chain_entry; -class render_primitive; +class texture_manager; +class osd_window; class bgfx_chain { @@ -25,14 +29,20 @@ public: bgfx_chain(std::string name, std::string author, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries); ~bgfx_chain(); - void submit(render_primitive* prim, int view); + void process(render_primitive* prim, int view, int screen, texture_manager& textures, osd_window &window, uint64_t blend = 0L); + + // Getters + std::vector<bgfx_slider*>& sliders() { return m_sliders; } + uint32_t applicable_passes(); private: - std::string m_name; - std::string m_author; - std::vector<bgfx_slider*> m_sliders; - std::vector<bgfx_parameter*> m_params; - std::vector<bgfx_chain_entry*> m_entries; + std::string m_name; + std::string m_author; + std::vector<bgfx_slider*> m_sliders; + std::vector<bgfx_parameter*> m_params; + std::vector<bgfx_chain_entry*> m_entries; + std::map<std::string, bgfx_slider*> m_slider_map; + int64_t m_current_time; }; #endif // __DRAWBGFX_CHAIN__ diff --git a/src/osd/modules/render/bgfx/chainentry.cpp b/src/osd/modules/render/bgfx/chainentry.cpp index c0b8845cdd3..526b40a978d 100644 --- a/src/osd/modules/render/bgfx/chainentry.cpp +++ b/src/osd/modules/render/bgfx/chainentry.cpp @@ -12,33 +12,271 @@ #include "emu.h" #include <bgfx/bgfx.h> +#include <bx/fpumath.h> + +#include "chainentry.h" #include "effect.h" #include "texture.h" #include "target.h" -#include "chainentry.h" +#include "entryuniform.h" +#include "texturemanager.h" +#include "vertex.h" +#include "suppressor.h" -bgfx_chain_entry::bgfx_chain_entry(std::string name, bgfx_effect* effect, std::vector<bgfx_input_pair>& inputs, bgfx_target* output) +bgfx_chain_entry::bgfx_chain_entry(std::string name, bgfx_effect* effect, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output) : m_name(name) , m_effect(effect) - , m_output(output) + , m_suppressors(suppressors) + , m_inputs(inputs) + , m_uniforms(uniforms) + , m_targets(targets) + , m_output(output) +{ +} + +bgfx_chain_entry::~bgfx_chain_entry() { - for (bgfx_input_pair input : inputs) + for (bgfx_entry_uniform* uniform : m_uniforms) { - m_inputs.push_back(input); + delete uniform; } + m_uniforms.clear(); } -bgfx_chain_entry::~bgfx_chain_entry() +void bgfx_chain_entry::submit(int view, render_primitive* prim, texture_manager& textures, uint16_t screen_width, uint16_t screen_height, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen) +{ + bgfx::setViewSeq(view, true); + + if (!setup_view(view, screen_width, screen_height, screen)) + { + return; + } + + for (bgfx_input_pair input : m_inputs) + { + input.bind(m_effect, textures, screen); + } + + bgfx::TransientVertexBuffer buffer; + put_screen_buffer(prim, &buffer); + bgfx::setVertexBuffer(&buffer); + + setup_auto_uniforms(prim, textures, screen_width, screen_height, rotation_type, swap_xy); + + for (bgfx_entry_uniform* uniform : m_uniforms) + { + if (uniform->name() != "s_tex") + { + uniform->bind(); + } + } + + 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); + } + if (m_targets.target(output_name) != nullptr) + { + m_targets.target(output_name)->page_flip(); + } +} + +void bgfx_chain_entry::setup_screensize_uniforms(texture_manager& textures, uint16_t screen_width, uint16_t screen_height) +{ + float width = screen_width; + float height = screen_height; + if (m_inputs.size() > 0) + { + width = float(textures.provider(m_inputs[0].texture())->width()); + height = float(textures.provider(m_inputs[0].texture())->height()); + } + + bgfx_uniform* screen_dims = m_effect->uniform("u_screen_dims"); + if (screen_dims != nullptr) + { + float values[2] = { width, height }; + screen_dims->set(values, sizeof(float) * 2); + } + + bgfx_uniform* inv_screen_dims = m_effect->uniform("u_inv_screen_dims"); + if (inv_screen_dims != nullptr) + { + float values[2] = { 1.0f / width, 1.0f / height }; + inv_screen_dims->set(values, sizeof(float) * 2); + } +} + +void bgfx_chain_entry::setup_sourcesize_uniform(render_primitive* prim) +{ + bgfx_uniform* source_dims = m_effect->uniform("u_source_dims"); + if (source_dims != nullptr) + { + float values[2] = { float(prim->texture.width), float(prim->texture.height) }; + source_dims->set(values, sizeof(float) * 2); + } +} + +void bgfx_chain_entry::setup_rotationtype_uniform(uint32_t rotation_type) +{ + bgfx_uniform* rotation_type_uniform = m_effect->uniform("u_rotation_type"); + if (rotation_type_uniform != nullptr) + { + float values[1] = { float(rotation_type) }; + rotation_type_uniform->set(values, sizeof(float)); + } +} + +void bgfx_chain_entry::setup_swapxy_uniform(bool swap_xy) +{ + bgfx_uniform* swap_xy_uniform = m_effect->uniform("u_swap_xy"); + if (swap_xy_uniform != nullptr) + { + float values[1] = { swap_xy ? 1.0f : 0.0f }; + swap_xy_uniform->set(values, sizeof(float)); + } +} + +void bgfx_chain_entry::setup_auto_uniforms(render_primitive* prim, texture_manager& textures, uint16_t screen_width, uint16_t screen_height, uint32_t rotation_type, bool swap_xy) { + setup_screensize_uniforms(textures, screen_width, screen_height); + setup_sourcesize_uniform(prim); + setup_rotationtype_uniform(rotation_type); + setup_swapxy_uniform(swap_xy); +} + +bool bgfx_chain_entry::setup_view(int view, uint16_t screen_width, uint16_t screen_height, int32_t screen) +{ + 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); + } + if (m_targets.target(output_name) != nullptr) + { + bgfx_target* output = m_targets.target(output_name); + if (output->width() == 0) + { + return false; + } + handle = output->target(); + width = output->width() * output->prescale_x(); + height = output->height() * output->prescale_y(); + } + + bgfx::setViewFrameBuffer(view, handle); + bgfx::setViewRect(view, 0, 0, width, height); + + float projMat[16]; + bx::mtxOrtho(projMat, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f); + bgfx::setViewTransform(view, nullptr, projMat); + + bgfx::setViewClear(view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0); + return true; } -void bgfx_chain_entry::submit(render_primitive* prim, int view) +void bgfx_chain_entry::put_screen_buffer(render_primitive* prim, bgfx::TransientVertexBuffer* buffer) { - for (bgfx_input_pair input : m_inputs) + if (bgfx::checkAvailTransientVertexBuffer(6, ScreenVertex::ms_decl)) + { + bgfx::allocTransientVertexBuffer(buffer, 6, ScreenVertex::ms_decl); + } + else + { + return; + } + + ScreenVertex* vertex = reinterpret_cast<ScreenVertex*>(buffer->data); + + float x[4] = { 0, 1, 0, 1 }; + float y[4] = { 0, 0, 1, 1 }; + float u[4] = { 0, 1, 0, 1 }; + float v[4] = { 0, 0, 1, 1 }; + + bgfx::RendererType::Enum renderer_type = bgfx::getRendererType(); + if (renderer_type == bgfx::RendererType::OpenGL || renderer_type == bgfx::RendererType::OpenGLES) { - input.bind(m_effect); + v[0] = v[1] = 1; + v[2] = v[3] = 0; } - bgfx::setViewFrameBuffer(view, m_output->target()); - m_effect->submit(view); + + vertex[0].m_x = x[0]; + vertex[0].m_y = y[0]; + vertex[0].m_z = 0; + vertex[0].m_rgba = 0xffffffff; + vertex[0].m_u = u[0]; + vertex[0].m_v = v[0]; + + vertex[1].m_x = x[1]; + vertex[1].m_y = y[1]; + vertex[1].m_z = 0; + vertex[1].m_rgba = 0xffffffff; + vertex[1].m_u = u[1]; + vertex[1].m_v = v[1]; + + vertex[2].m_x = x[3]; + vertex[2].m_y = y[3]; + vertex[2].m_z = 0; + vertex[2].m_rgba = 0xffffffff; + vertex[2].m_u = u[3]; + vertex[2].m_v = v[3]; + + vertex[3].m_x = x[3]; + vertex[3].m_y = y[3]; + vertex[3].m_z = 0; + vertex[3].m_rgba = 0xffffffff; + vertex[3].m_u = u[3]; + vertex[3].m_v = v[3]; + + vertex[4].m_x = x[2]; + vertex[4].m_y = y[2]; + vertex[4].m_z = 0; + vertex[4].m_rgba = 0xffffffff; + vertex[4].m_u = u[2]; + vertex[4].m_v = v[2]; + + vertex[5].m_x = x[0]; + vertex[5].m_y = y[0]; + vertex[5].m_z = 0; + vertex[5].m_rgba = 0xffffffff; + vertex[5].m_u = u[0]; + vertex[5].m_v = v[0]; } + +bool bgfx_chain_entry::skip() +{ + if (m_suppressors.size() == 0) + { + return false; + } + + // Group all AND/OR'd results together and OR them together (hack for now) + // TODO: Make this a bit more logical + + bool or_suppress = false; + int and_count = 0; + int and_suppressed = 0; + for (bgfx_suppressor* suppressor : m_suppressors) + { + if (suppressor->combine() == bgfx_suppressor::combine_mode::COMBINE_AND) + { + and_count++; + if (suppressor->suppress()) + { + and_suppressed++; + } + } + else if (suppressor->combine() == bgfx_suppressor::combine_mode::COMBINE_OR) + { + or_suppress |= suppressor->suppress(); + } + } + + return (and_count != 0 && and_suppressed == and_count) || or_suppress; +}
\ No newline at end of file diff --git a/src/osd/modules/render/bgfx/chainentry.h b/src/osd/modules/render/bgfx/chainentry.h index 83a615d28a5..15606ae8b79 100644 --- a/src/osd/modules/render/bgfx/chainentry.h +++ b/src/osd/modules/render/bgfx/chainentry.h @@ -14,32 +14,51 @@ #ifndef __DRAWBGFX_CHAIN_ENTRY__ #define __DRAWBGFX_CHAIN_ENTRY__ +#include <bgfx/bgfx.h> + #include <string> #include <vector> #include "inputpair.h" +#include "targetmanager.h" class render_primitive; class bgfx_effect; -class bgfx_texture; class bgfx_target; +class bgfx_entry_uniform; +class bgfx_suppressor; +class texture_manager; +class target_manager; class bgfx_chain_entry { public: - bgfx_chain_entry(std::string name, bgfx_effect* effect, std::vector<bgfx_input_pair>& inputs, bgfx_target* output); + bgfx_chain_entry(std::string name, bgfx_effect* effect, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output); ~bgfx_chain_entry(); - void submit(render_primitive* prim, int view); + void submit(int view, render_primitive* prim, texture_manager& textures, uint16_t screen_width, uint16_t screen_height, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen); // Getters std::string name() const { return m_name; } + bool skip(); private: - std::string m_name; - bgfx_effect* m_effect; - std::vector<bgfx_input_pair> m_inputs; - bgfx_target* m_output; + void setup_auto_uniforms(render_primitive* prim, texture_manager& textures, uint16_t screen_width, uint16_t screen_height, uint32_t rotation_type, bool swap_xy); + void setup_screensize_uniforms(texture_manager& textures, uint16_t screen_width, uint16_t screen_height); + void setup_sourcesize_uniform(render_primitive* prim); + void setup_rotationtype_uniform(uint32_t rotation_type); + void setup_swapxy_uniform(bool swap_xy); + + bool setup_view(int view, uint16_t screen_width, uint16_t screen_height, int32_t screen); + void put_screen_buffer(render_primitive* prim, bgfx::TransientVertexBuffer* buffer); + + std::string m_name; + bgfx_effect* m_effect; + std::vector<bgfx_suppressor*> m_suppressors; + std::vector<bgfx_input_pair> m_inputs; + std::vector<bgfx_entry_uniform*> m_uniforms; + target_manager& m_targets; + std::string m_output; }; #endif // __DRAWBGFX_CHAIN_ENTRY__ diff --git a/src/osd/modules/render/bgfx/chainentryreader.cpp b/src/osd/modules/render/bgfx/chainentryreader.cpp index ef9322782ee..e98b704a853 100644 --- a/src/osd/modules/render/bgfx/chainentryreader.cpp +++ b/src/osd/modules/render/bgfx/chainentryreader.cpp @@ -9,6 +9,10 @@ #include <string> #include "emu.h" +#include "rendutil.h" +#include <modules/render/copyutil.h> + +#include <modules/lib/osdobj_common.h> #include "chainentryreader.h" @@ -16,13 +20,23 @@ #include "targetmanager.h" #include "effectmanager.h" #include "chainentry.h" +#include "slider.h" #include "inputpair.h" +#include "entryuniform.h" +#include "entryuniformreader.h" +#include "suppressor.h" +#include "suppressorreader.h" -bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, texture_manager& textures, target_manager& targets, effect_manager& effects) +bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::string prefix, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params) { - validate_parameters(value); + if (!validate_parameters(value, prefix)) + { + printf("Failed validation\n"); + return nullptr; + } bgfx_effect* effect = effects.effect(value["effect"].GetString()); + std::string name = value["name"].GetString(); std::vector<bgfx_input_pair> inputs; if (value.HasMember("input")) @@ -30,27 +44,82 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, textur const Value& input_array = value["input"]; for (UINT32 i = 0; i < input_array.Size(); i++) { - std::string sampler = input_array[i]["sampler"].GetString(); + if (!READER_CHECK(input_array[i].HasMember("sampler"), (prefix + "input[" + std::to_string(i) + ": Must have string value 'sampler' (what sampler are we binding to?)\n").c_str())) return nullptr; + if (!READER_CHECK(input_array[i]["sampler"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'sampler' must be a string\n").c_str())) return nullptr; + if (!READER_CHECK(input_array[i].HasMember("texture"), (prefix + "input[" + std::to_string(i) + ": Must have string value 'texture' (what texture are we using?)\n").c_str())) return nullptr; + if (!READER_CHECK(input_array[i]["texture"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'texture' must be a string\n").c_str())) return nullptr; + std::string sampler = input_array[i]["sampler"].GetString(); std::string texture = input_array[i]["texture"].GetString(); - inputs.push_back(bgfx_input_pair(i, sampler, textures.texture(texture))); + inputs.push_back(bgfx_input_pair(i, sampler, texture)); } } - bgfx_target* output = targets.target(value["output"].GetString()); + std::vector<bgfx_entry_uniform*> uniforms; + if (value.HasMember("uniforms")) + { + const Value& uniform_array = value["uniforms"]; + for (UINT32 i = 0; i < uniform_array.Size(); i++) + { + bgfx_entry_uniform* uniform = entry_uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: ", effect, sliders, params); + if (uniform == nullptr) + { + for (bgfx_entry_uniform* existing_uniform : uniforms) delete existing_uniform; + return nullptr; + } + uniforms.push_back(uniform); + } + } - return new bgfx_chain_entry(value["name"].GetString(), effect, inputs, output); -} + std::vector<bgfx_suppressor*> suppressors; + if (value.HasMember("disablewhen")) + { + const Value& suppressor_array = value["disablewhen"]; + for (UINT32 i = 0; i < suppressor_array.Size(); i++) + { + bgfx_suppressor* suppressor = suppressor_reader::read_from_value(suppressor_array[i], prefix, sliders); + if (suppressor == nullptr) + { + for (bgfx_entry_uniform* uniform : uniforms) delete uniform; + for (bgfx_suppressor* existing_suppressor : suppressors) delete existing_suppressor; + return nullptr; + } + suppressors.push_back(suppressor); + } + } -void chain_entry_reader::validate_parameters(const Value& value) -{ - assert(value.HasMember("effect")); - assert(value["effect"].IsString()); - if (value.HasMember("name")) + if (value.HasMember("textures")) { - assert(value["name"].IsString()); + const Value& texture_array = value["textures"]; + for (UINT32 i = 0; i < texture_array.Size(); i++) + { + std::string texture_path = std::string(options.bgfx_path()) + "/artwork/"; + if (!READER_CHECK(texture_array[i].IsString(), (prefix + "textures[" + std::to_string(i) + "]: Value must be a string\n").c_str())) + { + for (bgfx_entry_uniform* uniform : uniforms) delete uniform; + for (bgfx_suppressor* suppressor : suppressors) delete suppressor; + return nullptr; + } + std::string texture_name = texture_array[i].GetString(); + + textures.create_png_texture(texture_path, texture_name, texture_name); + } } - assert(value.HasMember("shader")); - assert(value["shader"].IsString()); - assert(value.HasMember("output")); - assert(value["output"].IsString()); + + std::string output = value["output"].GetString(); + return new bgfx_chain_entry(name, effect, suppressors, inputs, uniforms, targets, output); } + +bool chain_entry_reader::validate_parameters(const Value& value, std::string prefix) +{ + if (!READER_CHECK(value.HasMember("effect"), (prefix + "Must have string value 'effect' (what effect does this entry use?)\n").c_str())) return false; + if (!READER_CHECK(value["effect"].IsString(), (prefix + "Value 'effect' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'effect' (what effect does this entry use?)\n").c_str())) return false; + if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("output"), (prefix + "Must have string value 'offset' (what target are we rendering to?)\n").c_str())) return false; + if (!READER_CHECK(value["output"].IsString(), (prefix + "Value 'output' must be a string\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("input") || value["input"].IsArray(), (prefix + "Value 'input' must be an array\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("uniforms") || value["uniforms"].IsArray(), (prefix + "Value 'uniforms' must be an array\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("disablewhen") || value["disablewhen"].IsArray(), (prefix + "Value 'disablewhen' must be an array\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("textures") || value["textures"].IsArray(), (prefix + "Value 'textures' must be an array\n").c_str())) return false; + return true; +}
\ No newline at end of file diff --git a/src/osd/modules/render/bgfx/chainentryreader.h b/src/osd/modules/render/bgfx/chainentryreader.h index 09001a6ea70..a6001ca60eb 100644 --- a/src/osd/modules/render/bgfx/chainentryreader.h +++ b/src/osd/modules/render/bgfx/chainentryreader.h @@ -11,20 +11,25 @@ #ifndef __DRAWBGFX_CHAIN_ENTRY_READER__ #define __DRAWBGFX_CHAIN_ENTRY_READER__ +#include <map> + #include "statereader.h" +class osd_options; class bgfx_chain_entry; class texture_manager; class target_manager; class effect_manager; +class bgfx_slider; +class bgfx_parameter; class chain_entry_reader : public state_reader { public: - static bgfx_chain_entry* read_from_value(const Value& value, texture_manager& textures, target_manager& targets, effect_manager& effects); + static bgfx_chain_entry* read_from_value(const Value& value, std::string prefix, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params); private: - static void validate_parameters(const Value& value); + static bool validate_parameters(const Value& value, std::string prefix); }; #endif // __DRAWBGFX_CHAIN_ENTRY_READER__ diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp index 4a14bc47b86..d650e2dadce 100644 --- a/src/osd/modules/render/bgfx/chainmanager.cpp +++ b/src/osd/modules/render/bgfx/chainmanager.cpp @@ -12,9 +12,8 @@ #include "emu.h" #include <rapidjson/document.h> +#include <rapidjson/error/en.h> -#include <bgfx/bgfxplatform.h> -#include <bgfx/bgfx.h> #include <bx/readerwriter.h> #include <bx/crtimpl.h> @@ -33,24 +32,33 @@ chain_manager::~chain_manager() m_chains.clear(); } -bgfx_chain* chain_manager::chain(std::string name) +bgfx_chain* chain_manager::chain(std::string name, running_machine& machine, uint32_t window_index) { - std::map<std::string, bgfx_chain*>::iterator iter = m_chains.find(name); + std::map<std::string, bgfx_chain*>::iterator iter = m_chains.find(name + std::to_string(window_index)); if (iter != m_chains.end()) { return iter->second; } - return load_chain(name); + return load_chain(name, machine, window_index); } -bgfx_chain* chain_manager::load_chain(std::string name) { - std::string path = "bgfx/chains/" + name + ".json"; +bgfx_chain* chain_manager::load_chain(std::string name, running_machine& machine, uint32_t window_index) +{ + if (name.length() < 5 || (name.compare(name.length() - 5, 5, ".json")!= 0)) + { + name = name + ".json"; + } + std::string path = std::string(m_options.bgfx_path()) + "/chains/" + name; bx::CrtFileReader reader; - bx::open(&reader, path.c_str()); + if (!bx::open(&reader, path.c_str())) + { + printf("Unable to open chain file %s, falling back to no post processing\n", path.c_str()); + return nullptr; + } - int32_t size = (uint32_t)bx::getSize(&reader); + int32_t size(bx::getSize(&reader)); char* data = new char[size + 1]; bx::read(&reader, reinterpret_cast<void*>(data), size); @@ -59,9 +67,24 @@ bgfx_chain* chain_manager::load_chain(std::string name) { Document document; document.Parse<0>(data); - bgfx_chain* chain = chain_reader::read_from_value(document, m_textures, m_targets, m_effects, m_width, m_height); - m_chains[name] = chain; + if (document.HasParseError()) + { + std::string error(GetParseError_En(document.GetParseError())); + printf("Unable to parse chain %s. Errors returned:\n", path.c_str()); + printf("%s\n", error.c_str()); + return nullptr; + } + + bgfx_chain* chain = chain_reader::read_from_value(document, name + ": ", m_options, machine, window_index, m_textures, m_targets, m_effects, m_width, m_height); + + if (chain == nullptr) + { + printf("Unable to load chain %s, falling back to no post processing\n", path.c_str()); + return nullptr; + } + + m_chains[name + std::to_string(window_index)] = chain; return chain; } diff --git a/src/osd/modules/render/bgfx/chainmanager.h b/src/osd/modules/render/bgfx/chainmanager.h index 63c97215dec..4f413459d37 100644 --- a/src/osd/modules/render/bgfx/chainmanager.h +++ b/src/osd/modules/render/bgfx/chainmanager.h @@ -17,18 +17,19 @@ #include <map> #include <string> -#include <bgfx/bgfx.h> - #include "texturemanager.h" #include "targetmanager.h" #include "effectmanager.h" +class running_machine; + class bgfx_chain; class chain_manager { public: - chain_manager(texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t width, uint32_t height) - : m_textures(textures) + chain_manager(osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t width, uint32_t height) + : m_options(options) + , m_textures(textures) , m_targets(targets) , m_effects(effects) , m_width(width) @@ -38,11 +39,12 @@ public: ~chain_manager(); // Getters - bgfx_chain* chain(std::string name); + bgfx_chain* chain(std::string name, running_machine& machine, uint32_t window_index); private: - bgfx_chain* load_chain(std::string name); + bgfx_chain* load_chain(std::string name, running_machine& machine, uint32_t window_index); + osd_options& m_options; texture_manager& m_textures; target_manager& m_targets; effect_manager& m_effects; diff --git a/src/osd/modules/render/bgfx/chainreader.cpp b/src/osd/modules/render/bgfx/chainreader.cpp index 392fb93fb65..79ab78cdaa2 100644 --- a/src/osd/modules/render/bgfx/chainreader.cpp +++ b/src/osd/modules/render/bgfx/chainreader.cpp @@ -8,19 +8,28 @@ #include <string> #include <vector> +#include <map> #include "emu.h" +#include <modules/lib/osdobj_common.h> + +#include "chainreader.h" #include "chain.h" #include "sliderreader.h" #include "paramreader.h" #include "chainentryreader.h" +#include "targetreader.h" #include "targetmanager.h" -#include "chainreader.h" +#include "slider.h" +#include "parameter.h" -bgfx_chain* chain_reader::read_from_value(const Value& value, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t screen_width, uint32_t screen_height) +bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix, osd_options& options, running_machine& machine, uint32_t window_index, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t screen_width, uint32_t screen_height) { - validate_parameters(value); + if (!validate_parameters(value, prefix)) + { + return nullptr; + } std::string name = value["name"].GetString(); std::string author = value["author"].GetString(); @@ -32,10 +41,25 @@ bgfx_chain* chain_reader::read_from_value(const Value& value, texture_manager& t const Value& slider_array = value["sliders"]; for (UINT32 i = 0; i < slider_array.Size(); i++) { - sliders.push_back(slider_reader::read_from_value(slider_array[i])); + std::vector<bgfx_slider*> expanded_sliders = slider_reader::read_from_value(slider_array[i], prefix + "sliders[" + std::to_string(i) + "]: ", machine, window_index); + if (expanded_sliders.size() == 0) + { + return nullptr; + } + for (bgfx_slider* slider : expanded_sliders) + { + sliders.push_back(slider); + } } } + // Map sliders + std::map<std::string, bgfx_slider*> slider_map; + for (bgfx_slider* slider : sliders) + { + slider_map[slider->name()] = slider; + } + // Parse parameters std::vector<bgfx_parameter*> parameters; if (value.HasMember("parameters")) @@ -43,57 +67,65 @@ bgfx_chain* chain_reader::read_from_value(const Value& value, texture_manager& t const Value& param_array = value["parameters"]; for (UINT32 i = 0; i < param_array.Size(); i++) { - parameters.push_back(parameter_reader::read_from_value(param_array[i])); + bgfx_parameter* parameter = parameter_reader::read_from_value(param_array[i], prefix + "parameters[" + std::to_string(i) + "]; ", window_index); + if (parameter == nullptr) + { + return nullptr; + } + parameters.push_back(parameter); } } - // Parse chain entries - std::vector<bgfx_chain_entry*> entries; - if (value.HasMember("passes")) + // Map parameters + std::map<std::string, bgfx_parameter*> param_map; + for (bgfx_parameter* param : parameters) { - const Value& entry_array = value["passes"]; - for (UINT32 i = 0; i < entry_array.Size(); i++) - { - entries.push_back(chain_entry_reader::read_from_value(entry_array[i], textures, targets, effects)); - } + param_map[param->name()] = param; } // Create targets if (value.HasMember("targets")) { const Value& target_array = value["targets"]; + // TODO: Move into its own reader for (UINT32 i = 0; i < target_array.Size(); i++) { - assert(target_array[i].HasMember("name")); - assert(target_array[i]["name"].IsString()); - uint32_t width = 0; - uint32_t height = 0; - if (target_array[i].HasMember("screen") && target_array[i]["screen"].IsBool()) + if (!target_reader::read_from_value(target_array[i], prefix + "targets[" + std::to_string(i) + "]: ", targets, options, screen_width, screen_height)) { - width = screen_width; - height = screen_height; + return nullptr; } - else - { - assert(target_array[i].HasMember("width")); - assert(target_array[i]["width"].IsDouble()); - assert(target_array[i].HasMember("height")); - assert(target_array[i]["height"].IsDouble()); - width = uint32_t(target_array[i]["width"].GetDouble()); - height = uint32_t(target_array[i]["height"].GetDouble()); - } - targets.create_target(target_array[i]["name"].GetString(), bgfx::TextureFormat::RGBA8, width, height); } } - return new bgfx_chain(name, author, sliders, parameters, entries); + // Parse chain entries + std::vector<bgfx_chain_entry*> entries; + if (value.HasMember("passes")) + { + const Value& entry_array = value["passes"]; + for (UINT32 i = 0; i < entry_array.Size(); i++) + { + bgfx_chain_entry* entry = chain_entry_reader::read_from_value(entry_array[i], prefix + "passes[" + std::to_string(i) + "]: ", options, textures, targets, effects, slider_map, param_map); + if (entry == nullptr) + { + return nullptr; + } + entries.push_back(entry); + } + } + + return new bgfx_chain(name, author, sliders, parameters, entries); } -void chain_reader::validate_parameters(const Value& value) +bool chain_reader::validate_parameters(const Value& value, std::string prefix) { - assert(value.HasMember("name")); - assert(value["name"].IsString()); - assert(value.HasMember("author")); - assert(value["author"].IsString()); - assert(value.HasMember("passes")); + if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false; + if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("author"), (prefix + "Must have string value 'author'\n").c_str())) return false; + if (!READER_CHECK(value["author"].IsString(), (prefix + "Value 'author' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("passes"), (prefix + "Must have array value 'passes'\n").c_str())) return false; + if (!READER_CHECK(value["passes"].IsArray(), (prefix + "Value 'passes' must be an array\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("sliders") || value["sliders"].IsArray(), (prefix + "Value 'sliders' must be an array\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("parameters") || value["parameters"].IsArray(), (prefix + "Value 'parameters' must be an array\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("targets") || value["targets"].IsArray(), (prefix + "Value 'targets' must be an array\n").c_str())) return false; + return true; } diff --git a/src/osd/modules/render/bgfx/chainreader.h b/src/osd/modules/render/bgfx/chainreader.h index fb5dccf0d1c..78e3d677a04 100644 --- a/src/osd/modules/render/bgfx/chainreader.h +++ b/src/osd/modules/render/bgfx/chainreader.h @@ -21,10 +21,10 @@ class effect_manager; class chain_reader : public state_reader { public: - static bgfx_chain* read_from_value(const Value& value, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t screen_width, uint32_t screen_height); + static bgfx_chain* read_from_value(const Value& value, std::string prefix, osd_options& options, running_machine& machine, uint32_t window_index, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t screen_width, uint32_t screen_height); private: - static void validate_parameters(const Value& value); + static bool validate_parameters(const Value& value, std::string prefix); }; #endif // __DRAWBGFX_CHAIN_READER__ diff --git a/src/osd/modules/render/bgfx/depthreader.cpp b/src/osd/modules/render/bgfx/depthreader.cpp index cdcfa1b2046..e904604b84d 100644 --- a/src/osd/modules/render/bgfx/depthreader.cpp +++ b/src/osd/modules/render/bgfx/depthreader.cpp @@ -21,13 +21,13 @@ const depth_reader::string_to_enum depth_reader::FUNCTION_NAMES[depth_reader::FU { "always", BGFX_STATE_DEPTH_TEST_ALWAYS } }; -uint64_t depth_reader::read_from_value(const Value& value) +uint64_t depth_reader::read_from_value(const Value& value, std::string prefix) { uint64_t write_enable = 0; - if (value.HasMember("writeEnable")) + if (value.HasMember("writeenable")) { - assert(value["writeEnable"].IsBool()); - write_enable = value["writeEnable"].GetBool() ? BGFX_STATE_DEPTH_WRITE: 0; + if (!READER_CHECK(value["writeenable"].IsBool(), (prefix + "Value 'writeenable' must be a boolean\n").c_str())) return 0; + write_enable = value["writeenable"].GetBool() ? BGFX_STATE_DEPTH_WRITE: 0; } uint64_t function = get_enum_from_value(value, "function", BGFX_STATE_DEPTH_TEST_ALWAYS, FUNCTION_NAMES, FUNCTION_COUNT); diff --git a/src/osd/modules/render/bgfx/depthreader.h b/src/osd/modules/render/bgfx/depthreader.h index 761a1653323..9e2c99a0b29 100644 --- a/src/osd/modules/render/bgfx/depthreader.h +++ b/src/osd/modules/render/bgfx/depthreader.h @@ -11,11 +11,13 @@ #ifndef __DRAWBGFX_DEPTH_READER__ #define __DRAWBGFX_DEPTH_READER__ +#include <string> + #include "statereader.h" class depth_reader : public state_reader { public: - static uint64_t read_from_value(const Value& value); + static uint64_t read_from_value(const Value& value, std::string prefix); private: static const int FUNCTION_COUNT = 8; diff --git a/src/osd/modules/render/bgfx/effect.cpp b/src/osd/modules/render/bgfx/effect.cpp index 98bf317a50c..9431c0bcba9 100644 --- a/src/osd/modules/render/bgfx/effect.cpp +++ b/src/osd/modules/render/bgfx/effect.cpp @@ -8,6 +8,8 @@ #include "effect.h" +#include "uniform.h" + bgfx_effect::bgfx_effect(uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<bgfx_uniform*> uniforms) : m_state(state) { @@ -29,13 +31,13 @@ bgfx_effect::~bgfx_effect() bgfx::destroyProgram(m_program_handle); } -void bgfx_effect::submit(int view) +void bgfx_effect::submit(int view, uint64_t blend) { for (std::pair<std::string, bgfx_uniform*> uniform_pair : m_uniforms) { (uniform_pair.second)->upload(); } - bgfx::setState(m_state); + bgfx::setState(m_state | blend); bgfx::submit(view, m_program_handle); } diff --git a/src/osd/modules/render/bgfx/effect.h b/src/osd/modules/render/bgfx/effect.h index 2bbc4b8fda9..8c1c3c4f617 100644 --- a/src/osd/modules/render/bgfx/effect.h +++ b/src/osd/modules/render/bgfx/effect.h @@ -2,7 +2,7 @@ // copyright-holders:Ryan Holtz //============================================================ // -// effect.h - BGFX shader material to be applied to a mesh +// effect.cpp - BGFX shader material to be applied to a mesh // //============================================================ @@ -13,28 +13,24 @@ #include <bgfx/bgfx.h> -#include <string> #include <vector> #include <map> -#include "uniform.h" +class bgfx_uniform; class bgfx_effect { public: - bgfx_effect(uint64_t state, bgfx::ShaderHandle vertexShader, bgfx::ShaderHandle fragmentShader, std::vector<bgfx_uniform*> uniforms); - ~bgfx_effect(); + bgfx_effect(uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<bgfx_uniform*> uniforms); + ~bgfx_effect(); - void submit(int view); - - // Getters - bgfx_uniform* uniform(std::string name); - bgfx::ProgramHandle get_program() const { return m_program_handle; } + void submit(int view, uint64_t blend = 0L); + bgfx_uniform* uniform(std::string name); private: - uint64_t m_state; - bgfx::ProgramHandle m_program_handle; - std::map<std::string, bgfx_uniform*> m_uniforms; + uint64_t m_state; + bgfx::ProgramHandle m_program_handle; + std::map<std::string, bgfx_uniform*> m_uniforms; }; #endif // __DRAWBGFX_EFFECT__ diff --git a/src/osd/modules/render/bgfx/effectmanager.cpp b/src/osd/modules/render/bgfx/effectmanager.cpp index c7410406f13..7522a88dc8c 100644 --- a/src/osd/modules/render/bgfx/effectmanager.cpp +++ b/src/osd/modules/render/bgfx/effectmanager.cpp @@ -44,13 +44,17 @@ bgfx_effect* effect_manager::effect(std::string name) return load_effect(name); } -bgfx_effect* effect_manager::load_effect(std::string name) { - std::string path = "bgfx/effects/" + name + ".json"; +bgfx_effect* effect_manager::load_effect(std::string name) +{ + if (name.length() < 5 || (name.compare(name.length() - 5, 5, ".json") != 0)) { + name = name + ".json"; + } + std::string path = std::string(m_options.bgfx_path()) + "/effects/" + name; bx::CrtFileReader reader; bx::open(&reader, path.c_str()); - int32_t size = (uint32_t)bx::getSize(&reader); + int32_t size (bx::getSize(&reader)); char* data = new char[size + 1]; bx::read(&reader, reinterpret_cast<void*>(data), size); @@ -59,7 +63,7 @@ bgfx_effect* effect_manager::load_effect(std::string name) { Document document; document.Parse<0>(data); - bgfx_effect* effect = effect_reader::read_from_value(m_shaders, document); + bgfx_effect* effect = effect_reader::read_from_value(document, "Effect '" + name + "': ", m_shaders); m_effects[name] = effect; diff --git a/src/osd/modules/render/bgfx/effectmanager.h b/src/osd/modules/render/bgfx/effectmanager.h index e3d1666d26e..476d00ba62a 100644 --- a/src/osd/modules/render/bgfx/effectmanager.h +++ b/src/osd/modules/render/bgfx/effectmanager.h @@ -25,7 +25,7 @@ class bgfx_effect; class effect_manager { public: - effect_manager(shader_manager& shaders) : m_shaders(shaders) { } + effect_manager(osd_options& options, shader_manager& shaders) : m_options(options), m_shaders(shaders) { } ~effect_manager(); // Getters @@ -34,6 +34,7 @@ public: private: bgfx_effect* load_effect(std::string name); + osd_options& m_options; shader_manager& m_shaders; std::map<std::string, bgfx_effect*> m_effects; }; diff --git a/src/osd/modules/render/bgfx/effectreader.cpp b/src/osd/modules/render/bgfx/effectreader.cpp index 63a6a925a64..80a8b73abed 100644 --- a/src/osd/modules/render/bgfx/effectreader.cpp +++ b/src/osd/modules/render/bgfx/effectreader.cpp @@ -22,12 +22,19 @@ #include "effectreader.h" -bgfx_effect* effect_reader::read_from_value(shader_manager& shaders, const Value& value) +bgfx_effect* effect_reader::read_from_value(const Value& value, std::string prefix, shader_manager& shaders) { - validate_parameters(value); + if (!validate_parameters(value, prefix)) + { + return nullptr; + } - uint64_t blend = blend_reader::read_from_value(value["blend"]); - uint64_t depth = depth_reader::read_from_value(value["depth"]); + uint64_t blend = 0; + if (value.HasMember("blend")) + { + blend = blend_reader::read_from_value(value["blend"]); + } + uint64_t depth = depth_reader::read_from_value(value["depth"], prefix + "depth: "); uint64_t cull = cull_reader::read_from_value(value["cull"]); uint64_t write = write_reader::read_from_value(value["write"]); @@ -35,7 +42,7 @@ bgfx_effect* effect_reader::read_from_value(shader_manager& shaders, const Value const Value& uniform_array = value["uniforms"]; for (UINT32 i = 0; i < uniform_array.Size(); i++) { - uniforms.push_back(uniform_reader::read_from_value(uniform_array[i])); + uniforms.push_back(uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: ")); } std::string vertex_name(value["vertex"].GetString()); @@ -55,23 +62,17 @@ bgfx_effect* effect_reader::read_from_value(shader_manager& shaders, const Value return new bgfx_effect(blend | depth | cull | write, vertex_shader, fragment_shader, uniforms); } -void effect_reader::validate_parameters(const Value& value) +bool effect_reader::validate_parameters(const Value& value, std::string prefix) { - assert(value.HasMember("blend")); - assert(value.HasMember("depth")); - assert(value.HasMember("cull")); - assert(value.HasMember("write")); - assert(value.HasMember("vertex")); - assert(value["vertex"].IsString()); - assert(value.HasMember("fragment") || value.HasMember("pixel")); - if (value.HasMember("fragment")) - { - assert(value["fragment"].IsString()); - } - if (value.HasMember("pixel")) - { - assert(value["pixel"].IsString()); - } - assert(value.HasMember("uniforms")); - assert(value["uniforms"].IsArray()); + if (!READER_CHECK(value.HasMember("depth"), (prefix + "Must have object value 'depth' (what are our Z-buffer settings?)\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("cull"), (prefix + "Must have object value 'cull' (do we cull triangles based on winding?)\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("write"), (prefix + "Must have object value 'write' (what are our color buffer write settings?)\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("vertex"), (prefix + "Must have string value 'vertex' (what is our vertex shader?)\n").c_str())) return false; + if (!READER_CHECK(value["vertex"].IsString(), (prefix + "Value 'vertex' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("fragment") || value.HasMember("pixel"), (prefix + "Must have string value named 'fragment' or 'pixel' (what is our fragment/pixel shader?)\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("fragment") || value["fragment"].IsString(), (prefix + "Value 'fragment' must be a string\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("pixel") || value["pixel"].IsString(), (prefix + "Value 'pixel' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("uniforms"), (prefix + "Must have array value 'uniforms' (what are our shader's parameters?)\n").c_str())) return false; + if (!READER_CHECK(value["uniforms"].IsArray(), (prefix + "Value 'uniforms' must be an array\n").c_str())) return false; + return true; } diff --git a/src/osd/modules/render/bgfx/effectreader.h b/src/osd/modules/render/bgfx/effectreader.h index a48500131e0..0bc1b334435 100644 --- a/src/osd/modules/render/bgfx/effectreader.h +++ b/src/osd/modules/render/bgfx/effectreader.h @@ -11,6 +11,8 @@ #ifndef __DRAWBGFX_EFFECT_READER__ #define __DRAWBGFX_EFFECT_READER__ +#include <string> + #include "statereader.h" class bgfx_effect; @@ -19,10 +21,10 @@ class shader_manager; class effect_reader : public state_reader { public: - static bgfx_effect* read_from_value(shader_manager& shaders, const Value& value); + static bgfx_effect* read_from_value(const Value& value, std::string prefix, shader_manager& shaders); private: - static void validate_parameters(const Value& value); + static bool validate_parameters(const Value& value, std::string prefix); }; #endif // __DRAWBGFX_EFFECT_READER__ diff --git a/src/osd/modules/render/bgfx/entryuniform.h b/src/osd/modules/render/bgfx/entryuniform.h new file mode 100644 index 00000000000..a72b9e00cf5 --- /dev/null +++ b/src/osd/modules/render/bgfx/entryuniform.h @@ -0,0 +1,34 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// entryuniform.h - BGFX shader chain uniform remapper +// +// Represents the mapping between a fixed value, a slider, or +// other dynamic parameter and a chain effect shader uniform +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_ENTRY_UNIFORM__ +#define __DRAWBGFX_ENTRY_UNIFORM__ + +#include <bgfx/bgfx.h> + +#include "uniform.h" + +class bgfx_entry_uniform +{ +public: + bgfx_entry_uniform(bgfx_uniform* uniform) : m_uniform(uniform) { } + virtual ~bgfx_entry_uniform() { } + + virtual void bind() = 0; + std::string name() const { return m_uniform->name(); } + +protected: + bgfx_uniform* m_uniform; +}; + +#endif // __DRAWBGFX_ENTRY_UNIFORM__ diff --git a/src/osd/modules/render/bgfx/entryuniformreader.cpp b/src/osd/modules/render/bgfx/entryuniformreader.cpp new file mode 100644 index 00000000000..c9a11086817 --- /dev/null +++ b/src/osd/modules/render/bgfx/entryuniformreader.cpp @@ -0,0 +1,59 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// entryuniformreader.cpp - BGFX chain entry uniform reader +// +//============================================================ + +#include "entryuniformreader.h" + +#include "entryuniform.h" +#include "effect.h" +#include "slideruniformreader.h" +#include "valueuniformreader.h" +#include "paramuniformreader.h" +#include "uniform.h" + +bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_effect* effect, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params) +{ + if (!validate_parameters(value, prefix)) + { + return nullptr; + } + + std::string name = value["uniform"].GetString(); + bgfx_uniform* uniform = effect->uniform(name); + + if (!READER_CHECK(uniform != nullptr, (prefix + "Uniform '" + name + " does not appear to exist\n").c_str())) + { + return nullptr; + } + + if (value.HasMember("slider")) + { + return slider_uniform_reader::read_from_value(value, prefix, uniform, sliders); + } + else if (value.HasMember("value")) + { + return value_uniform_reader::read_from_value(value, prefix, uniform); + } + else if (value.HasMember("parameter")) + { + return param_uniform_reader::read_from_value(value, prefix, uniform, params); + } + else + { + READER_CHECK(false, (prefix + "Unrecognized uniform type for uniform binding " + name).c_str()); + } + + + return nullptr; +} + +bool entry_uniform_reader::validate_parameters(const Value& value, std::string prefix) +{ + if (!READER_CHECK(value.HasMember("uniform"), (prefix + "Must have string value 'uniform' (what uniform are we mapping?)\n").c_str())) return false; + if (!READER_CHECK(value["uniform"].IsString(), (prefix + "Value 'effect' must be a string\n").c_str())) return false; + return true; +} diff --git a/src/osd/modules/render/bgfx/entryuniformreader.h b/src/osd/modules/render/bgfx/entryuniformreader.h new file mode 100644 index 00000000000..73c66269a5e --- /dev/null +++ b/src/osd/modules/render/bgfx/entryuniformreader.h @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// entryuniformreader.h - BGFX chain entry uniform reader +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_ENTRY_UNIFORM_READER__ +#define __DRAWBGFX_ENTRY_UNIFORM_READER__ + +#include <string> +#include <map> + +#include "statereader.h" + +class bgfx_entry_uniform; +class bgfx_slider; +class bgfx_effect; +class bgfx_parameter; + +class entry_uniform_reader : public state_reader +{ +public: + static bgfx_entry_uniform* read_from_value(const Value& value, std::string prefix, bgfx_effect* effect, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params); + +private: + static bool validate_parameters(const Value& value, std::string prefix); +}; + +#endif // __DRAWBGFX_ENTRY_UNIFORM_READER__ diff --git a/src/osd/modules/render/bgfx/frameparameter.cpp b/src/osd/modules/render/bgfx/frameparameter.cpp new file mode 100644 index 00000000000..a354664cfce --- /dev/null +++ b/src/osd/modules/render/bgfx/frameparameter.cpp @@ -0,0 +1,27 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// frameparameter.cpp - Frame-based dynamic shader param +// +//============================================================ + +#include "frameparameter.h" + +bgfx_frame_parameter::bgfx_frame_parameter(std::string name, parameter_type type, uint32_t period) + : bgfx_parameter(name, type) + , m_current_frame(0) + , m_period(period) +{ +} + +float bgfx_frame_parameter::value() +{ + return float(m_current_frame); +} + +void bgfx_frame_parameter::tick(double /*delta*/) +{ + m_current_frame++; + m_current_frame %= m_period; +} diff --git a/src/osd/modules/render/bgfx/frameparameter.h b/src/osd/modules/render/bgfx/frameparameter.h new file mode 100644 index 00000000000..022a6f2065b --- /dev/null +++ b/src/osd/modules/render/bgfx/frameparameter.h @@ -0,0 +1,35 @@ + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// frameparameter.cpp - Frame-based dynamic shader param +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_FRAME_PARAMETER__ +#define __DRAWBGFX_FRAME_PARAMETER__ + +#include <bgfx/bgfx.h> + +#include <string> + +#include "parameter.h" + +class bgfx_frame_parameter : public bgfx_parameter +{ +public: + bgfx_frame_parameter(std::string name, parameter_type type, uint32_t period); + virtual ~bgfx_frame_parameter() { } + + virtual float value() override; + virtual void tick(double delta) override; + +private: + uint32_t m_current_frame; + uint32_t m_period; +}; + +#endif // __DRAWBGFX_FRAME_PARAMETER__ diff --git a/src/osd/modules/render/bgfx/fs_blit.sc b/src/osd/modules/render/bgfx/fs_blit.sc index 5130d1bebb5..ff6befc4272 100644 --- a/src/osd/modules/render/bgfx/fs_blit.sc +++ b/src/osd/modules/render/bgfx/fs_blit.sc @@ -5,6 +5,7 @@ $input v_color0, v_texcoord0 #include "../../../../../3rdparty/bgfx/examples/common/common.sh" +// Samplers SAMPLER2D(s_tex, 0); void main() diff --git a/src/osd/modules/render/bgfx/fs_color.sc b/src/osd/modules/render/bgfx/fs_color.sc new file mode 100644 index 00000000000..fae98f2a39f --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_color.sc @@ -0,0 +1,43 @@ +$input v_color0, v_texcoord0 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// Color Convolution Effect +//----------------------------------------------------------------------------- + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +// User-supplied +uniform vec4 u_red_ratios; +uniform vec4 u_grn_ratios; +uniform vec4 u_blu_ratios; +uniform vec4 u_offset; +uniform vec4 u_scale; +uniform vec4 u_saturation; + +// Samplers +SAMPLER2D(s_tex, 0); + +void main() +{ + vec4 BaseTexel = texture2D(s_tex, v_texcoord0); + + vec3 OutRGB = BaseTexel.rgb; + + // RGB Tint & Shift + float ShiftedRed = dot(OutRGB, u_red_ratios.xyz); + float ShiftedGrn = dot(OutRGB, u_grn_ratios.xyz); + float ShiftedBlu = dot(OutRGB, u_blu_ratios.xyz); + + // RGB Scale & Offset + vec3 OutTexel = vec3(ShiftedRed, ShiftedGrn, ShiftedBlu) * u_scale.xyz + u_offset.xyz; + + // Saturation + vec3 Grayscale = vec3(0.299, 0.587, 0.114); + float OutLuma = dot(OutTexel, Grayscale); + vec3 OutChroma = OutTexel - OutLuma; + vec3 Saturated = OutLuma + OutChroma * u_saturation.x; + + gl_FragColor = vec4(Saturated, BaseTexel.a); +} diff --git a/src/osd/modules/render/bgfx/fs_deconverge.sc b/src/osd/modules/render/bgfx/fs_deconverge.sc new file mode 100644 index 00000000000..409896ce40a --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_deconverge.sc @@ -0,0 +1,20 @@ +$input v_color0, v_texcoord0, v_texcoord1, v_texcoord2 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// Deconvergence Effect +//----------------------------------------------------------------------------- + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +// Samplers +SAMPLER2D(s_tex, 0); + +void main() +{ + float r = texture2D(s_tex, v_texcoord0).r; + float g = texture2D(s_tex, v_texcoord1).g; + float b = texture2D(s_tex, v_texcoord2).b; + gl_FragColor = vec4(r, g, b, 1.0) * v_color0; +} diff --git a/src/osd/modules/render/bgfx/fs_defocus.sc b/src/osd/modules/render/bgfx/fs_defocus.sc new file mode 100644 index 00000000000..03c442e4780 --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_defocus.sc @@ -0,0 +1,50 @@ +$input v_color0, v_texcoord0 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// Defocus Effect +//----------------------------------------------------------------------------- + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +// Autos +uniform vec4 u_screen_dims; + +// User-supplied +uniform vec4 u_defocus; + +// Samplers +SAMPLER2D(s_tex, 0); + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +void main() +{ + const vec2 Coord1Offset = vec2( 0.75, 0.50); + const vec2 Coord2Offset = vec2( 0.25, 1.00); + const vec2 Coord3Offset = vec2(-0.50, 0.75); + const vec2 Coord4Offset = vec2(-1.00, 0.25); + const vec2 Coord5Offset = vec2(-0.75, -0.50); + const vec2 Coord6Offset = vec2(-0.25, -1.00); + const vec2 Coord7Offset = vec2( 0.50, -0.75); + const vec2 Coord8Offset = vec2( 1.00, -0.25); + + vec2 DefocusTexelDims = u_defocus.xy / u_screen_dims.xy; + + vec4 d0 = texture2D(s_tex, v_texcoord0); + vec4 d1 = texture2D(s_tex, v_texcoord0 + Coord1Offset * DefocusTexelDims); + vec4 d2 = texture2D(s_tex, v_texcoord0 + Coord2Offset * DefocusTexelDims); + vec4 d3 = texture2D(s_tex, v_texcoord0 + Coord3Offset * DefocusTexelDims); + vec4 d4 = texture2D(s_tex, v_texcoord0 + Coord4Offset * DefocusTexelDims); + vec4 d5 = texture2D(s_tex, v_texcoord0 + Coord5Offset * DefocusTexelDims); + vec4 d6 = texture2D(s_tex, v_texcoord0 + Coord6Offset * DefocusTexelDims); + vec4 d7 = texture2D(s_tex, v_texcoord0 + Coord7Offset * DefocusTexelDims); + vec4 d8 = texture2D(s_tex, v_texcoord0 + Coord8Offset * DefocusTexelDims); + + vec4 blurred = (d0 + d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8) / 9.0; + + gl_FragColor = vec4(blurred.xyz, 1.0) * v_color0; +} diff --git a/src/osd/modules/render/bgfx/fs_distortion.sc b/src/osd/modules/render/bgfx/fs_distortion.sc new file mode 100644 index 00000000000..a80286cfb1a --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_distortion.sc @@ -0,0 +1,219 @@ +$input v_color0, v_texcoord0 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// Distortion Effect +//----------------------------------------------------------------------------- + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +// Autos +uniform vec4 u_screen_dims; +uniform vec4 u_rotation_type; + +// User-supplied +uniform vec4 u_curvature; +uniform vec4 u_round_corner; +uniform vec4 u_smooth_border; +uniform vec4 u_vignetting; +uniform vec4 u_reflection; + +// Samplers +SAMPLER2D(s_tex, 0); + +// Functions + +// www.stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader/ +float rand(vec2 seed) +{ + // irrationals for pseudo randomness + vec2 i = vec2(23.140692, 2.6651442); // e^pi (Gelfond constant), 2^sqrt(2) (Gelfond-Schneider constant) + + return fract(cos(dot(seed, i)) * 123456.0); +} + +// www.dinodini.wordpress.com/2010/04/05/normalized-tunable-sigmoid-functions/ +float normalizedSigmoid(float n, float k) +{ + // valid for n and k in range of -1.0 and 1.0 + return (n - n * k) / (k - abs(n) * 2.0 * k + 1.0); +} + +// www.iquilezles.org/www/articles/distfunctions/distfunctions.htm +float roundBox(vec2 p, vec2 b, float r) +{ + return length(max(abs(p) - b + r, 0.0)) - r; +} + +vec2 GetRatioCorrection() +{ + float ScreenQuadRatio = 1.0; + + return ScreenQuadRatio > 1.0f + ? vec2(1.0, 1.0f / ScreenQuadRatio) + : vec2(ScreenQuadRatio, 1.0); +} + +float GetNoiseFactor(float n, float random) +{ + // smaller n become more noisy + return 1.0 + random * max(0.0, 0.25 * pow(2.7182817, -8.0 * n)); +} + +float GetVignetteFactor(vec2 coord, float amount) +{ + vec2 VignetteCoord = coord; + + float VignetteLength = length(VignetteCoord); + float VignetteBlur = (amount * 0.75) + 0.25; + + // 0.5 full screen fitting circle + float VignetteRadius = 1.0 - (amount * 0.25); + float Vignette = smoothstep(VignetteRadius, VignetteRadius - VignetteBlur, VignetteLength); + + return saturate(Vignette); +} + +float GetSpotAddend(vec2 coord, float amount) +{ + vec2 RatioCorrection = GetRatioCorrection(); + + // normalized screen quad ratio + vec2 QuadRatio = vec2(1.0, u_screen_dims.y / u_screen_dims.x); + + // normalized screen quad ratio + // upper right quadrant + vec2 spotOffset = vec2(-0.25, 0.25); // 0 degrees + if (u_rotation_type.x == 1.0) + spotOffset = vec2(-0.25, -0.25); // 90 degrees + if (u_rotation_type.x == 2.0) + spotOffset = vec2(0.25, -0.25); // 180 degrees + if (u_rotation_type.x == 3.0) + spotOffset = vec2(0.25, 0.25); // 270 degrees + + vec2 SpotCoord = (coord + spotOffset * RatioCorrection) / RatioCorrection; + + float SpotBlur = amount; + + // 0.5 full screen fitting circle + float SpotRadius = amount * 0.75; + float Spot = smoothstep(SpotRadius, SpotRadius - SpotBlur, length(SpotCoord)); + + float SigmoidSpot = amount * normalizedSigmoid(Spot, 0.75); + + // increase strength by 100% + SigmoidSpot = SigmoidSpot * 2.0; + + return saturate(SigmoidSpot); +} + +float GetRoundCornerFactor(vec2 coord, float radiusAmount, float smoothAmount) +{ + vec2 RatioCorrection = GetRatioCorrection(); + + // reduce smooth amount down to radius amount + smoothAmount = min(smoothAmount, radiusAmount); + + float range = min(u_screen_dims.x, u_screen_dims.y) * 0.5; + float radius = range * max(radiusAmount, 0.0025); + float smooth_val = 1.0 / (range * max(smoothAmount, 0.0025)); + + // compute box + float box = roundBox(u_screen_dims.xy * (coord * 2.0f), u_screen_dims.xy * RatioCorrection, radius); + + // apply smooth + box *= smooth_val; + box += 1.0 - pow(smooth_val * 0.5, 0.5); + + float border = smoothstep(1.0, 0.0, box); + + return saturate(border); +} + +// www.francois-tarlier.com/blog/cubic-lens-distortion-shader/ +vec2 GetDistortedCoords(vec2 centerCoord, float amount) +{ + // lens distortion coefficient + float k = amount; + + // cubic distortion value + float kcube = amount * 2.0; + + // compute cubic distortion factor + float r2 = centerCoord.x * centerCoord.x + centerCoord.y * centerCoord.y; + float f = kcube == 0.0 ? 1.0 + r2 * k : 1.0 + r2 * (k + kcube * sqrt(r2)); + + // fit screen bounds + f /= 1.0 + amount * 0.5; + + // apply cubic distortion factor + centerCoord *= f; + + return centerCoord; +} + +vec2 GetCoords(vec2 coord, float distortionAmount) +{ + vec2 RatioCorrection = GetRatioCorrection(); + + // center coordinates + coord -= 0.5; + + // apply ratio difference between screen and quad + coord /= RatioCorrection; + + // distort coordinates + coord = GetDistortedCoords(coord, distortionAmount); + + // revert ratio difference between screen and quad + coord *= RatioCorrection; + + // un-center coordinates + coord += 0.5; + + return coord; +} + +// Shader + +void main() +{ + // Screen Curvature + vec2 BaseCoord = GetCoords(v_texcoord0, u_curvature.x * 0.25); // reduced amount + + vec2 BaseCoordCentered = BaseCoord; + BaseCoordCentered -= 0.5; + + // Color + vec4 BaseColor = texture2D(s_tex, BaseCoord); + BaseColor.a = 1.0; + + // Clamp + if (BaseCoord.x > 1.0 || BaseCoord.y > 1.0 || BaseCoord.x < 0.0 || BaseCoord.y < 0.0) + BaseColor.rgb = vec3(0.0, 0.0, 0.0); + + // Vignetting Simulation + vec2 VignetteCoord = BaseCoordCentered; + + float VignetteFactor = GetVignetteFactor(VignetteCoord, u_vignetting.x); + BaseColor.rgb *= VignetteFactor; + + // Light Reflection Simulation + vec3 LightColor = vec3(1.0, 0.90, 0.80); // color temperature 5.000 Kelvin + + vec2 SpotCoord = BaseCoordCentered; + vec2 NoiseCoord = BaseCoordCentered; + + float SpotAddend = GetSpotAddend(SpotCoord, u_reflection.x); + float NoiseFactor = GetNoiseFactor(SpotAddend, rand(NoiseCoord)); + BaseColor.rgb += SpotAddend * NoiseFactor * LightColor; + + // Round Corners Simulation + vec2 RoundCornerCoord = BaseCoordCentered; + + float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, u_round_corner.x, u_smooth_border.x); + BaseColor.rgb *= roundCornerFactor; + + gl_FragColor = BaseColor; +} diff --git a/src/osd/modules/render/bgfx/fs_gui.sc b/src/osd/modules/render/bgfx/fs_gui.sc index 28a1438d189..9f539c1182a 100644 --- a/src/osd/modules/render/bgfx/fs_gui.sc +++ b/src/osd/modules/render/bgfx/fs_gui.sc @@ -5,10 +5,10 @@ $input v_color0, v_texcoord0 #include "../../../../../3rdparty/bgfx/examples/common/common.sh" +// Samplers SAMPLER2D(s_tex, 0); void main() { - vec4 texel = texture2D(s_tex, v_texcoord0); - gl_FragColor = texel * v_color0; + gl_FragColor = texture2D(s_tex, v_texcoord0) * v_color0; } diff --git a/src/osd/modules/render/bgfx/fs_ntsc_decode.sc b/src/osd/modules/render/bgfx/fs_ntsc_decode.sc new file mode 100644 index 00000000000..1f5c9305053 --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_ntsc_decode.sc @@ -0,0 +1,126 @@ +$input v_color0, v_texcoord0 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// NTSC Decode Effect +//----------------------------------------------------------------------------- + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +// Autos +uniform vec4 u_source_dims; + +// User-supplied +uniform vec4 u_a_value; +uniform vec4 u_b_value; +uniform vec4 u_cc_value; +uniform vec4 u_o_value; +uniform vec4 u_scan_time; +uniform vec4 u_notch_width; +uniform vec4 u_y_freq_response; +uniform vec4 u_i_freq_response; +uniform vec4 u_q_freq_response; +uniform vec4 u_jitter_offset; + +// Parametric +uniform vec4 u_jitter_amount; + +// Samplers +SAMPLER2D(s_tex, 0); + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +void main() +{ + vec4 BaseTexel = texture2D(s_tex, v_texcoord0.xy); + + vec4 zero = vec4(0.0, 0.0, 0.0, 0.0); + vec4 quarter = vec4(0.25, 0.25, 0.25, 0.25); + vec4 onehalf = vec4(0.5, 0.5, 0.5, 0.5); + vec4 one = vec4(1.0, 1.0, 1.0, 1.0); + vec4 two = vec4(2.0, 2.0, 2.0, 2.0); + vec4 four = vec4(4.0, 4.0, 4.0, 4.0); + vec4 TimePerSample = u_scan_time.xxxx / (u_source_dims.xxxx * four); + + vec4 Fc_y1 = (u_cc_value.xxxx - u_notch_width.xxxx * onehalf) * TimePerSample; + vec4 Fc_y2 = (u_cc_value.xxxx + u_notch_width.xxxx * onehalf) * TimePerSample; + vec4 Fc_y3 = u_y_freq_response.xxxx * TimePerSample; + vec4 Fc_i = u_i_freq_response.xxxx * TimePerSample; + vec4 Fc_q = u_q_freq_response.xxxx * TimePerSample; + vec4 Fc_i_2 = Fc_i * two; + vec4 Fc_q_2 = Fc_q * two; + + const vec4 PI = vec4(3.1415927, 3.1415927, 3.1415927, 3.1415927); + const vec4 PI2 = vec4(6.2831854, 6.2831854, 6.2831854, 6.2831854); + + vec4 W = PI2 * u_cc_value.xxxx * u_scan_time.xxxx; + vec4 WoPI = W / PI; + + vec4 HOffset = (u_b_value.xxxx + u_jitter_amount.xxxx * u_jitter_offset.xxxx) / WoPI; + vec4 VScale = (u_a_value.xxxx * u_source_dims.yyyy) / WoPI; + + vec4 YAccum = zero; + vec4 IAccum = zero; + vec4 QAccum = zero; + + for (int index = 0; index < 64; index = index + 4) + { + float n = float(index); + vec4 n4 = vec4(n, n, n, n) + vec4(0.0, 1.0, 2.0, 3.0); + + vec4 Cx = v_texcoord0.xxxx + u_source_dims.xxxx * (n4 * quarter); + + // theory: What if we put white in the input of the NTSC decode shader? + vec4 C = texture2D(s_tex, vec2(Cx.x, v_texcoord0.y)); + + vec4 T = Cx + HOffset + v_texcoord0.yyyy * VScale; + vec4 WT = W * T + u_o_value.xxxx; + + vec4 SincKernel = vec4(0.54, 0.54, 0.54, 0.54) + vec4(0.46, 0.46, 0.46, 0.46) * cos((PI2 / 1.0) * n4); + + vec4 SincYIn1 = Fc_y1 * PI2 * n4; + vec4 SincYIn2 = Fc_y2 * PI2 * n4; + vec4 SincYIn3 = Fc_y3 * PI2 * n4; + vec4 SincIIn = Fc_i * PI2 * n4; + vec4 SincQIn = Fc_q * PI2 * n4; + + SincYIn1 = SincYIn1 == zero ? one : SincYIn1; + SincYIn2 = SincYIn2 == zero ? one : SincYIn2; + SincYIn3 = SincYIn3 == zero ? one : SincYIn3; + + SincIIn = SincIIn == zero ? one : SincIIn; + SincQIn = SincQIn == zero ? one : SincQIn; + + vec4 SincY1 = SincYIn1 != zero ? sin(SincYIn1) / SincYIn1 : one; + vec4 SincY2 = SincYIn2 != zero ? sin(SincYIn2) / SincYIn2 : one; + vec4 SincY3 = SincYIn3 != zero ? sin(SincYIn3) / SincYIn3 : one; + + vec4 IdealY = (Fc_y1 * two * SincY1 - Fc_y2 * two * SincY2) + Fc_y3 * two * SincY3; + vec4 IdealI = Fc_i_2 * (SincIIn != zero ? sin(SincIIn) / SincIIn : one); + vec4 IdealQ = Fc_q_2 * (SincQIn != zero ? sin(SincQIn) / SincQIn : one); + + vec4 FilterY = SincKernel * IdealY; + vec4 FilterI = SincKernel * IdealI; + vec4 FilterQ = SincKernel * IdealQ; + + YAccum = YAccum + C * FilterY; + IAccum = IAccum + C * cos(WT) * FilterI; + QAccum = QAccum + C * sin(WT) * FilterQ; + } + + vec3 YIQ = vec3( + (YAccum.r + YAccum.g + YAccum.b + YAccum.a), + (IAccum.r + IAccum.g + IAccum.b + IAccum.a) * 2.0, + (QAccum.r + QAccum.g + QAccum.b + QAccum.a) * 2.0); + + vec3 RGB = vec3( + dot(YIQ, vec3(1.0, 0.956, 0.621)), + dot(YIQ, vec3(1.0, -0.272, -0.647)), + dot(YIQ, vec3(1.0, -1.106, 1.703))); + + // RGB obviously contains a NaN somewhere along the line! Returns black if vec4 etc. are included, white if just vec4(1.0) + gl_FragColor = vec4(RGB, BaseTexel.a) * v_color0; +} diff --git a/src/osd/modules/render/bgfx/fs_ntsc_encode.sc b/src/osd/modules/render/bgfx/fs_ntsc_encode.sc new file mode 100644 index 00000000000..61f5ae12ac9 --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_ntsc_encode.sc @@ -0,0 +1,72 @@ +$input v_color0, v_texcoord0 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// NTSC Effect +//----------------------------------------------------------------------------- + +// NB: intentionally wasteful of uniforms in order for easier slider utilization + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +// Autos +uniform vec4 u_source_dims; + +// User-supplied +uniform vec4 u_a_value; +uniform vec4 u_b_value; +uniform vec4 u_cc_value; +uniform vec4 u_p_value; +uniform vec4 u_scan_time; +uniform vec4 u_jitter_offset; + +// Parametric +uniform vec4 u_jitter_amount; + +// Samplers +SAMPLER2D(s_tex, 0); + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +void main() +{ + vec2 PValueSourceTexel = vec2(u_p_value.x, 0.0) / u_source_dims.xy; + + vec2 C0 = v_texcoord0 + PValueSourceTexel * vec2(0.0, 0.0); + vec2 C1 = v_texcoord0 + PValueSourceTexel * vec2(0.25, 0.0); + vec2 C2 = v_texcoord0 + PValueSourceTexel * vec2(0.5, 0.0); + vec2 C3 = v_texcoord0 + PValueSourceTexel * vec2(0.75, 0.0); + vec4 Cx = vec4(C0.x, C1.x, C2.x, C3.x); + vec4 Cy = vec4(C0.y, C1.y, C2.y, C3.y); + vec4 Texel0 = texture2D(s_tex, C0); + vec4 Texel1 = texture2D(s_tex, C1); + vec4 Texel2 = texture2D(s_tex, C2); + vec4 Texel3 = texture2D(s_tex, C3); + + vec4 HPosition = Cx; + vec4 VPosition = Cy; + + const vec4 YDot = vec4(0.299, 0.587, 0.114, 0.0); + const vec4 IDot = vec4(0.595716, -0.274453, -0.321263, 0.0); + const vec4 QDot = vec4(0.211456, -0.522591, 0.311135, 0.0); + vec4 Y = vec4(dot(Texel0, YDot), dot(Texel1, YDot), dot(Texel2, YDot), dot(Texel3, YDot)); + vec4 I = vec4(dot(Texel0, IDot), dot(Texel1, IDot), dot(Texel2, IDot), dot(Texel3, IDot)); + vec4 Q = vec4(dot(Texel0, QDot), dot(Texel1, QDot), dot(Texel2, QDot), dot(Texel3, QDot)); + + const float PI = 3.1415927; + const float PI2 = 6.2831854; + + float W = PI2 * u_cc_value.x * u_scan_time.x; + float WoPI = W / PI; + + float HOffset = (u_a_value.x + u_jitter_amount.x * u_jitter_offset.x) / WoPI; + float VScale = (u_b_value.x * u_source_dims.y) / WoPI; + + vec4 T = Cx + vec4(HOffset, HOffset, HOffset, HOffset) + Cy * vec4(VScale, VScale, VScale, VScale); + vec4 TW = T * W; + + gl_FragColor = Y + I * cos(TW) + Q * sin(TW); +}
\ No newline at end of file diff --git a/src/osd/modules/render/bgfx/fs_phosphor.sc b/src/osd/modules/render/bgfx/fs_phosphor.sc index 2df6b3f827d..e5ac1d91f35 100644 --- a/src/osd/modules/render/bgfx/fs_phosphor.sc +++ b/src/osd/modules/render/bgfx/fs_phosphor.sc @@ -5,16 +5,20 @@ $input v_color0, v_texcoord0 #include "../../../../../3rdparty/bgfx/examples/common/common.sh" +// User-supplied uniform vec4 u_passthrough; uniform vec4 u_phosphor; +// Samplers SAMPLER2D(s_tex, 0); SAMPLER2D(s_prev, 1); void main() { - vec4 curr = texture2D(s_tex, v_texcoord0); - vec4 prev = texture2D(s_prev, v_texcoord0); - vec4 phosphored = vec4(max(curr.r, prev.r * u_phosphor.r), max(curr.g, prev.g * u_phosphor.g), max(curr.b, prev.b * u_phosphor.b), curr.a); - gl_FragColor = mix(phosphored, curr, u_passthrough.x) * v_color0; + vec4 curr = texture2D(s_tex, v_texcoord0); + vec3 prev = texture2D(s_prev, v_texcoord0).rgb * u_phosphor.rgb; + + vec3 maxed = max(curr.rgb, prev); + + gl_FragColor = u_passthrough.x > 0.0 ? curr : vec4(maxed, curr.a); } diff --git a/src/osd/modules/render/bgfx/fs_post.sc b/src/osd/modules/render/bgfx/fs_post.sc new file mode 100644 index 00000000000..bfe8eef42e4 --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_post.sc @@ -0,0 +1,148 @@ +$input v_color0, v_texcoord0, v_texcoord1 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// Defocus Effect +//----------------------------------------------------------------------------- + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +// Autos +uniform vec4 u_swap_xy; +uniform vec4 u_screen_dims; // size of the output window +uniform vec4 u_source_dims; // size of the guest machine +uniform vec4 u_screen_scale; // TODO: Hook up ScreenScale code-side +uniform vec4 u_screen_offset; // TODO: Hook up ScreenOffset code-side + +// User-supplied +uniform vec4 u_prepare_bloom; // disables some effects for rendering bloom textures +uniform vec4 u_prepare_vector; +uniform vec4 u_scanline_alpha; +uniform vec4 u_scanline_scale; +uniform vec4 u_scanline_bright_scale; +uniform vec4 u_scanline_bright_offset; +uniform vec4 u_scanline_jitter; +uniform vec4 u_scanline_height; +uniform vec4 u_back_color; // TODO: Unused in current implementation, mostly +uniform vec4 u_shadow_tile_mode; // 0 based on screen dimension, 1 based on source dimension +uniform vec4 u_shadow_alpha; +uniform vec4 u_shadow_uv; +uniform vec4 u_shadow_uv_offset; +uniform vec4 u_humbar_hertz_rate; // difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC) +uniform vec4 u_humbar_alpha; +uniform vec4 u_power; +uniform vec4 u_floor; + +// Parametric +uniform vec4 u_time; +uniform vec4 u_jitter_amount; + +// Samplers +SAMPLER2D(s_tex, 0); +SAMPLER2D(s_shadow, 1); + +//----------------------------------------------------------------------------- +// Scanline & Shadowmask Pixel Shader +//----------------------------------------------------------------------------- + +vec2 GetAdjustedCoords(vec2 coord, vec2 center_offset) +{ + // center coordinates + coord -= center_offset; + + // apply screen scale + //coord /= u_screen_scale.xy; + + // un-center coordinates + coord += center_offset; + + // apply screen offset + coord += (center_offset * 2.0) * u_screen_offset.xy; + + return coord; +} + +void main() +{ + vec2 ScreenTexelDims = vec2(1.0, 1.0) / u_screen_dims.xy; + vec2 SourceTexelDims = vec2(1.0, 1.0) / u_source_dims.xy; + vec2 SourceRes = u_source_dims.xy; + + vec2 HalfSourceRect = vec2(0.5, 0.5); + + vec2 ScreenCoord = v_texcoord0.xy; + vec2 BaseCoord = GetAdjustedCoords(v_texcoord0, HalfSourceRect); + + // Color + vec4 BaseColor = texture2D(s_tex, BaseCoord); + BaseColor.a = 1.0; + + if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0) + { + BaseColor.rgb = vec3(0.0, 0.0, 0.0); + } + + // Mask Simulation (may not affect bloom) + if (u_prepare_bloom.x == 0.0 && u_shadow_alpha.x > 0.0) + { + vec2 screenCoord = ScreenCoord; + screenCoord = u_swap_xy.x > 0.0 ? screenCoord.yx : screenCoord.xy; + + vec2 shadowTile = (u_shadow_tile_mode.x == 0.0 ? u_screen_dims.xy : u_source_dims.xy); + shadowTile = u_swap_xy.x > 0.0 ? shadowTile.yx : shadowTile.xy; + + vec2 ShadowFrac = fract(screenCoord * shadowTile); + vec2 ShadowCoord = (ShadowFrac * u_shadow_uv.xy); + + vec4 ShadowColor = texture2D(s_shadow, ShadowCoord); + vec3 ShadowMaskColor = mix(vec3(1.0, 1.0, 1.0), ShadowColor.rgb, u_shadow_alpha.xxx); + float ShadowMaskClear = (1.0 - ShadowColor.a) * u_shadow_alpha.x; + + // apply shadow mask color + BaseColor.rgb *= ShadowMaskColor; + // clear shadow mask by background color + BaseColor.rgb = mix(BaseColor.rgb, u_back_color.rgb, ShadowMaskClear); + } + + // Color Compression (may not affect bloom) + if (u_prepare_bloom.x == 0.0) + { + // increasing the floor of the signal without affecting the ceiling + BaseColor.rgb = u_floor.rgb + (vec3(1.0, 1.0, 1.0) - u_floor.rgb) * BaseColor.rgb; + } + + // Color Power (may affect bloom) + BaseColor.r = pow(BaseColor.r, u_power.r); + BaseColor.g = pow(BaseColor.g, u_power.g); + BaseColor.b = pow(BaseColor.b, u_power.b); + + // Scanline Simulation (may not affect bloom) + if (u_prepare_bloom.x == 0.0) + { + // Scanline Simulation (may not affect vector screen) + if (u_prepare_vector.x == 0.0 && u_scanline_alpha.x > 0.0f) + { + float ScanCoord = v_texcoord0.y * u_source_dims.y * u_scanline_scale.x * 3.1415927; + float ScanCoordJitter = u_scanline_jitter.x * u_jitter_amount.x * 1.618034; + float ScanSine = sin(ScanCoord + ScanCoordJitter); + float ScanSineScaled = pow(ScanSine * ScanSine, 1.0);//u_scanline_height.x); + float ScanBrightness = (ScanSineScaled * u_scanline_bright_scale.x + 1.0 + u_scanline_bright_offset.x) * 0.5; + + BaseColor.rgb *= mix(vec3(1.0, 1.0, 1.0), vec3(ScanBrightness, ScanBrightness, ScanBrightness), u_scanline_alpha.xxx); + } + + // Hum Bar Simulation (may not affect vector screen) + if (u_prepare_vector.x == 0.0 && u_humbar_alpha.x > 0.0f) + { + float HumTimeStep = fract(u_time.x * 0.001); + float HumBrightness = 1.0 - fract(BaseCoord.y + HumTimeStep) * u_humbar_alpha.x; + BaseColor.rgb *= HumBrightness; + } + } + + vec4 Output = u_prepare_vector.x > 0.0 ? BaseColor * (v_color0 + vec4(1.0, 1.0, 1.0, 0.0)) : BaseColor * v_color0; + Output.a = 1.0; + + gl_FragColor = Output; +} diff --git a/src/osd/modules/render/bgfx/fs_ratios.sc b/src/osd/modules/render/bgfx/fs_ratios.sc deleted file mode 100644 index c45050d4a4f..00000000000 --- a/src/osd/modules/render/bgfx/fs_ratios.sc +++ /dev/null @@ -1,23 +0,0 @@ -$input v_color0, v_texcoord0 - -// license:BSD-3-Clause -// copyright-holders:Dario Manesku - -#include "../../../../../3rdparty/bgfx/examples/common/common.sh" - -uniform vec4 u_ratio_amount; -uniform vec4 u_red_ratios; -uniform vec4 u_grn_ratios; -uniform vec4 u_blu_ratios; - -SAMPLER2D(s_tex, 0); - -void main() -{ - vec4 texel = texture2D(s_tex, v_texcoord0); - float red = dot(texel.rgb, u_red_ratios.rgb); - float grn = dot(texel.rgb, u_grn_ratios.rgb); - float blu = dot(texel.rgb, u_blu_ratios.rgb); - vec3 mixed = mix(texel.rgb, vec3(red, grn, blu), u_ratio_amount.x); - gl_FragColor = vec4(mixed, texel.a) * v_color0; -} diff --git a/src/osd/modules/render/bgfx/fs_screen.sc b/src/osd/modules/render/bgfx/fs_screen.sc index 59c2916039e..cecf14b4730 100644 --- a/src/osd/modules/render/bgfx/fs_screen.sc +++ b/src/osd/modules/render/bgfx/fs_screen.sc @@ -5,12 +5,10 @@ $input v_color0, v_texcoord0 #include "../../../../../3rdparty/bgfx/examples/common/common.sh" +// Samplers SAMPLER2D(s_tex, 0); -uniform vec4 u_tint; - void main() { - vec4 texel = texture2D(s_tex, v_texcoord0); - gl_FragColor = texel * v_color0 * u_tint; + gl_FragColor = texture2D(s_tex, v_texcoord0) * v_color0; } diff --git a/src/osd/modules/render/bgfx/fs_tint.sc b/src/osd/modules/render/bgfx/fs_tint.sc deleted file mode 100644 index 3e79f1e16e6..00000000000 --- a/src/osd/modules/render/bgfx/fs_tint.sc +++ /dev/null @@ -1,16 +0,0 @@ -$input v_color0, v_texcoord0 - -// license:BSD-3-Clause -// copyright-holders:Dario Manesku - -#include "../../../../../3rdparty/bgfx/examples/common/common.sh" - -uniform vec4 u_tint; -uniform vec4 u_shift; - -SAMPLER2D(s_tex, 0); - -void main() -{ - gl_FragColor = texture2D(s_tex, v_texcoord0 + u_shift.xy) * u_tint * v_color0; -} diff --git a/src/osd/modules/render/bgfx/inputpair.cpp b/src/osd/modules/render/bgfx/inputpair.cpp index e28372db3ce..24a4b101c5c 100644 --- a/src/osd/modules/render/bgfx/inputpair.cpp +++ b/src/osd/modules/render/bgfx/inputpair.cpp @@ -9,18 +9,29 @@ // //============================================================ +#include "emu.h" + #include "inputpair.h" #include "texture.h" +#include "target.h" #include "effect.h" +#include "uniform.h" +#include "texturemanager.h" -bgfx_input_pair::bgfx_input_pair(int index, std::string sampler, bgfx_texture* texture) +bgfx_input_pair::bgfx_input_pair(int index, std::string sampler, std::string texture) : m_index(index) , m_sampler(sampler) , m_texture(texture) { } -void bgfx_input_pair::bind(bgfx_effect *effect) +void bgfx_input_pair::bind(bgfx_effect *effect, texture_manager& textures, const int32_t screen) const { - bgfx::setTexture(m_index, effect->uniform(m_sampler)->handle(), m_texture->handle()); + assert(effect->uniform(m_sampler) != nullptr); + std::string texture = m_texture; + if (m_texture == "previous") + { + texture = m_texture + std::to_string(screen); + } + bgfx::setTexture(m_index, effect->uniform(m_sampler)->handle(), textures.handle(texture)); } diff --git a/src/osd/modules/render/bgfx/inputpair.h b/src/osd/modules/render/bgfx/inputpair.h index 196165c69f4..c4664beb2b9 100644 --- a/src/osd/modules/render/bgfx/inputpair.h +++ b/src/osd/modules/render/bgfx/inputpair.h @@ -14,24 +14,26 @@ #ifndef __DRAWBGFX_INPUT_PAIR__ #define __DRAWBGFX_INPUT_PAIR__ -#include <bgfx/bgfx.h> - #include <string> class bgfx_effect; -class bgfx_texture; +class texture_manager; class bgfx_input_pair { public: - bgfx_input_pair(int index, std::string sampler, bgfx_texture* texture); + 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); + // Getters + std::string sampler() const { return m_sampler; } + std::string texture() const { return m_texture; } private: - int m_index; - std::string m_sampler; - bgfx_texture* m_texture; + int m_index; + std::string m_sampler; + std::string m_texture; }; #endif // __DRAWBGFX_INPUT_PAIR__ diff --git a/src/osd/modules/render/bgfx/parameter.cpp b/src/osd/modules/render/bgfx/parameter.cpp deleted file mode 100644 index 004d5fd17f8..00000000000 --- a/src/osd/modules/render/bgfx/parameter.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -//============================================================ -// -// parameter.cpp - BGFX shader parameter -// -// A value that represents some form of parametric -// operation, which can be fed to the input of a BGFX -// shader uniform. -// -//============================================================ - -#include "emu.h" - -// NB: NOT FINISHED! - -#include "parameter.h" - -bgfx_parameter::bgfx_parameter(std::string name, parameter_type type, int period) - : m_name(name) - , m_type(type) - , m_period(period) - , m_frame(0) -{ -} - -bgfx_parameter::~bgfx_parameter() -{ -} - -void bgfx_parameter::frame() -{ - switch(m_type) - { - case PARAM_FRAME_MASK: - m_frame++; - if (m_frame == m_period) - { - m_frame = 0; - } - break; - default: - break; - } -} - -bool bgfx_parameter::active() -{ - switch (m_type) - { - case PARAM_FRAME_MASK: - return (m_frame % m_period == 0); - default: - return false; - } -} diff --git a/src/osd/modules/render/bgfx/parameter.h b/src/osd/modules/render/bgfx/parameter.h index b31b25d8a75..6a74efd887c 100644 --- a/src/osd/modules/render/bgfx/parameter.h +++ b/src/osd/modules/render/bgfx/parameter.h @@ -17,27 +17,28 @@ #include <string> -#include "emu.h" - class bgfx_parameter { public: enum parameter_type { - PARAM_FRAME_MASK + PARAM_FRAME, + PARAM_WINDOW, + PARAM_TIME }; - bgfx_parameter(std::string name, parameter_type type, int period); - ~bgfx_parameter(); + bgfx_parameter(std::string name, parameter_type type) : m_name(name), m_type(type) { } + virtual ~bgfx_parameter() { } + + virtual void tick(double delta) = 0; - void frame(); - bool active(); + // Getters + virtual float value() = 0; + std::string name() const { return m_name; } -private: - std::string m_name; - parameter_type m_type; - UINT32 m_period; - UINT32 m_frame; +protected: + std::string m_name; + parameter_type m_type; }; #endif // __DRAWBGFX_PARAMETER__ diff --git a/src/osd/modules/render/bgfx/paramreader.cpp b/src/osd/modules/render/bgfx/paramreader.cpp index 39a995a1489..f8225c39457 100644 --- a/src/osd/modules/render/bgfx/paramreader.cpp +++ b/src/osd/modules/render/bgfx/paramreader.cpp @@ -11,28 +11,55 @@ #include "paramreader.h" #include "parameter.h" +#include "frameparameter.h" +#include "windowparameter.h" +#include "timeparameter.h" const parameter_reader::string_to_enum parameter_reader::TYPE_NAMES[parameter_reader::TYPE_COUNT] = { - { "frame_mask", uint64_t(bgfx_parameter::parameter_type::PARAM_FRAME_MASK) } + { "frame", bgfx_parameter::parameter_type::PARAM_FRAME }, + { "window", bgfx_parameter::parameter_type::PARAM_WINDOW }, + { "time", bgfx_parameter::parameter_type::PARAM_TIME } }; -bgfx_parameter* parameter_reader::read_from_value(const Value& value) +bgfx_parameter* parameter_reader::read_from_value(const Value& value, std::string prefix, uint32_t window_index) { - validate_parameters(value); + if (!validate_parameters(value, prefix)) + { + return nullptr; + } std::string name = value["name"].GetString(); - bgfx_parameter::parameter_type type = bgfx_parameter::parameter_type(get_enum_from_value(value, "type", uint64_t(bgfx_parameter::parameter_type::PARAM_FRAME_MASK), TYPE_NAMES, TYPE_COUNT)); - int period = int(value["period"].GetDouble()); + bgfx_parameter::parameter_type type = bgfx_parameter::parameter_type(get_enum_from_value(value, "type", bgfx_parameter::parameter_type::PARAM_FRAME, TYPE_NAMES, TYPE_COUNT)); - return new bgfx_parameter(name, type, period); + if (type == bgfx_parameter::parameter_type::PARAM_FRAME) + { + uint32_t period = int(value["period"].GetDouble()); + return new bgfx_frame_parameter(name, type, period); + } + else if (type == bgfx_parameter::parameter_type::PARAM_WINDOW) + { + return new bgfx_window_parameter(name, type, window_index); + } + else if (type == bgfx_parameter::parameter_type::PARAM_TIME) + { + float limit = float(value["limit"].GetDouble()); + return new bgfx_time_parameter(name, type, limit); + } + else + { + READER_CHECK(false, (prefix + "Unknown parameter type '" + std::string(value["type"].GetString()) + "'\n").c_str()); + } + + return nullptr; } -void parameter_reader::validate_parameters(const Value& value) +bool parameter_reader::validate_parameters(const Value& value, std::string prefix) { - assert(value.HasMember("name")); - assert(value["name"].IsString()); - assert(value.HasMember("type")); - assert(value["type"].IsString()); - assert(value.HasMember("period")); - assert(value["period"].IsDouble()); + if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false; + if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("type"), (prefix + "Must have string value 'type'\n").c_str())) return false; + if (!READER_CHECK(value["type"].IsString(), (prefix + "Value 'type' must be a string\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("period") || value["period"].IsNumber(), (prefix + "Value 'period' must be numeric\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("limit") || value["limit"].IsNumber(), (prefix + "Value 'period' must be numeric\n").c_str())) return false; + return true; } diff --git a/src/osd/modules/render/bgfx/paramreader.h b/src/osd/modules/render/bgfx/paramreader.h index 4b31db52528..5b48c08251a 100644 --- a/src/osd/modules/render/bgfx/paramreader.h +++ b/src/osd/modules/render/bgfx/paramreader.h @@ -18,13 +18,13 @@ class bgfx_parameter; class parameter_reader : public state_reader { public: - static bgfx_parameter* read_from_value(const Value& value); + static bgfx_parameter* read_from_value(const Value& value, std::string prefix, uint32_t window_index); private: - static void validate_parameters(const Value& value); + static bool validate_parameters(const Value& value, std::string prefix); - static const int TYPE_COUNT = 1; - static const string_to_enum TYPE_NAMES[TYPE_COUNT]; + static const int TYPE_COUNT = 3; + static const string_to_enum TYPE_NAMES[TYPE_COUNT]; }; #endif // __DRAWBGFX_PARAM_READER__ diff --git a/src/osd/modules/render/bgfx/paramuniform.cpp b/src/osd/modules/render/bgfx/paramuniform.cpp new file mode 100644 index 00000000000..c318f2ff01c --- /dev/null +++ b/src/osd/modules/render/bgfx/paramuniform.cpp @@ -0,0 +1,23 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// paramuniform.cpp - BGFX shader chain parametric uniform +// +//============================================================ + +#include "paramuniform.h" + +#include "parameter.h" + +bgfx_param_uniform::bgfx_param_uniform(bgfx_uniform* uniform, bgfx_parameter* param) + : bgfx_entry_uniform(uniform) + , m_param(param) +{ +} + +void bgfx_param_uniform::bind() +{ + float value = m_param->value(); + m_uniform->set(&value, sizeof(float)); +} diff --git a/src/osd/modules/render/bgfx/paramuniform.h b/src/osd/modules/render/bgfx/paramuniform.h new file mode 100644 index 00000000000..b49fb2c7d61 --- /dev/null +++ b/src/osd/modules/render/bgfx/paramuniform.h @@ -0,0 +1,29 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// paramuniform.h - BGFX shader chain parametric uniform +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_PARAM_UNIFORM__ +#define __DRAWBGFX_PARAM_UNIFORM__ + +#include "entryuniform.h" + +class bgfx_parameter; + +class bgfx_param_uniform : public bgfx_entry_uniform +{ +public: + bgfx_param_uniform(bgfx_uniform* uniform, bgfx_parameter* param); + + virtual void bind() override; + +private: + bgfx_parameter* m_param; +}; + +#endif // __DRAWBGFX_PARAM_UNIFORM__ diff --git a/src/osd/modules/render/bgfx/paramuniformreader.cpp b/src/osd/modules/render/bgfx/paramuniformreader.cpp new file mode 100644 index 00000000000..704b79b204f --- /dev/null +++ b/src/osd/modules/render/bgfx/paramuniformreader.cpp @@ -0,0 +1,32 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//==================================================================== +// +// paramuniformreader.cpp - BGFX chain entry parameter mapper reader +// +//==================================================================== + +#include "paramuniformreader.h" + +#include "entryuniform.h" +#include "paramuniform.h" +#include "parameter.h" + +bgfx_entry_uniform* param_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_parameter*>& params) +{ + if (!validate_parameters(value, prefix)) + { + return nullptr; + } + + std::string parameter = value["parameter"].GetString(); + + return new bgfx_param_uniform(uniform, params[parameter]); +} + +bool param_uniform_reader::validate_parameters(const Value& value, std::string prefix) +{ + if (!READER_CHECK(value.HasMember("parameter"), (prefix + "Must have string value 'parameter' (what parameter is being mapped?)\n").c_str())) return false; + if (!READER_CHECK(value["parameter"].IsString(), (prefix + "Value 'parameter' must be a string\n").c_str())) return false; + return true; +} diff --git a/src/osd/modules/render/bgfx/paramuniformreader.h b/src/osd/modules/render/bgfx/paramuniformreader.h new file mode 100644 index 00000000000..baf281b562b --- /dev/null +++ b/src/osd/modules/render/bgfx/paramuniformreader.h @@ -0,0 +1,32 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//================================================================== +// +// paramuniformreader.h - BGFX chain entry parameter mapper reader +// +//================================================================== + +#pragma once + +#ifndef __DRAWBGFX_PARAM_UNIFORM_READER__ +#define __DRAWBGFX_PARAM_UNIFORM_READER__ + +#include <string> +#include <map> + +#include "statereader.h" + +class bgfx_entry_uniform; +class bgfx_uniform; +class bgfx_parameter; + +class param_uniform_reader : public state_reader +{ +public: + static bgfx_entry_uniform* read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_parameter*>& params); + +private: + static bool validate_parameters(const Value& value, std::string prefix); +}; + +#endif // __DRAWBGFX_PARAM_UNIFORM_READER__ diff --git a/src/osd/modules/render/bgfx/shadermanager.cpp b/src/osd/modules/render/bgfx/shadermanager.cpp index 93a7205b93c..3d9479a228a 100644 --- a/src/osd/modules/render/bgfx/shadermanager.cpp +++ b/src/osd/modules/render/bgfx/shadermanager.cpp @@ -39,29 +39,34 @@ bgfx::ShaderHandle shader_manager::shader(std::string name) return load_shader(name); } -bgfx::ShaderHandle shader_manager::load_shader(std::string name) { - std::string shader_path = "shaders/dx9/"; +bgfx::ShaderHandle shader_manager::load_shader(std::string name) +{ + std::string shader_path; switch (bgfx::getRendererType()) { - case bgfx::RendererType::Direct3D11: - case bgfx::RendererType::Direct3D12: - shader_path = "shaders/dx11/"; - break; + case bgfx::RendererType::Direct3D9: + shader_path = m_options.bgfx_path() + std::string("/shaders/dx9/"); + break; + + case bgfx::RendererType::Direct3D11: + case bgfx::RendererType::Direct3D12: + shader_path = m_options.bgfx_path() + std::string("/shaders/dx11/"); + break; - case bgfx::RendererType::OpenGL: - shader_path = "shaders/glsl/"; - break; + case bgfx::RendererType::OpenGL: + shader_path = m_options.bgfx_path() + std::string("/shaders/glsl/"); + break; - case bgfx::RendererType::Metal: - shader_path = "shaders/metal/"; - break; + case bgfx::RendererType::Metal: + shader_path = m_options.bgfx_path() + std::string("/shaders/metal/"); + break; - case bgfx::RendererType::OpenGLES: - shader_path = "shaders/gles/"; - break; + case bgfx::RendererType::OpenGLES: + shader_path = m_options.bgfx_path() + std::string("/shaders/gles/"); + break; - default: - break; + default: + fatalerror("Unknown BGFX renderer type %d", bgfx::getRendererType()); } bgfx::ShaderHandle handle = bgfx::createShader(load_mem(shader_path + name + ".bin")); @@ -71,7 +76,8 @@ bgfx::ShaderHandle shader_manager::load_shader(std::string name) { return handle; } -const bgfx::Memory* shader_manager::load_mem(std::string name) { +const bgfx::Memory* shader_manager::load_mem(std::string name) +{ bx::CrtFileReader reader; bx::open(&reader, name.c_str()); diff --git a/src/osd/modules/render/bgfx/shadermanager.h b/src/osd/modules/render/bgfx/shadermanager.h index 5cc971ca829..18c95bf6238 100644 --- a/src/osd/modules/render/bgfx/shadermanager.h +++ b/src/osd/modules/render/bgfx/shadermanager.h @@ -14,14 +14,17 @@ #ifndef __DRAWBGFX_SHADER_MANAGER__ #define __DRAWBGFX_SHADER_MANAGER__ +#include <bgfx/bgfx.h> + +#include <modules/lib/osdobj_common.h> + #include <map> #include <string> -#include <bgfx/bgfx.h> class shader_manager { public: - shader_manager() {} + shader_manager(osd_options& options) : m_options(options) { } ~shader_manager(); // Getters @@ -31,7 +34,8 @@ private: bgfx::ShaderHandle load_shader(std::string name); static const bgfx::Memory* load_mem(std::string name); - std::map<std::string, bgfx::ShaderHandle> m_shaders; + std::map<std::string, bgfx::ShaderHandle> m_shaders; + osd_options& m_options; }; #endif // __DRAWBGFX_SHADER_MANAGER__ diff --git a/src/osd/modules/render/bgfx/slider.cpp b/src/osd/modules/render/bgfx/slider.cpp index 76f093580bd..355b0c2a30a 100644 --- a/src/osd/modules/render/bgfx/slider.cpp +++ b/src/osd/modules/render/bgfx/slider.cpp @@ -9,51 +9,119 @@ #include "emu.h" #include "slider.h" +#include "ui/ui.h" -bgfx_slider::bgfx_slider(slider_type type, std::string name, std::string description, void *defaults, void *min, void *max) - : m_type(type) - , m_name(name) +bgfx_slider::bgfx_slider(running_machine &machine, std::string name, int32_t min, int32_t def, int32_t max, int32_t step, slider_type type, screen_type screen, float scale, std::string format, std::string description, std::vector<std::string>& strings) + : m_name(name) + , m_step(step) + , m_type(type) + , m_screen_type(screen) + , m_scale(scale) + , m_format(format) , m_description(description) { - m_data = global_alloc_array_clear<char>(storage_size(type)); - m_min = global_alloc_array_clear<char>(storage_size(type)); - m_max = global_alloc_array_clear<char>(storage_size(type)); - memcpy(m_data, defaults, size(type)); - memcpy(m_min, min, size(type)); - memcpy(m_max, max, size(type)); + m_min = min; + m_default = def; + m_max = max; + + m_value = def; + if (m_type != slider_type::SLIDER_INT && m_type != slider_type::SLIDER_INT_ENUM) + { + m_value = float(def) * scale; + } + + for (std::string string : strings) + { + m_strings.push_back(string); + } + + m_slider_state = create_core_slider(machine); } bgfx_slider::~bgfx_slider() { - global_free(m_data); - global_free(m_min); - global_free(m_max); } -size_t bgfx_slider::storage_size(slider_type type) +static INT32 update_trampoline(running_machine &machine, void *arg, std::string *str, INT32 newval) { - switch(type) - { - case SLIDER_INT: - return 1 * sizeof(int); - case SLIDER_BOOL: - case SLIDER_FLOAT: - case SLIDER_COLOR: - case SLIDER_VEC2: - return 4 * sizeof(float); - default: - return 0; - } + if (arg != nullptr) + { + return reinterpret_cast<bgfx_slider*>(arg)->update(str, newval); + } + return 0; } -size_t bgfx_slider::size(slider_type type) +slider_state* bgfx_slider::create_core_slider(running_machine& machine) +{ + int size = sizeof(slider_state) + m_description.length(); + slider_state *state = reinterpret_cast<slider_state *>(auto_alloc_array_clear(machine, UINT8, size)); + + state->minval = m_min; + state->defval = m_default; + state->maxval = m_max; + state->incval = m_step; + state->update = update_trampoline; + state->arg = this; + state->id = 0; // fixme + strcpy(state->description, m_description.c_str()); + + return state; +} + +int32_t bgfx_slider::update(std::string *str, int32_t newval) +{ + switch (m_type) + { + case SLIDER_INT_ENUM: + { + if (newval != SLIDER_NOCHANGE) + { + m_value = float(newval); + } + if (str != nullptr) + { + *str = string_format(m_format, m_strings[as_int()]); + } + return as_int(); + } + + case SLIDER_INT: + { + if (newval != SLIDER_NOCHANGE) + { + m_value = float(newval); + } + if (str != nullptr) + { + *str = string_format(m_format, as_int()); + } + return as_int(); + } + + default: + { + float *val_ptr = reinterpret_cast<float *>(&m_value); + if (newval != SLIDER_NOCHANGE) + { + *val_ptr = float(newval) * m_scale; + } + if (str != nullptr) + { + *str = string_format(m_format, *val_ptr); + } + return int32_t(floor(*val_ptr / m_scale + 0.5f)); + } + } + return 0; +} + +size_t bgfx_slider::get_size_for_type(slider_type type) { switch(type) { - case SLIDER_INT: - return sizeof(int); - case SLIDER_BOOL: + case SLIDER_INT_ENUM: case SLIDER_FLOAT: + case SLIDER_INT: return sizeof(float); case SLIDER_COLOR: return sizeof(float) * 3; diff --git a/src/osd/modules/render/bgfx/slider.h b/src/osd/modules/render/bgfx/slider.h index efff831a4da..5ba8427a54d 100644 --- a/src/osd/modules/render/bgfx/slider.h +++ b/src/osd/modules/render/bgfx/slider.h @@ -15,35 +15,66 @@ #include <string> #include <vector> -#include <map> -#include "uniform.h" +#include "emu.h" +#include "ui/ui.h" class bgfx_slider { public: enum slider_type { - SLIDER_BOOL, + SLIDER_INT_ENUM, SLIDER_FLOAT, SLIDER_INT, SLIDER_COLOR, SLIDER_VEC2 }; - bgfx_slider(slider_type type, std::string name, std::string description, void *defaults, void *min, void *max); + enum screen_type + { + SLIDER_SCREEN_TYPE_NONE = 0, + SLIDER_SCREEN_TYPE_RASTER = 1, + SLIDER_SCREEN_TYPE_VECTOR = 2, + SLIDER_SCREEN_TYPE_VECTOR_OR_RASTER = SLIDER_SCREEN_TYPE_VECTOR | SLIDER_SCREEN_TYPE_RASTER, + SLIDER_SCREEN_TYPE_LCD = 4, + SLIDER_SCREEN_TYPE_LCD_OR_RASTER = SLIDER_SCREEN_TYPE_LCD | SLIDER_SCREEN_TYPE_RASTER, + SLIDER_SCREEN_TYPE_LCD_OR_VECTOR = SLIDER_SCREEN_TYPE_LCD | SLIDER_SCREEN_TYPE_VECTOR, + SLIDER_SCREEN_TYPE_ANY = SLIDER_SCREEN_TYPE_RASTER | SLIDER_SCREEN_TYPE_VECTOR | SLIDER_SCREEN_TYPE_LCD + }; + + bgfx_slider(running_machine& machine, std::string name, int32_t min, int32_t def, int32_t max, int32_t step, slider_type type, screen_type screen, float scale, std::string format, std::string description, std::vector<std::string>& strings); ~bgfx_slider(); - static size_t size(slider_type type); - static size_t storage_size(slider_type type); + int32_t update(std::string *str, int32_t newval); + + // Getters + std::string name() const { return m_name; } + slider_type type() const { return m_type; } + float value() const { return m_value; } + float uniform_value() const { return float(m_value); } + slider_state* core_slider() const { return m_slider_state; } + size_t size() const { return get_size_for_type(m_type); } + + static size_t get_size_for_type(slider_type type); + protected: + slider_state* create_core_slider(running_machine &machine); + int32_t as_int() const { return int32_t(floor(m_value + 0.5f)); } - slider_type m_type; - std::string m_name; - std::string m_description; - char* m_data; - char* m_min; - char* m_max; + std::string m_name; + int32_t m_min; + int32_t m_default; + int32_t m_max; + int32_t m_step; + slider_type m_type; + screen_type m_screen_type; + float m_scale; + std::string m_format; + std::string m_description; + std::vector<std::string> m_strings; + float m_value; + slider_state* m_slider_state; }; #endif // __DRAWBGFX_SLIDER__ diff --git a/src/osd/modules/render/bgfx/sliderreader.cpp b/src/osd/modules/render/bgfx/sliderreader.cpp index 2cd56d52457..fbc9fd253aa 100644 --- a/src/osd/modules/render/bgfx/sliderreader.cpp +++ b/src/osd/modules/render/bgfx/sliderreader.cpp @@ -6,69 +6,160 @@ // //============================================================== -#include "emu.h" - #include "sliderreader.h" +#include "emu.h" #include "slider.h" const slider_reader::string_to_enum slider_reader::TYPE_NAMES[slider_reader::TYPE_COUNT] = { - { "bool", uint64_t(bgfx_slider::slider_type::SLIDER_BOOL) }, - { "float", uint64_t(bgfx_slider::slider_type::SLIDER_FLOAT) }, - { "int", uint64_t(bgfx_slider::slider_type::SLIDER_INT) }, - { "color", uint64_t(bgfx_slider::slider_type::SLIDER_COLOR) }, - { "vec2", uint64_t(bgfx_slider::slider_type::SLIDER_VEC2) } + { "int_enum", uint64_t(bgfx_slider::slider_type::SLIDER_INT_ENUM) }, + { "float", uint64_t(bgfx_slider::slider_type::SLIDER_FLOAT) }, + { "int", uint64_t(bgfx_slider::slider_type::SLIDER_INT) }, + { "color", uint64_t(bgfx_slider::slider_type::SLIDER_COLOR) }, + { "vec2", uint64_t(bgfx_slider::slider_type::SLIDER_VEC2) } }; -bgfx_slider* slider_reader::read_from_value(const Value& value) +const slider_reader::string_to_enum slider_reader::SCREEN_NAMES[slider_reader::SCREEN_COUNT] = { + { "none", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_NONE) }, + { "raster", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_RASTER) }, + { "vector", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_VECTOR) }, + { "crt", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_VECTOR_OR_RASTER) }, + { "vector_raster", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_VECTOR_OR_RASTER) }, + { "lcd", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_LCD) }, + { "non_vector", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_LCD_OR_RASTER) }, + { "lcd_raster", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_LCD_OR_RASTER) }, + { "lcd_vector", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_LCD_OR_VECTOR) }, + { "any", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_ANY) }, + { "all", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_ANY) } +}; + +std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, std::string prefix, running_machine& machine, uint32_t window_index) { - validate_parameters(value); + std::vector<bgfx_slider*> sliders; + + if (!validate_parameters(value, prefix)) + { + return sliders; + } - bgfx_slider::slider_type type = bgfx_slider::slider_type(get_enum_from_value(value, "type", uint64_t(bgfx_slider::slider_type::SLIDER_FLOAT), TYPE_NAMES, TYPE_COUNT)); std::string name = value["name"].GetString(); + int step = value["step"].GetInt(); + bgfx_slider::slider_type type = bgfx_slider::slider_type(get_enum_from_value(value, "type", uint64_t(bgfx_slider::slider_type::SLIDER_FLOAT), TYPE_NAMES, TYPE_COUNT)); + bgfx_slider::screen_type screen_type = bgfx_slider::screen_type(get_enum_from_value(value, "screen", uint64_t(bgfx_slider::screen_type::SLIDER_SCREEN_TYPE_ANY), SCREEN_NAMES, SCREEN_COUNT)); + float scale = value["scale"].GetFloat(); + std::string format = value["format"].GetString(); std::string description = value["text"].GetString(); - float defaults[4]; - float min[4]; - float max[4]; - get_values(value, "default", defaults); - get_values(value, "min", min); - get_values(value, "max", max); + std::vector<std::string> strings; + if (value.HasMember("strings")) + { + const Value& string_array = value["strings"]; + for (UINT32 i = 0; i < string_array.Size(); i++) + { + if (!READER_CHECK(string_array[i].IsString(), (prefix + "Slider '" + name + "': strings[" + std::to_string(i) + "]: must be a string\n").c_str())) + { + return sliders; + } + strings.push_back(std::string(string_array[i].GetString())); + } + } + + int slider_count; + switch (type) + { + case bgfx_slider::slider_type::SLIDER_FLOAT: + case bgfx_slider::slider_type::SLIDER_INT: + case bgfx_slider::slider_type::SLIDER_INT_ENUM: + slider_count = 1; + break; + case bgfx_slider::slider_type::SLIDER_VEC2: + slider_count = 2; + break; + case bgfx_slider::slider_type::SLIDER_COLOR: + slider_count = 3; + break; + default: + slider_count = 0; + break; + } - return new bgfx_slider(type, name, description, defaults, min, max); + if (slider_count > 1) + { + int min[3]; + int defaults[3]; + int max[3]; + if (!READER_CHECK(value["min"].IsArray(), (prefix + "Slider '" + name + "': value 'min' must be an array\n").c_str())) return sliders; + if (!READER_CHECK(value["default"].IsArray(), (prefix + "Slider '" + name + "': value 'default' must be an array\n").c_str())) return sliders; + if (!READER_CHECK(value["max"].IsArray(), (prefix + "Slider '" + name + "': value 'max' must be an array\n").c_str())) return sliders; + get_values(value, prefix + "Slider '" + name + "': 'min': ", "min", min, slider_count); + get_values(value, prefix + "Slider '" + name + "': 'default': ", "default", defaults, slider_count); + get_values(value, prefix + "Slider '" + name + "': 'max': ", "max", max, slider_count); + for (int index = 0; index < slider_count; index++) + { + std::string desc; + std::string full_name = name + std::to_string(index); + switch (index) + { + case 0: + desc = "Window " + std::to_string(window_index) + ", " + description + (type == bgfx_slider::slider_type::SLIDER_VEC2 ? "X" : "Red"); + break; + case 1: + desc = "Window " + std::to_string(window_index) + ", " + description + (type == bgfx_slider::slider_type::SLIDER_VEC2 ? "Y" : "Green"); + break; + case 2: + desc = "Window " + std::to_string(window_index) + ", " + description + (type == bgfx_slider::slider_type::SLIDER_VEC2 ? "Invalid" : "Blue"); + break; + default: + desc = "Window " + std::to_string(window_index) + ", " + description + "Invalid"; + break; + } + sliders.push_back(new bgfx_slider(machine, full_name, min[index], defaults[index], max[index], step, type, screen_type, scale, format, desc, strings)); + } + } + else + { + int min = get_int(value, "min", 0); + int def = get_int(value, "default", 0); + int max = get_int(value, "max", 100); + sliders.push_back(new bgfx_slider(machine, name + "0", min, def, max, step, type, screen_type, scale, format, "Window " + std::to_string(window_index) + ", " + description, strings)); + } + return sliders; } -void slider_reader::get_values(const Value& value, std::string name, float* values) +bool slider_reader::get_values(const Value& value, std::string prefix, std::string name, int* values, const int count) { const char* name_str = name.c_str(); - if (value.HasMember(name_str)) + const Value& value_array = value[name_str]; + for (UINT32 i = 0; i < value_array.Size() && i < count; i++) { - if (value[name_str].IsBool()) - { - values[0] = value[name_str].GetBool() ? 1.0f : 0.0f; - } - else if (value[name_str].IsDouble()) - { - values[0] = float(value[name_str].GetDouble()); - } - else - { - const Value& value_array = value[name_str]; - for (UINT32 i = 0; i < value_array.Size() && i < 4; i++) - { - values[i] = float(value_array[i].GetDouble()); - } - } + if (!READER_CHECK(value_array[i].IsInt(), (prefix + "Entry " + std::to_string(i) + " must be an integer\n").c_str())) return false; + values[i] = value_array[i].GetInt(); } + return true; } -void slider_reader::validate_parameters(const Value& value) +bool slider_reader::validate_parameters(const Value& value, std::string prefix) { - assert(value.HasMember("type")); - assert(value["type"].IsString()); - assert(value.HasMember("name")); - assert(value["name"].IsString()); - assert(value.HasMember("text")); - assert(value["text"].IsString()); - assert(value.HasMember("default")); + if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false; + if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("min"), (prefix + "Must have integer or array value 'min'\n").c_str())) return false; + if (!READER_CHECK(value["min"].IsInt() || value["min"].IsArray(), (prefix + "Value 'min' must be an integer or an array the size of the corresponding slider type\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("default"), (prefix + "Must have integer or array value 'default'\n").c_str())) return false; + if (!READER_CHECK(value["default"].IsInt() || value["default"].IsArray(), (prefix + "Value 'default' must be an integer or an array the size of the corresponding slider type\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("max"), (prefix + "Must have integer or array value 'max'\n").c_str())) return false; + if (!READER_CHECK(value["max"].IsInt() || value["max"].IsArray(), (prefix + "Value 'max' must be an integer or an array the size of the corresponding slider type\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("step"), (prefix + "Must have integer value 'step'\n").c_str())) return false; + if (!READER_CHECK(value["step"].IsInt(), (prefix + "Value 'step' must be an integer (how much does this slider increment by internally?)\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("type"), (prefix + "Must have string value 'type'\n").c_str())) return false; + if (!READER_CHECK(value["type"].IsString(), (prefix + "Value 'type' must be a string (what type of slider is this? [int_enum, int, float])\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("screen"), (prefix + "Must have string value 'screen'\n").c_str())) return false; + if (!READER_CHECK(value["screen"].IsString(), (prefix + "Value 'screen' must be a string (what type of output device does this slider apply to? [none, raster, vector, crt, lcd, non_vector, any])\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("scale"), (prefix + "Must have numeric value 'scale'\n").c_str())) return false; + if (!READER_CHECK(value["scale"].IsNumber(), (prefix + "Value 'scale' must be a number (what do we multiply with to get 1.0?)").c_str())) return false; + if (!READER_CHECK(value.HasMember("format"), (prefix + "Must have string value 'format'\n").c_str())) return false; + if (!READER_CHECK(value["format"].IsString(), (prefix + "Value 'scale' must be a string (how would we display it in a printf?)").c_str())) return false; + if (!READER_CHECK(value.HasMember("text"), (prefix + "Must have string value 'text'\n").c_str())) return false; + if (!READER_CHECK(value["text"].IsString(), (prefix + "Value 'text' must be a string (how would you explain it?)").c_str())) return false; + if (!READER_CHECK(!value.HasMember("strings") || value["strings"].IsArray(), (prefix + "Value 'strings' must be an array\n").c_str())) return false; + return true; } diff --git a/src/osd/modules/render/bgfx/sliderreader.h b/src/osd/modules/render/bgfx/sliderreader.h index 9140fded836..f6e42694fa9 100644 --- a/src/osd/modules/render/bgfx/sliderreader.h +++ b/src/osd/modules/render/bgfx/sliderreader.h @@ -11,21 +11,26 @@ #ifndef __DRAWBGFX_SLIDER_READER__ #define __DRAWBGFX_SLIDER_READER__ +#include <vector> + #include "statereader.h" class bgfx_slider; +class running_machine; class slider_reader : public state_reader { public: - static bgfx_slider* read_from_value(const Value& value); + static std::vector<bgfx_slider*> read_from_value(const Value& value, std::string prefix, running_machine& machine, uint32_t window_index); private: - static void get_values(const Value& value, std::string name, float* values); - static void validate_parameters(const Value& value); + static bool get_values(const Value& value, std::string prefix, std::string name, int* values, const int count); + static bool validate_parameters(const Value& value, std::string prefix); static const int TYPE_COUNT = 5; static const string_to_enum TYPE_NAMES[TYPE_COUNT]; + static const int SCREEN_COUNT = 11; + static const string_to_enum SCREEN_NAMES[SCREEN_COUNT]; }; #endif // __DRAWBGFX_SLIDER_READER__ diff --git a/src/osd/modules/render/bgfx/slideruniform.cpp b/src/osd/modules/render/bgfx/slideruniform.cpp new file mode 100644 index 00000000000..7a63b1e6901 --- /dev/null +++ b/src/osd/modules/render/bgfx/slideruniform.cpp @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// slideruniform.cpp - BGFX shader chain slider uniform +// +// Represents the mapping between a slider and a chain +// shader uniform for a given entry +// +//============================================================ + +#include "slideruniform.h" + +#include "slider.h" + +bgfx_slider_uniform::bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> sliders) + : bgfx_entry_uniform(uniform) +{ + for (bgfx_slider* slider : sliders) + { + m_sliders.push_back(slider); + } +} + +void bgfx_slider_uniform::bind() +{ + float values[4]; + for (uint32_t i = 0; i < m_sliders.size(); i++) + { + values[i] = m_sliders[i]->uniform_value(); + } + m_uniform->set(values, sizeof(float) * m_sliders.size()); +} diff --git a/src/osd/modules/render/bgfx/slideruniform.h b/src/osd/modules/render/bgfx/slideruniform.h new file mode 100644 index 00000000000..a2fa990dd1f --- /dev/null +++ b/src/osd/modules/render/bgfx/slideruniform.h @@ -0,0 +1,34 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// slideruniform.h - BGFX shader chain slider uniform +// +// Represents the mapping between a slider and a chain +// shader uniform for a given entry +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_SLIDER_UNIFORM__ +#define __DRAWBGFX_SLIDER_UNIFORM__ + +#include "entryuniform.h" + +#include <vector> + +class bgfx_slider; + +class bgfx_slider_uniform : public bgfx_entry_uniform +{ +public: + bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> sliders); + + virtual void bind() override; + +private: + std::vector<bgfx_slider*> m_sliders; +}; + +#endif // __DRAWBGFX_SLIDER_UNIFORM__ diff --git a/src/osd/modules/render/bgfx/slideruniformreader.cpp b/src/osd/modules/render/bgfx/slideruniformreader.cpp new file mode 100644 index 00000000000..95de126adf9 --- /dev/null +++ b/src/osd/modules/render/bgfx/slideruniformreader.cpp @@ -0,0 +1,46 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//================================================================== +// +// slideruniformreader.cpp - BGFX chain entry slider mapper reader +// +//================================================================== + +#include "slideruniformreader.h" + +#include <vector> + +#include "slideruniform.h" +#include "entryuniform.h" +#include "slider.h" + +bgfx_entry_uniform* slider_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_slider*>& sliders) +{ + if (!validate_parameters(value, prefix)) + { + return nullptr; + } + + std::string name = value["slider"].GetString(); + std::vector<bgfx_slider*> slider_list; + slider_list.push_back(sliders[name + "0"]); + + if (slider_list[0]->type() == bgfx_slider::slider_type::SLIDER_VEC2) + { + slider_list.push_back(sliders[name + "1"]); + } + else if (slider_list[0]->type() == bgfx_slider::slider_type::SLIDER_COLOR) + { + slider_list.push_back(sliders[name + "1"]); + slider_list.push_back(sliders[name + "2"]); + } + + return new bgfx_slider_uniform(uniform, slider_list); +} + +bool slider_uniform_reader::validate_parameters(const Value& value, std::string prefix) +{ + if (!READER_CHECK(value.HasMember("slider"), (prefix + "Must have string value 'slider' (what slider are we getting the value of?)\n").c_str())) return false; + if (!READER_CHECK(value["slider"].IsString(), (prefix + "Value 'slider' must be a string\n").c_str())) return false; + return true; +} diff --git a/src/osd/modules/render/bgfx/slideruniformreader.h b/src/osd/modules/render/bgfx/slideruniformreader.h new file mode 100644 index 00000000000..0db387270b0 --- /dev/null +++ b/src/osd/modules/render/bgfx/slideruniformreader.h @@ -0,0 +1,32 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//================================================================ +// +// slideruniformreader.h - BGFX chain entry slider mapper reader +// +//================================================================ + +#pragma once + +#ifndef __DRAWBGFX_SLIDER_UNIFORM_READER__ +#define __DRAWBGFX_SLIDER_UNIFORM_READER__ + +#include <string> +#include <map> + +#include "entryuniform.h" +#include "statereader.h" + +class bgfx_uniform; +class bgfx_slider; + +class slider_uniform_reader : public state_reader +{ +public: + static bgfx_entry_uniform* read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_slider*>& sliders); + +private: + static bool validate_parameters(const Value& value, std::string prefix); +}; + +#endif // __DRAWBGFX_SLIDER_UNIFORM_READER__ diff --git a/src/osd/modules/render/bgfx/statereader.cpp b/src/osd/modules/render/bgfx/statereader.cpp index 0a459c60102..0f5c0a2f88c 100644 --- a/src/osd/modules/render/bgfx/statereader.cpp +++ b/src/osd/modules/render/bgfx/statereader.cpp @@ -38,14 +38,22 @@ void state_reader::validate_array_parameter(const Value& value, std::string type } } -void state_reader::validate_double_parameter(const Value& value, std::string typeName, std::string name) +void state_reader::validate_float_parameter(const Value& value, std::string typeName, std::string name) { if (value.HasMember(name.c_str())) { - assert(value[name.c_str()].IsDouble()); + assert(value[name.c_str()].IsFloat()); } } +void state_reader::validate_int_parameter(const Value& value, std::string typeName, std::string name) +{ + if (value.HasMember(name.c_str())) + { + assert(value[name.c_str()].IsInt()); + } +} + void state_reader::validate_string_parameter(const Value& value, std::string typeName, std::string name) { if (value.HasMember(name.c_str())) @@ -71,6 +79,15 @@ bool state_reader::get_bool(const Value& value, const std::string name, const bo return default_value; } +int state_reader::get_int(const Value& value, const std::string name, const int default_value) +{ + if (value.HasMember(name.c_str())) + { + return int(floor(value[name.c_str()].GetDouble() + 0.5)); + } + return default_value; +} + void state_reader::get_float(const Value& value, const std::string name, float* out, float* default_value, int count) { if (value.HasMember(name.c_str())) diff --git a/src/osd/modules/render/bgfx/statereader.h b/src/osd/modules/render/bgfx/statereader.h index ce52536ca0a..5b9a5f5625d 100644 --- a/src/osd/modules/render/bgfx/statereader.h +++ b/src/osd/modules/render/bgfx/statereader.h @@ -22,17 +22,34 @@ protected: }; static void validate_array_parameter(const Value& value, std::string type_name, std::string name, const int count); - static void validate_double_parameter(const Value& value, std::string type_name, std::string name); - static void validate_string_parameter(const Value& value, std::string type_name, std::string name); + static void validate_float_parameter(const Value& value, std::string type_name, std::string name); + static void validate_int_parameter(const Value& value, std::string type_name, std::string name); + static void validate_string_parameter(const Value& value, std::string type_name, std::string name); static void validate_boolean_parameter(const Value& value, std::string type_name, std::string name); static bool get_bool(const Value& value, const std::string name, const bool default_value); - static void get_float(const Value& value, const std::string name, float* out, float* default_value, const int count = 1); - static std::string get_string(const Value& value, const std::string name, const std::string default_value); + static void get_float(const Value& value, const std::string name, float* out, float* default_value, const int count = 1); + static int get_int(const Value& value, const std::string name, int default_value); + static std::string get_string(const Value& value, const std::string name, const std::string default_value); static uint64_t get_enum_from_value(const Value& value, std::string name, const uint64_t default_value, const string_to_enum* enums, const int count); static uint64_t get_param_from_string(std::string value, const string_to_enum* enums, const int count); +protected: + static bool READER_CHECK(bool condition, const char* format, ...) + { + if (!condition) + { + va_list ap; + va_start(ap, format); + char buf[2048]; + vsnprintf(buf, 2048, format, ap); + osd_printf_error("Error: %s\n", buf); + va_end(ap); + } + return condition; + } + private: static void get_vec_values(const Value& value_array, float* data, const unsigned int count); }; diff --git a/src/osd/modules/render/bgfx/suppressor.cpp b/src/osd/modules/render/bgfx/suppressor.cpp new file mode 100644 index 00000000000..b01e0f94d04 --- /dev/null +++ b/src/osd/modules/render/bgfx/suppressor.cpp @@ -0,0 +1,57 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// suppressor.h - Conditionally suppress a bgfx chain entry +// from being processed. +// +//============================================================ + +#include "suppressor.h" + +#include "slider.h" + +bgfx_suppressor::bgfx_suppressor(std::vector<bgfx_slider*> sliders, uint32_t condition, combine_mode combine, void* value) + : m_sliders(sliders) + , m_condition(condition) + , m_combine(combine) + , m_value(nullptr) +{ + uint32_t size = sliders[0]->size(); + m_value = new uint8_t[size]; + memcpy(m_value, value, size); +} + +bgfx_suppressor::~bgfx_suppressor() +{ + delete [] m_value; +} + +bool bgfx_suppressor::suppress() +{ + int32_t count = 1; + if (m_sliders[0]->type() == bgfx_slider::slider_type::SLIDER_VEC2) + { + count = 2; + } + else if (m_sliders[0]->type() == bgfx_slider::slider_type::SLIDER_COLOR) + { + count = 3; + } + + float current_values[3]; + for (int32_t index = 0; index < count; index++) + { + current_values[index] = m_sliders[index]->value(); + } + + switch (m_condition) + { + case CONDITION_NOTEQUAL: + return memcmp(m_value, current_values, m_sliders[0]->size()) != 0; + case CONDITION_EQUAL: + return memcmp(m_value, current_values, m_sliders[0]->size()) == 0; + default: + return false; + } +} diff --git a/src/osd/modules/render/bgfx/suppressor.h b/src/osd/modules/render/bgfx/suppressor.h new file mode 100644 index 00000000000..93166eff693 --- /dev/null +++ b/src/osd/modules/render/bgfx/suppressor.h @@ -0,0 +1,51 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// suppressor.h - Conditionally suppress a bgfx chain entry +// from being processed. +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_SUPPRESSOR__ +#define __DRAWBGFX_SUPPRESSOR__ + +#include <bgfx/bgfx.h> + +#include <vector> + +class bgfx_slider; + +class bgfx_suppressor +{ +public: + enum condition_type + { + CONDITION_EQUAL, + CONDITION_NOTEQUAL, + + CONDITION_COUNT + }; + + enum combine_mode { + COMBINE_AND, + COMBINE_OR + }; + + bgfx_suppressor(std::vector<bgfx_slider*> sliders, uint32_t condition, combine_mode combine, void* value); + ~bgfx_suppressor(); + + // Getters + bool suppress(); + combine_mode combine() const { return m_combine; } + +private: + std::vector<bgfx_slider*> m_sliders; + uint32_t m_condition; + combine_mode m_combine; + uint8_t* m_value; +}; + +#endif // __DRAWBGFX_SUPPRESSOR__ diff --git a/src/osd/modules/render/bgfx/suppressorreader.cpp b/src/osd/modules/render/bgfx/suppressorreader.cpp new file mode 100644 index 00000000000..6d736a5a411 --- /dev/null +++ b/src/osd/modules/render/bgfx/suppressorreader.cpp @@ -0,0 +1,96 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// suppressorreader.cpp - Reads pass-skipping conditions +// +//============================================================ + +#include <string> + +#include "suppressorreader.h" + +#include "suppressor.h" +#include "slider.h" + +const suppressor_reader::string_to_enum suppressor_reader::CONDITION_NAMES[suppressor_reader::CONDITION_COUNT] = { + { "equal", bgfx_suppressor::condition_type::CONDITION_EQUAL }, + { "notequal", bgfx_suppressor::condition_type::CONDITION_NOTEQUAL } +}; + +const suppressor_reader::string_to_enum suppressor_reader::COMBINE_NAMES[suppressor_reader::COMBINE_COUNT] = { + { "and", bgfx_suppressor::combine_mode::COMBINE_AND }, + { "or", bgfx_suppressor::combine_mode::COMBINE_OR } +}; + +bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, std::string prefix, std::map<std::string, bgfx_slider*>& sliders) +{ + if (!validate_parameters(value, prefix)) + { + return nullptr; + } + + std::string name = value["name"].GetString(); + uint32_t condition = uint32_t(get_enum_from_value(value, "condition", bgfx_suppressor::condition_type::CONDITION_EQUAL, CONDITION_NAMES, CONDITION_COUNT)); + bgfx_suppressor::combine_mode mode = bgfx_suppressor::combine_mode(get_enum_from_value(value, "combine", bgfx_suppressor::combine_mode::COMBINE_OR, COMBINE_NAMES, COMBINE_COUNT)); + + std::vector<bgfx_slider*> check_sliders; + check_sliders.push_back(sliders[name + "0"]); + + int slider_count; + switch (check_sliders[0]->type()) + { + case bgfx_slider::slider_type::SLIDER_FLOAT: + case bgfx_slider::slider_type::SLIDER_INT: + case bgfx_slider::slider_type::SLIDER_INT_ENUM: + slider_count = 1; + break; + case bgfx_slider::slider_type::SLIDER_VEC2: + slider_count = 2; + break; + case bgfx_slider::slider_type::SLIDER_COLOR: + slider_count = 3; + break; + default: + slider_count = 0; + break; + } + + int values[4]; + if (slider_count > 1) + { + get_values(value, prefix, "value", values, slider_count); + if (!READER_CHECK(slider_count == value["value"].GetArray().Size(), (prefix + "Expected " + std::to_string(slider_count) + " values, got " + std::to_string(value["value"].GetArray().Size()) + "\n").c_str())) return nullptr; + for (int index = 1; index < slider_count; index++) + { + check_sliders.push_back(sliders[name + std::to_string(index)]); + } + } + else + { + values[0] = get_int(value, "value", 0); + } + + return new bgfx_suppressor(check_sliders, condition, mode, values); +} + +bool suppressor_reader::validate_parameters(const Value& value, std::string prefix) +{ + if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false; + if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("value"), (prefix + "Must have numeric or array value 'value'\n").c_str())) return false; + if (!READER_CHECK(value["value"].IsNumber() || value["value"].IsArray(), (prefix + "Value 'value' must be a number or array the size of the corresponding slider type\n").c_str())) return false; + return true; +} + +bool suppressor_reader::get_values(const Value& value, std::string prefix, std::string name, int* values, const int count) +{ + const char* name_str = name.c_str(); + const Value& value_array = value[name_str]; + for (UINT32 i = 0; i < value_array.Size() && i < count; i++) + { + if (!READER_CHECK(value_array[i].IsInt(), (prefix + "value[" + std::to_string(i) + "] must be an integer\n").c_str())) return false; + values[i] = value_array[i].GetInt(); + } + return true; +} diff --git a/src/osd/modules/render/bgfx/suppressorreader.h b/src/osd/modules/render/bgfx/suppressorreader.h new file mode 100644 index 00000000000..fc0a3f1cb8b --- /dev/null +++ b/src/osd/modules/render/bgfx/suppressorreader.h @@ -0,0 +1,37 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// suppressorreader.h - Reads pass-skipping conditions +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_SUPPRESSOR_READER__ +#define __DRAWBGFX_SUPPRESSOR_READER__ + +#include "statereader.h" + +#include <string> +#include <map> + +class bgfx_suppressor; +class bgfx_slider; + +class suppressor_reader : public state_reader +{ +public: + static bgfx_suppressor* read_from_value(const Value& value, std::string prefix, std::map<std::string, bgfx_slider*>& sliders); + +private: + static bool get_values(const Value& value, std::string prefix, std::string name, int* values, const int count); + static bool validate_parameters(const Value& value, std::string prefix); + + static const int CONDITION_COUNT = 2; + static const string_to_enum CONDITION_NAMES[CONDITION_COUNT]; + static const int COMBINE_COUNT = 2; + static const string_to_enum COMBINE_NAMES[COMBINE_COUNT]; +}; + +#endif // __DRAWBGFX_SUPPRESSOR_READER__ diff --git a/src/osd/modules/render/bgfx/target.cpp b/src/osd/modules/render/bgfx/target.cpp index b8026060b04..e29cbc810d9 100644 --- a/src/osd/modules/render/bgfx/target.cpp +++ b/src/osd/modules/render/bgfx/target.cpp @@ -8,19 +8,110 @@ #include "target.h" -bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, bool filter) - : bgfx_texture(name, format, width, height, nullptr, BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | (filter ? 0 : (BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT))) +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) + : m_name(name) + , m_format(format) + , m_targets(nullptr) + , m_textures(nullptr) + , m_width(width) + , m_height(height) + , m_prescale_x(prescale_x) + , m_prescale_y(prescale_y) + , m_double_buffer(double_buffer) + , m_style(style) + , m_filter(filter) + , m_output(output) + , m_current_page(0) + , m_initialized(false) + , m_page_count(double_buffer ? 2 : 1) { - m_target = bgfx::createFrameBuffer(1, &m_handle, false); + if (init) + { + uint32_t wrap_mode = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP; + uint32_t filter_mode = filter ? (BGFX_TEXTURE_MIN_ANISOTROPIC | BGFX_TEXTURE_MAG_ANISOTROPIC) : (BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT); + + m_textures = new bgfx::TextureHandle[m_page_count]; + m_targets = new bgfx::FrameBufferHandle[m_page_count]; + 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); + m_targets[page] = bgfx::createFrameBuffer(1, &m_textures[page], false); + } + + m_initialized = true; + } } -bgfx_target::bgfx_target(std::string name, void *handle, uint32_t width, uint32_t height) - : bgfx_texture(name, bgfx::TextureFormat::RGBA8, width, height, nullptr, BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT) +bgfx_target::bgfx_target(void *handle, uint16_t width, uint16_t height) + : m_name("backbuffer") + , m_format(bgfx::TextureFormat::Unknown) + , m_targets(nullptr) + , m_textures(nullptr) + , m_width(width) + , m_height(height) + , m_prescale_x(1) + , m_prescale_y(1) + , m_double_buffer(false) + , m_style(TARGET_STYLE_CUSTOM) + , m_filter(false) + , m_current_page(0) + , m_initialized(true) + , m_page_count(0) { - m_target = bgfx::createFrameBuffer(handle, width, height); + m_targets = new bgfx::FrameBufferHandle[1]; + m_targets[0] = bgfx::createFrameBuffer(handle, width, height); + + // No backing texture } bgfx_target::~bgfx_target() { - bgfx::destroyFrameBuffer(m_target); + 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]); + } + delete [] m_textures; + delete [] m_targets; + } + else + { + bgfx::destroyFrameBuffer(m_targets[0]); + delete [] m_targets; + } +} + +void bgfx_target::page_flip() +{ + if (!m_initialized) return; + + if (m_double_buffer) + { + m_current_page = 1 - m_current_page; + } +} + +bgfx::FrameBufferHandle bgfx_target::target() +{ + if (!m_initialized) return BGFX_INVALID_HANDLE; + return m_targets[m_current_page]; +} + +bgfx::TextureHandle bgfx_target::texture() const +{ + if (!m_initialized) return BGFX_INVALID_HANDLE; + + if (m_double_buffer) + { + return m_textures[1 - m_current_page]; + } + else + { + return m_textures[m_current_page]; + } } + diff --git a/src/osd/modules/render/bgfx/target.h b/src/osd/modules/render/bgfx/target.h index 19bf429e606..ad8efbde2cb 100644 --- a/src/osd/modules/render/bgfx/target.h +++ b/src/osd/modules/render/bgfx/target.h @@ -11,21 +11,68 @@ #ifndef __DRAWBGFX_TARGET__ #define __DRAWBGFX_TARGET__ -#include "texture.h" +#include <bgfx/bgfx.h> -class bgfx_target : public bgfx_texture +#include <string> + +#include "texturehandleprovider.h" + +enum +{ + TARGET_STYLE_GUEST = 0, + TARGET_STYLE_NATIVE, + TARGET_STYLE_CUSTOM +}; + +class bgfx_target : public bgfx_texture_handle_provider { public: - bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, bool filter = false); - bgfx_target(std::string name, void *handle, uint32_t width, uint32_t height); + 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(void *handle, uint16_t width, uint16_t height); virtual ~bgfx_target(); + void page_flip(); + // Getters - bgfx::FrameBufferHandle target() const { return m_target; } + bgfx::FrameBufferHandle target(); + bgfx::TextureFormat::Enum format() const { return m_format; } + std::string name() const { return m_name; } + bool double_buffered() const { return m_double_buffer; } + uint32_t style() const { return m_style; } + bool filter() const { return m_filter; } + uint32_t prescale_x() const { return m_prescale_x; } + uint32_t prescale_y() const { return m_prescale_y; } + bool output() const { return m_output; } + + // bgfx_texture_handle_provider + virtual uint16_t width() const override { return m_width; } + virtual uint16_t height() const override { return m_height; } + virtual bgfx::TextureHandle texture() const override; virtual bool is_target() const override { return true; } private: - bgfx::FrameBufferHandle m_target; + std::string m_name; + bgfx::TextureFormat::Enum m_format; + + bgfx::FrameBufferHandle* m_targets; + bgfx::TextureHandle* m_textures; + + uint16_t m_width; + uint16_t m_height; + + uint32_t m_prescale_x; + uint32_t m_prescale_y; + + bool m_double_buffer; + uint32_t m_style; + bool m_filter; + bool m_output; + + uint32_t m_current_page; + + bool m_initialized; + + const uint32_t m_page_count; }; #endif // __DRAWBGFX_TARGET__ diff --git a/src/osd/modules/render/bgfx/targetmanager.cpp b/src/osd/modules/render/bgfx/targetmanager.cpp index 88a3013350e..3e5828efabc 100644 --- a/src/osd/modules/render/bgfx/targetmanager.cpp +++ b/src/osd/modules/render/bgfx/targetmanager.cpp @@ -11,7 +11,12 @@ #include <bgfx/bgfx.h> +#include <vector> + +#include "modules/lib/osdobj_common.h" + #include "targetmanager.h" + #include "target.h" target_manager::~target_manager() @@ -23,21 +28,19 @@ target_manager::~target_manager() m_targets.clear(); } -bgfx_target* target_manager::create_target(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, bool filter) +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, filter); + bgfx_target* target = new bgfx_target(name, format, width, height, prescale_x, prescale_y, style, double_buffer, filter, width > 0 && height > 0, output); m_targets[name] = target; - m_textures.add_texture(name, target); + m_textures.add_provider(name, target); return target; } -bgfx_target* target_manager::create_target(std::string name, void *handle, uint32_t width, uint32_t height) +bgfx_target* target_manager::create_backbuffer(void *handle, uint32_t width, uint32_t height) { - bgfx_target* target = new bgfx_target(name, handle, width, height); - m_targets[name] = target; - - m_textures.add_texture(name, target); + bgfx_target* target = new bgfx_target(handle, width, height); + m_targets["backbuffer"] = target; return target; } @@ -51,3 +54,63 @@ bgfx_target* target_manager::target(std::string name) return nullptr; } + +void target_manager::update_guest_targets(uint16_t width, uint16_t height) +{ + if (width != m_guest_width || height != m_guest_height) + { + 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]); + } + } +} + +void target_manager::update_window_count(uint32_t count) +{ + if (count != m_window_count) + { + m_window_count = count; + rebuild_outputs(); + } +} + +void target_manager::rebuild_outputs() +{ + for (uint32_t i = 0; i < m_window_count; i++) + { + rebuild_target("output" + std::to_string(i)); + rebuild_target("previous" + std::to_string(i)); + } +} + +void target_manager::rebuild_target(std::string name) +{ + bgfx_target* target = m_targets[name]; + if (target != nullptr) { + delete target; + } + 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]); +}
\ 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 0d5f6f5f020..f017119502c 100644 --- a/src/osd/modules/render/bgfx/targetmanager.h +++ b/src/osd/modules/render/bgfx/targetmanager.h @@ -22,23 +22,35 @@ #include "texturemanager.h" class bgfx_target; +class osd_options; class target_manager { public: - target_manager(texture_manager& textures) : m_textures(textures) { } + 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(); - bgfx_target* create_target(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, bool filter = false); - bgfx_target* create_target(std::string name, void *handle, uint32_t width, uint32_t height); + 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); // 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; } private: - bgfx_target* create_target(std::string name); + void rebuild_outputs(); + void rebuild_target(std::string name); 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; }; #endif // __DRAWBGFX_TARGET_MANAGER__ diff --git a/src/osd/modules/render/bgfx/targetreader.cpp b/src/osd/modules/render/bgfx/targetreader.cpp new file mode 100644 index 00000000000..1f375155751 --- /dev/null +++ b/src/osd/modules/render/bgfx/targetreader.cpp @@ -0,0 +1,87 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// targetreader.cpp - BGFX target JSON reader +// +//============================================================ + +#include <string> + +#include "emu.h" +#include <modules/lib/osdobj_common.h> + +#include "targetreader.h" +#include "targetmanager.h" +#include "target.h" + +const target_reader::string_to_enum target_reader::STYLE_NAMES[target_reader::STYLE_COUNT] = { + { "guest", TARGET_STYLE_GUEST }, + { "native", TARGET_STYLE_NATIVE }, + { "custom", TARGET_STYLE_CUSTOM } +}; + +bool target_reader::read_from_value(const Value& value, std::string prefix, target_manager& targets, osd_options& options, uint32_t screen_width, uint32_t screen_height) +{ + if (!validate_parameters(value, prefix)) + { + return false; + } + + std::string target_name = value["name"].GetString(); + uint32_t mode = uint32_t(get_enum_from_value(value, "mode", TARGET_STYLE_NATIVE, STYLE_NAMES, STYLE_COUNT)); + bool bilinear = get_bool(value, "bilinear", true); + bool double_buffer = get_bool(value, "doublebuffer", true); + bool prescale = get_bool(value, "prescale", false); + bool output = get_bool(value, "output", false); + + uint16_t width = 0; + uint16_t height = 0; + switch (mode) + { + case TARGET_STYLE_GUEST: + width = targets.guest_width(); + height = targets.guest_height(); + break; + case TARGET_STYLE_NATIVE: + width = screen_width; + height = screen_height; + break; + case TARGET_STYLE_CUSTOM: + if (!READER_CHECK(value.HasMember("width"), (prefix + "Target '" + target_name + "': Must have numeric value 'width'\n").c_str())) return false; + if (!READER_CHECK(value["width"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'width' must be a number\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("height"), (prefix + "Target '" + target_name + "': Must have numeric value 'height'\n").c_str())) return false; + if (!READER_CHECK(value["height"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'height' must be a number\n").c_str())) return false; + width = uint32_t(value["width"].GetDouble()); + height = uint32_t(value["height"].GetDouble()); + break; + } + + uint32_t prescale_x = 1; + uint32_t prescale_y = 1; + if (prescale) + { + prescale_x = options.bgfx_prescale_x(); + prescale_y = options.bgfx_prescale_y(); + } + + if (!output) + { + targets.create_target(target_name, bgfx::TextureFormat::RGBA8, width, height, prescale_x, prescale_y, mode, double_buffer, bilinear, output); + } + + return true; +} + +bool target_reader::validate_parameters(const Value& value, std::string prefix) +{ + if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str())) return false; + if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("mode"), (prefix + "Must have string enum 'mode'\n").c_str())) return false; + if (!READER_CHECK(value["mode"].IsString(), (prefix + "Value 'mode' must be a string (what screens does this apply to?)\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("bilinear") || value["bilinear"].IsBool(), (prefix + "Value 'bilinear' must be a boolean\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("doublebuffer") || value["doublebuffer"].IsBool(), (prefix + "Value 'doublebuffer' must be a boolean\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("prescale") || value["prescale"].IsBool(), (prefix + "Value 'prescale' must be a boolean\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("output") || value["output"].IsBool(), (prefix + "Value 'output' must be a boolean\n").c_str())) return false; + return true; +} diff --git a/src/osd/modules/render/bgfx/targetreader.h b/src/osd/modules/render/bgfx/targetreader.h new file mode 100644 index 00000000000..13709905cfb --- /dev/null +++ b/src/osd/modules/render/bgfx/targetreader.h @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// targetreader.h - BGFX target JSON reader +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_TARGET_READER__ +#define __DRAWBGFX_TARGET_READER__ + +#include <string> + +#include "statereader.h" + +class target_manager; +class osd_options; + +class target_reader : public state_reader +{ +public: + static bool read_from_value(const Value& value, std::string prefix, target_manager& targets, osd_options& options, uint32_t screen_width, uint32_t screen_height); + +private: + static bool validate_parameters(const Value& value, std::string prefix); + + static const int STYLE_COUNT = 3; + static const string_to_enum STYLE_NAMES[STYLE_COUNT]; +}; + +#endif // __DRAWBGFX_TARGET_READER__ diff --git a/src/osd/modules/render/bgfx/texture.cpp b/src/osd/modules/render/bgfx/texture.cpp index c588fa63b20..bd69e18e424 100644 --- a/src/osd/modules/render/bgfx/texture.cpp +++ b/src/osd/modules/render/bgfx/texture.cpp @@ -10,7 +10,7 @@ #include "texture.h" -bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, void* data, uint32_t flags) +bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t flags, void* data) : m_name(name) , m_format(format) , m_width(width) @@ -20,19 +20,30 @@ bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, u bgfx::calcTextureSize(info, width, height, 1, false, 1, format); if (data != nullptr) { - m_handle = bgfx::createTexture2D(width, height, 1, format, flags, bgfx::copy(data, info.storageSize)); + m_texture = bgfx::createTexture2D(width, height, 1, format, flags, bgfx::copy(data, info.storageSize)); } else { - m_handle = bgfx::createTexture2D(width, height, 1, format, flags); + m_texture = bgfx::createTexture2D(width, height, 1, format, flags); const bgfx::Memory* memory = bgfx::alloc(info.storageSize); memset(memory->data, 0, info.storageSize); - bgfx::updateTexture2D(m_handle, 0, 0, 0, width, height, memory, info.storageSize / height); + bgfx::updateTexture2D(m_texture, 0, 0, 0, width, height, memory, info.storageSize / height); } } +bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, const bgfx::Memory* data, uint32_t flags) + : m_name(name) + , m_format(format) + , m_width(width) + , m_height(height) +{ + bgfx::TextureInfo info; + bgfx::calcTextureSize(info, width, height, 1, false, 1, format); + m_texture = bgfx::createTexture2D(width, height, 1, format, flags, data); +} + bgfx_texture::~bgfx_texture() { - bgfx::destroyTexture(m_handle); + bgfx::destroyTexture(m_texture); } diff --git a/src/osd/modules/render/bgfx/texture.h b/src/osd/modules/render/bgfx/texture.h index 70dad1c13b6..bb9e5962337 100644 --- a/src/osd/modules/render/bgfx/texture.h +++ b/src/osd/modules/render/bgfx/texture.h @@ -15,26 +15,31 @@ #include <string> -class bgfx_texture +#include "texturehandleprovider.h" + +class bgfx_texture : public bgfx_texture_handle_provider { public: - bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, void* data = nullptr, uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP); + bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t flags, void* data); + bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, const bgfx::Memory* data, uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP); virtual ~bgfx_texture(); // Getters std::string name() const { return m_name; } bgfx::TextureFormat::Enum format() const { return m_format; } - uint32_t width() const { return m_width; } - uint32_t height() const { return m_height; } - bgfx::TextureHandle handle() const { return m_handle; } - virtual bool is_target() const { return false; } + + // bgfx_texture_handle_provider + virtual uint16_t width() const override { return m_width; } + virtual uint16_t height() const override { return m_height; } + virtual bgfx::TextureHandle texture() const override { return m_texture; } + virtual bool is_target() const override { return false; } protected: std::string m_name; bgfx::TextureFormat::Enum m_format; - uint32_t m_width; - uint32_t m_height; - bgfx::TextureHandle m_handle; + uint16_t m_width; + uint16_t m_height; + bgfx::TextureHandle m_texture; }; #endif // __DRAWBGFX_TEXTURE__ diff --git a/src/osd/modules/render/bgfx/texturehandleprovider.h b/src/osd/modules/render/bgfx/texturehandleprovider.h new file mode 100644 index 00000000000..e309bea8d59 --- /dev/null +++ b/src/osd/modules/render/bgfx/texturehandleprovider.h @@ -0,0 +1,28 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// texturehandleprovider.h +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__ +#define __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__ + +#include <bgfx/bgfx.h> + +class bgfx_texture_handle_provider +{ +public: + virtual ~bgfx_texture_handle_provider() { } + + // Getters + virtual bgfx::TextureHandle texture() const = 0; + virtual bool is_target() const = 0; + virtual uint16_t width() const = 0; + virtual uint16_t height() const = 0; +}; + +#endif // __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__ diff --git a/src/osd/modules/render/bgfx/texturemanager.cpp b/src/osd/modules/render/bgfx/texturemanager.cpp index 4da872978dd..f5423b34eed 100644 --- a/src/osd/modules/render/bgfx/texturemanager.cpp +++ b/src/osd/modules/render/bgfx/texturemanager.cpp @@ -11,14 +11,18 @@ #include <bgfx/bgfx.h> +#include "emu.h" + #include "texturemanager.h" #include "texture.h" +#include "rendutil.h" +#include "modules/render/copyutil.h" texture_manager::~texture_manager() { - for (std::pair<std::string, bgfx_texture*> texture : m_textures) + for (std::pair<std::string, bgfx_texture_handle_provider*> texture : m_textures) { - if (!(texture.second)->is_target()) + if (texture.second != nullptr && !(texture.second)->is_target()) { delete texture.second; } @@ -26,21 +30,65 @@ texture_manager::~texture_manager() m_textures.clear(); } -void texture_manager::add_texture(std::string name, bgfx_texture* texture) +void texture_manager::add_provider(std::string name, bgfx_texture_handle_provider* provider) { - m_textures[name] = texture; + std::map<std::string, bgfx_texture_handle_provider*>::iterator iter = m_textures.find(name); + if (iter != m_textures.end()) + { + iter->second = provider; + } + else + { + m_textures[name] = provider; + } } bgfx_texture* texture_manager::create_texture(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, void* data, uint32_t flags) { - bgfx_texture* texture = new bgfx_texture(name, format, width, height, data, flags); + bgfx_texture* texture = new bgfx_texture(name, format, width, height, flags, data); m_textures[name] = texture; return texture; } -bgfx_texture* texture_manager::texture(std::string name) +bgfx_texture* texture_manager::create_png_texture(std::string path, std::string file_name, std::string texture_name, uint32_t flags) +{ + bitmap_argb32 bitmap; + emu_file file(path.c_str(), OPEN_FLAG_READ); + render_load_png(bitmap, file, nullptr, file_name.c_str()); + + uint8_t *texture_data = new uint8_t[bitmap.width() * bitmap.height() * 4]; + + uint32_t width = bitmap.width(); + uint32_t height = bitmap.height(); + uint32_t rowpixels = bitmap.rowpixels(); + void *base = bitmap.raw_pixptr(0); + for (int y = 0; y < height; y++) { + copy_util::copyline_argb32(reinterpret_cast<UINT32 *>(texture_data) + y * width, reinterpret_cast<UINT32 *>(base) + y * rowpixels, width, nullptr); + } + + bgfx_texture* texture = create_texture(texture_name, bgfx::TextureFormat::RGBA8, width, height, texture_data, flags); + + delete[] texture_data; + + return texture; +} + +bgfx::TextureHandle texture_manager::handle(std::string name) +{ + bgfx::TextureHandle handle = BGFX_INVALID_HANDLE; + std::map<std::string, bgfx_texture_handle_provider*>::iterator iter = m_textures.find(name); + if (iter != m_textures.end()) + { + handle = (iter->second)->texture(); + } + + assert(handle.idx != bgfx::invalidHandle); + return handle; +} + +bgfx_texture_handle_provider* texture_manager::provider(std::string name) { - std::map<std::string, bgfx_texture*>::iterator iter = m_textures.find(name); + std::map<std::string, bgfx_texture_handle_provider*>::iterator iter = m_textures.find(name); if (iter != m_textures.end()) { return iter->second; diff --git a/src/osd/modules/render/bgfx/texturemanager.h b/src/osd/modules/render/bgfx/texturemanager.h index 69608c03616..710ddc0bb34 100644 --- a/src/osd/modules/render/bgfx/texturemanager.h +++ b/src/osd/modules/render/bgfx/texturemanager.h @@ -19,6 +19,7 @@ #include <bgfx/bgfx.h> +class bgfx_texture_handle_provider; class bgfx_texture; class texture_manager { @@ -27,15 +28,17 @@ public: ~texture_manager(); bgfx_texture* create_texture(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, void* data = nullptr, uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP); - void add_texture(std::string name, bgfx_texture* texture); + bgfx_texture* create_png_texture(std::string path, std::string file_name, std::string texture_name, uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP); + void add_provider(std::string name, bgfx_texture_handle_provider* texture); // Getters - bgfx_texture* texture(std::string name); + bgfx::TextureHandle handle(std::string name); + bgfx_texture_handle_provider* provider(std::string name); private: bgfx_texture* create_texture(std::string name); - std::map<std::string, bgfx_texture*> m_textures; + std::map<std::string, bgfx_texture_handle_provider*> m_textures; }; #endif // __DRAWBGFX_TEXTURE_MANAGER__ diff --git a/src/osd/modules/render/bgfx/timeparameter.cpp b/src/osd/modules/render/bgfx/timeparameter.cpp new file mode 100644 index 00000000000..f1f10ce700b --- /dev/null +++ b/src/osd/modules/render/bgfx/timeparameter.cpp @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// timeparameter.cpp - Time-based dynamic shader param +// +//============================================================ + +#include "timeparameter.h" + +bgfx_time_parameter::bgfx_time_parameter(std::string name, parameter_type type, double limit) + : bgfx_parameter(name, type) + , m_current_time(0) + , m_limit(limit) +{ +} + +float bgfx_time_parameter::value() +{ + return float(m_current_time * 1000.0 * 1000.0); +} + +void bgfx_time_parameter::tick(double delta) +{ + m_current_time += delta; + if (m_limit != 0) + { + while (m_current_time >= m_limit) + { + m_current_time -= m_limit; + } + } +} diff --git a/src/osd/modules/render/bgfx/timeparameter.h b/src/osd/modules/render/bgfx/timeparameter.h new file mode 100644 index 00000000000..6a05be4fc03 --- /dev/null +++ b/src/osd/modules/render/bgfx/timeparameter.h @@ -0,0 +1,34 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// timeparameter.cpp - Time-based dynamic shader param +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_TIME_PARAMETER__ +#define __DRAWBGFX_TIME_PARAMETER__ + +#include <bgfx/bgfx.h> + +#include <string> + +#include "parameter.h" + +class bgfx_time_parameter : public bgfx_parameter +{ +public: + bgfx_time_parameter(std::string name, parameter_type type, double limit); + virtual ~bgfx_time_parameter() { } + + virtual float value() override; + virtual void tick(double delta) override; + +private: + double m_current_time; + double m_limit; +}; + +#endif // __DRAWBGFX_TIME_PARAMETER__ diff --git a/src/osd/modules/render/bgfx/uniform.cpp b/src/osd/modules/render/bgfx/uniform.cpp index 2898c27a5b8..780705d8371 100644 --- a/src/osd/modules/render/bgfx/uniform.cpp +++ b/src/osd/modules/render/bgfx/uniform.cpp @@ -29,8 +29,10 @@ bgfx_uniform::~bgfx_uniform() void bgfx_uniform::upload() { - if (m_type != bgfx::UniformType::Int1) // Avoid samplers; set separately! + if (m_type != bgfx::UniformType::Int1) + { bgfx::setUniform(m_handle, m_data); + } } bgfx_uniform* bgfx_uniform::set(float* value) diff --git a/src/osd/modules/render/bgfx/uniformreader.cpp b/src/osd/modules/render/bgfx/uniformreader.cpp index 141bc657121..cfbcf0bdac0 100644 --- a/src/osd/modules/render/bgfx/uniformreader.cpp +++ b/src/osd/modules/render/bgfx/uniformreader.cpp @@ -7,28 +7,27 @@ //============================================================ #include "uniformreader.h" + #include "uniform.h" const uniform_reader::string_to_enum uniform_reader::TYPE_NAMES[uniform_reader::TYPE_COUNT] = { { "int", bgfx::UniformType::Int1 }, { "vec4", bgfx::UniformType::Vec4 }, { "mat3", bgfx::UniformType::Mat3 }, - { "mat4", bgfx::UniformType::Mat4 }, - { "camera", bgfx::UniformType::Mat4 } + { "mat4", bgfx::UniformType::Mat4 } }; -bgfx_uniform* uniform_reader::read_from_value(const Value& value) +bgfx_uniform* uniform_reader::read_from_value(const Value& value, std::string prefix) { - assert(value.HasMember("name")); - assert(value["name"].IsString()); + if (!validate_parameters(value, prefix)) + { + return nullptr; + } const char* name = value["name"].GetString(); - assert(value.HasMember("type")); bgfx::UniformType::Enum type = bgfx::UniformType::Enum(get_enum_from_value(value, "type", bgfx::UniformType::Vec4, TYPE_NAMES, TYPE_COUNT)); const size_t type_size = bgfx_uniform::get_size_for_type(type); - assert(value.HasMember("values")); - assert(value["values"].IsArray()); const Value& value_array = value["values"]; const size_t array_size = value_array.Size() * sizeof(float); @@ -41,7 +40,8 @@ bgfx_uniform* uniform_reader::read_from_value(const Value& value) data[index] = (float)value_array[index].GetDouble(); } - for (; index < type_size / 4; index++) { + for (; index < type_size / 4; index++) + { data[index] = 0.0f; } @@ -51,3 +51,13 @@ bgfx_uniform* uniform_reader::read_from_value(const Value& value) return uniform; } + +bool uniform_reader::validate_parameters(const Value& value, std::string prefix) +{ + if (!READER_CHECK(value.HasMember("name"), (prefix + "Must have string value 'name' (what is this uniform called in the shader code?)\n").c_str())) return false; + if (!READER_CHECK(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("type"), (prefix + "Must have string value 'type' [int, vec4, mat3, mat4]\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("values"), (prefix + "Must have array value 'values' (what are the uniform's default values?)\n").c_str())) return false; + if (!READER_CHECK(value["values"].IsArray(), (prefix + "Value 'values' must be an array\n").c_str())) return false; + return true; +} diff --git a/src/osd/modules/render/bgfx/uniformreader.h b/src/osd/modules/render/bgfx/uniformreader.h index 40bedf8b732..056feee04ba 100644 --- a/src/osd/modules/render/bgfx/uniformreader.h +++ b/src/osd/modules/render/bgfx/uniformreader.h @@ -17,24 +17,15 @@ class bgfx_uniform; -enum uniform_type -{ - TYPE_INT1 = bgfx::UniformType::Int1, - TYPE_VEC4 = bgfx::UniformType::Vec4, - TYPE_MAT3 = bgfx::UniformType::Mat3, - TYPE_MAT4 = bgfx::UniformType::Mat4, - TYPE_CAMERA, // Alias for the current ortho camera, used to auto-bind on material load - - TYPE_COUNT = 5 -}; - class uniform_reader : public state_reader { public: - static bgfx_uniform* read_from_value(const Value& value); + static bgfx_uniform* read_from_value(const Value& value, std::string prefix); private: - static const int TYPE_COUNT = uniform_type::TYPE_COUNT; + static bool validate_parameters(const Value& value, std::string prefix); + + static const int TYPE_COUNT = 4; static const string_to_enum TYPE_NAMES[TYPE_COUNT]; }; diff --git a/src/osd/modules/render/bgfx/valueuniform.cpp b/src/osd/modules/render/bgfx/valueuniform.cpp new file mode 100644 index 00000000000..e920c45dc18 --- /dev/null +++ b/src/osd/modules/render/bgfx/valueuniform.cpp @@ -0,0 +1,24 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// valueuniform.cpp - BGFX shader chain fixed uniform +// +// Represents the mapping between a fixed value and a chain +// shader uniform for a given entry +// +//============================================================ + +#include "valueuniform.h" + +bgfx_value_uniform::bgfx_value_uniform(bgfx_uniform* uniform, float* values, const int count) + : bgfx_entry_uniform(uniform) + , m_count(count) +{ + memcpy(m_values, values, sizeof(float) * count); +} + +void bgfx_value_uniform::bind() +{ + m_uniform->set(m_values, sizeof(float) * m_count); +} diff --git a/src/osd/modules/render/bgfx/valueuniform.h b/src/osd/modules/render/bgfx/valueuniform.h new file mode 100644 index 00000000000..2cce6970958 --- /dev/null +++ b/src/osd/modules/render/bgfx/valueuniform.h @@ -0,0 +1,31 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// valueuniform.cpp - BGFX shader chain fixed uniform +// +// Represents the mapping between a fixed value and a chain +// shader uniform for a given entry +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_VALUE_UNIFORM__ +#define __DRAWBGFX_VALUE_UNIFORM__ + +#include "entryuniform.h" + +class bgfx_value_uniform : public bgfx_entry_uniform +{ +public: + bgfx_value_uniform(bgfx_uniform* uniform, float* values, const int count); + + virtual void bind() override; + +private: + float m_values[4]; + const int m_count; +}; + +#endif // __DRAWBGFX_VALUE_UNIFORM__ diff --git a/src/osd/modules/render/bgfx/valueuniformreader.cpp b/src/osd/modules/render/bgfx/valueuniformreader.cpp new file mode 100644 index 00000000000..bbd9a886bf9 --- /dev/null +++ b/src/osd/modules/render/bgfx/valueuniformreader.cpp @@ -0,0 +1,44 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//================================================================== +// +// valueuniformreader.cpp - BGFX chain entry value mapper reader +// +//================================================================== + +#include "valueuniformreader.h" + +#include "entryuniform.h" +#include "valueuniform.h" + +bgfx_entry_uniform* value_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform) +{ + if (!validate_parameters(value, prefix)) + { + return nullptr; + } + + float values[4]; + int count = 1; + if (value["value"].IsNumber()) + { + values[0] = float(value["value"].GetDouble()); + } + else + { + const Value& value_array = value["value"]; + count = int(value_array.Size()); + for (int i = 0; i < count; i++) + { + values[i] = float(value_array[i].GetDouble()); + } + } + return new bgfx_value_uniform(uniform, values, count); +} + +bool value_uniform_reader::validate_parameters(const Value& value, std::string prefix) +{ + if (!READER_CHECK(value.HasMember("value"), (prefix + "Must have string value 'value' (what value is being assigned?)\n").c_str())) return false; + if (!READER_CHECK(value["value"].IsArray() || value["value"].IsNumber(), (prefix + "Value 'value' must be numeric or an array\n").c_str())) return false; + return true; +} diff --git a/src/osd/modules/render/bgfx/valueuniformreader.h b/src/osd/modules/render/bgfx/valueuniformreader.h new file mode 100644 index 00000000000..0b6fead1cca --- /dev/null +++ b/src/osd/modules/render/bgfx/valueuniformreader.h @@ -0,0 +1,31 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//================================================================ +// +// valueuniformreader.h - BGFX chain entry value mapper reader +// +//================================================================ + +#pragma once + +#ifndef __DRAWBGFX_VALUE_UNIFORM_READER__ +#define __DRAWBGFX_VALUE_UNIFORM_READER__ + +#include <string> +#include <map> + +#include "statereader.h" + +class bgfx_entry_uniform; +class bgfx_uniform; + +class value_uniform_reader : public state_reader +{ +public: + static bgfx_entry_uniform* read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform); + +private: + static bool validate_parameters(const Value& value, std::string prefix); +}; + +#endif // __DRAWBGFX_VALUE_UNIFORM_READER__ diff --git a/src/osd/modules/render/bgfx/varying.def.sc b/src/osd/modules/render/bgfx/varying.def.sc index 4745725e015..95b607539a7 100644 --- a/src/osd/modules/render/bgfx/varying.def.sc +++ b/src/osd/modules/render/bgfx/varying.def.sc @@ -1,6 +1,8 @@ vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0); vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0); -vec3 v_pos : TEXCOORD1 = vec3(0.0, 0.0, 0.0); +vec2 v_texcoord1 : TEXCOORD1 = vec2(0.0, 0.0); +vec2 v_texcoord2 : TEXCOORD2 = vec2(0.0, 0.0); +vec3 v_pos : TEXCOORD3 = vec3(0.0, 0.0, 0.0); vec3 a_position : POSITION; vec4 a_color0 : COLOR0; diff --git a/src/osd/modules/render/bgfx/vertex.h b/src/osd/modules/render/bgfx/vertex.h new file mode 100644 index 00000000000..30c38400f93 --- /dev/null +++ b/src/osd/modules/render/bgfx/vertex.h @@ -0,0 +1,37 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// vertex.h - BGFX screen vertex data +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_VERTEX__ +#define __DRAWBGFX_VERTEX__ + +#include <bgfx/bgfx.h> + +struct ScreenVertex +{ + float m_x; + float m_y; + float m_z; + UINT32 m_rgba; + float m_u; + float m_v; + + static void init() + { + ms_decl.begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) + .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float) + .end(); + } + + static bgfx::VertexDecl ms_decl; +}; + +#endif // __DRAWBGFX_VERTEX__
\ No newline at end of file diff --git a/src/osd/modules/render/bgfx/vs_ratios.sc b/src/osd/modules/render/bgfx/vs_color.sc index c3699f6fbd9..c3699f6fbd9 100644 --- a/src/osd/modules/render/bgfx/vs_ratios.sc +++ b/src/osd/modules/render/bgfx/vs_color.sc diff --git a/src/osd/modules/render/bgfx/vs_deconverge.sc b/src/osd/modules/render/bgfx/vs_deconverge.sc new file mode 100644 index 00000000000..cb3b43f8a49 --- /dev/null +++ b/src/osd/modules/render/bgfx/vs_deconverge.sc @@ -0,0 +1,31 @@ +$input a_position, a_texcoord0, a_color0 +$output v_color0, v_texcoord0, v_texcoord1, v_texcoord2 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +// Autos +uniform vec4 u_source_dims; + +// User-supplied +uniform vec4 u_converge_red; +uniform vec4 u_converge_green; +uniform vec4 u_converge_blue; +uniform vec4 u_radial_converge_red; +uniform vec4 u_radial_converge_green; +uniform vec4 u_radial_converge_blue; + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + + vec2 half_value = vec2(0.5, 0.5); + + v_texcoord0 = (a_texcoord0 - half_value) * (1.0 + u_radial_converge_red.xy ) + half_value + u_converge_red.xy * (vec2(1.0, 1.0) / u_source_dims.xy); + v_texcoord1 = (a_texcoord0 - half_value) * (1.0 + u_radial_converge_green.xy) + half_value + u_converge_green.xy * (vec2(1.0, 1.0) / u_source_dims.xy); + v_texcoord2 = (a_texcoord0 - half_value) * (1.0 + u_radial_converge_blue.xy ) + half_value + u_converge_blue.xy * (vec2(1.0, 1.0) / u_source_dims.xy); + + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/bgfx/vs_tint.sc b/src/osd/modules/render/bgfx/vs_defocus.sc index c3699f6fbd9..c3699f6fbd9 100644 --- a/src/osd/modules/render/bgfx/vs_tint.sc +++ b/src/osd/modules/render/bgfx/vs_defocus.sc diff --git a/src/osd/modules/render/bgfx/vs_distortion.sc b/src/osd/modules/render/bgfx/vs_distortion.sc new file mode 100644 index 00000000000..c3699f6fbd9 --- /dev/null +++ b/src/osd/modules/render/bgfx/vs_distortion.sc @@ -0,0 +1,14 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + v_texcoord0 = a_texcoord0; + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/bgfx/vs_ntsc_decode.sc b/src/osd/modules/render/bgfx/vs_ntsc_decode.sc new file mode 100644 index 00000000000..c3699f6fbd9 --- /dev/null +++ b/src/osd/modules/render/bgfx/vs_ntsc_decode.sc @@ -0,0 +1,14 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + v_texcoord0 = a_texcoord0; + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/bgfx/vs_ntsc_encode.sc b/src/osd/modules/render/bgfx/vs_ntsc_encode.sc new file mode 100644 index 00000000000..c3699f6fbd9 --- /dev/null +++ b/src/osd/modules/render/bgfx/vs_ntsc_encode.sc @@ -0,0 +1,14 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + v_texcoord0 = a_texcoord0; + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/bgfx/vs_post.sc b/src/osd/modules/render/bgfx/vs_post.sc new file mode 100644 index 00000000000..12b4931a1ae --- /dev/null +++ b/src/osd/modules/render/bgfx/vs_post.sc @@ -0,0 +1,19 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_texcoord1, v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +uniform vec4 u_swap_xy; + +uniform vec4 u_shadow_uv_offset; + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + v_texcoord0 = a_texcoord0; + v_texcoord1 = a_position.xy + ((u_swap_xy.x != 0.0) ? u_shadow_uv_offset.yx : u_shadow_uv_offset.xy); + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/bgfx/windowparameter.h b/src/osd/modules/render/bgfx/windowparameter.h new file mode 100644 index 00000000000..83afdb220b7 --- /dev/null +++ b/src/osd/modules/render/bgfx/windowparameter.h @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// windowparameter.h - Static window-index shader param +// +//============================================================ + +#pragma once + +#ifndef __DRAWBGFX_WINDOW_PARAMETER__ +#define __DRAWBGFX_WINDOW_PARAMETER__ + +#include <bgfx/bgfx.h> + +#include <string> + +#include "parameter.h" + +class bgfx_window_parameter : public bgfx_parameter +{ +public: + bgfx_window_parameter(std::string name, parameter_type type, uint32_t index) : bgfx_parameter(name, type), m_index(index) { } + virtual ~bgfx_window_parameter() { } + + virtual float value() override { return float(m_index); } + virtual void tick(double delta) override { }; + +private: + uint32_t m_index; +}; + +#endif // __DRAWBGFX_WINDOW_PARAMETER__ diff --git a/src/osd/modules/render/copyutil.h b/src/osd/modules/render/copyutil.h new file mode 100644 index 00000000000..f3cd3f6851a --- /dev/null +++ b/src/osd/modules/render/copyutil.h @@ -0,0 +1,167 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// copyutil.h - bitmap-conversion functions +// +//============================================================ + +#pragma once + +#ifndef __RENDER_COPYUTIL__ +#define __RENDER_COPYUTIL__ + +#include "emu.h" + +class copy_util +{ +public: + static inline void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette) + { + for (int x = 0; x < width; x++) + { + rgb_t srcpixel = palette[*src++]; + *dst++ = 0xff000000 | (srcpixel.b() << 16) | (srcpixel.g() << 8) | srcpixel.r(); + } + } + + static inline void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette) + { + for (int x = 0; x < width; x++) + { + rgb_t srcpixel = palette[*src++]; + *dst++ = (srcpixel.a() << 24) | (srcpixel.b() << 16) | (srcpixel.g() << 8) | srcpixel.r(); + } + } + + static inline void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette) + { + int x; + + // palette (really RGB map) case + if (palette != nullptr) + { + for (x = 0; x < width; x++) + { + rgb_t srcpix = *src++; + *dst++ = 0xff000000 | palette[0x200 + srcpix.b()] | palette[0x100 + srcpix.g()] | palette[srcpix.r()]; + } + } + + // direct case + else + { + for (x = 0; x < width; x++) + { + rgb_t srcpix = *src++; + *dst++ = 0xff000000 | (srcpix.b() << 16) | (srcpix.g() << 8) | srcpix.r(); + } + } + } + + static inline void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette) + { + int x; + // palette (really RGB map) case + if (palette != nullptr) + { + for (x = 0; x < width; x++) + { + rgb_t srcpix = *src++; + *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.b()] | palette[0x100 + srcpix.g()] | palette[srcpix.r()]; + } + } + + // direct case + else + { + for (x = 0; x < width; x++) + { + rgb_t srcpix = *src++; + *dst++ = (srcpix.a() << 24) | (srcpix.b() << 16) | (srcpix.g() << 8) | srcpix.r(); + } + } + } + + static inline UINT32 ycc_to_rgb(UINT8 y, UINT8 cb, UINT8 cr) + { + /* original equations: + + C = Y - 16 + D = Cb - 128 + E = Cr - 128 + + R = clip(( 298 * C + 409 * E + 128) >> 8) + G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) + B = clip(( 298 * C + 516 * D + 128) >> 8) + + R = clip(( 298 * (Y - 16) + 409 * (Cr - 128) + 128) >> 8) + G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8) + B = clip(( 298 * (Y - 16) + 516 * (Cb - 128) + 128) >> 8) + + R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) + G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) + B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) + + R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) + G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) + B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) + */ + int r, g, b, common; + + common = 298 * y - 298 * 16; + r = (common + 409 * cr - 409 * 128 + 128) >> 8; + g = (common - 100 * cb + 100 * 128 - 208 * cr + 208 * 128 + 128) >> 8; + b = (common + 516 * cb - 516 * 128 + 128) >> 8; + + if (r < 0) r = 0; + else if (r > 255) r = 255; + if (g < 0) g = 0; + else if (g > 255) g = 255; + if (b < 0) b = 0; + else if (b > 255) b = 255; + + return 0xff000000 | (b << 16) | (g << 8) | r; + } + + static inline void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xprescale) + { + int x; + + assert(width % 2 == 0); + + // palette (really RGB map) case + if (palette != nullptr) + { + for (x = 0; x < width / 2; x++) + { + UINT16 srcpix0 = *src++; + UINT16 srcpix1 = *src++; + UINT8 cb = srcpix0 & 0xff; + UINT8 cr = srcpix1 & 0xff; + for (int x2 = 0; x2 < xprescale; x2++) + *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); + for (int x2 = 0; x2 < xprescale; x2++) + *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); + } + } + + // direct case + else + { + for (x = 0; x < width; x += 2) + { + UINT16 srcpix0 = *src++; + UINT16 srcpix1 = *src++; + UINT8 cb = srcpix0 & 0xff; + UINT8 cr = srcpix1 & 0xff; + for (int x2 = 0; x2 < xprescale; x2++) + *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); + for (int x2 = 0; x2 < xprescale; x2++) + *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); + } + } + } +}; + +#endif // __RENDER_COPYUTIL__
\ No newline at end of file diff --git a/src/osd/modules/render/d3d/d3dcomm.h b/src/osd/modules/render/d3d/d3dcomm.h index 3419619df57..51758bb70b6 100644 --- a/src/osd/modules/render/d3d/d3dcomm.h +++ b/src/osd/modules/render/d3d/d3dcomm.h @@ -112,34 +112,34 @@ public: render_texinfo & get_texinfo() { return m_texinfo; } - int get_width() { return m_rawdims.c.x; } - int get_height() { return m_rawdims.c.y; } - int get_xscale() { return m_xprescale; } - int get_yscale() { return m_yprescale; } + int get_width() const { return m_rawdims.c.x; } + int get_height() const { return m_rawdims.c.y; } + int get_xscale() const { return m_xprescale; } + int get_yscale() const { return m_yprescale; } - UINT32 get_flags() { return m_flags; } + UINT32 get_flags() const { return m_flags; } void set_data(const render_texinfo *texsource, UINT32 flags); - texture_info * get_next() { return m_next; } - texture_info * get_prev() { return m_prev; } + texture_info * get_next() const { return m_next; } + texture_info * get_prev() const { return m_prev; } - UINT32 get_hash() { return m_hash; } + UINT32 get_hash() const { return m_hash; } void set_next(texture_info *next) { m_next = next; } void set_prev(texture_info *prev) { m_prev = prev; } - bool paused() { return m_cur_frame == m_prev_frame; } + bool paused() const { return m_cur_frame == m_prev_frame; } void advance_frame() { m_prev_frame = m_cur_frame; } void increment_frame_count() { m_cur_frame++; } void mask_frame_count(int mask) { m_cur_frame %= mask; } - int get_cur_frame() { return m_cur_frame; } - int get_prev_frame() { return m_prev_frame; } + int get_cur_frame() const { return m_cur_frame; } + int get_prev_frame() const { return m_prev_frame; } - texture * get_tex() { return m_d3dtex; } - surface * get_surface() { return m_d3dsurface; } - texture * get_finaltex() { return m_d3dfinaltex; } + texture * get_tex() const { return m_d3dtex; } + surface * get_surface() const { return m_d3dsurface; } + texture * get_finaltex() const { return m_d3dfinaltex; } vec2f & get_uvstart() { return m_start; } vec2f & get_uvstop() { return m_stop; } @@ -187,19 +187,20 @@ public: float line_time, float line_length, float prim_width, float prim_height); - D3DPRIMITIVETYPE get_type() { return m_type; } - UINT32 get_count() { return m_count; } - UINT32 get_vertcount() { return m_numverts; } - UINT32 get_flags() { return m_flags; } + // TODO: Remove needless 'get_' prefix + D3DPRIMITIVETYPE get_type() const { return m_type; } + UINT32 get_count() const { return m_count; } + UINT32 get_vertcount() const { return m_numverts; } + UINT32 get_flags() const { return m_flags; } - texture_info * get_texture() { return m_texture; } - DWORD get_modmode() { return m_modmode; } + texture_info * get_texture() const { return m_texture; } + DWORD get_modmode() const { return m_modmode; } - float get_line_time() { return m_line_time; } - float get_line_length() { return m_line_length; } + float get_line_time() const { return m_line_time; } + float get_line_length() const { return m_line_length; } - float get_prim_width() { return m_prim_width; } - float get_prim_height() { return m_prim_height; } + float get_prim_width() const { return m_prim_width; } + float get_prim_height() const { return m_prim_height; } private: diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 3706b68042d..6336404bd4a 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -1648,10 +1648,10 @@ void shaders::render_quad(poly_info *poly, int vertnum) int next_index = 0; - next_index = ntsc_pass(rt, next_index, poly, vertnum); - next_index = color_convolution_pass(rt, next_index, poly, vertnum); - next_index = prescale_pass(rt, next_index, poly, vertnum); - next_index = deconverge_pass(rt, next_index, poly, vertnum); + next_index = ntsc_pass(rt, next_index, poly, vertnum); // handled in bgfx + next_index = color_convolution_pass(rt, next_index, poly, vertnum); // handled in bgfx + next_index = prescale_pass(rt, next_index, poly, vertnum); // handled in bgfx + next_index = deconverge_pass(rt, next_index, poly, vertnum); // handled in bgfx next_index = defocus_pass(rt, next_index, poly, vertnum); // 1st pass next_index = defocus_pass(rt, next_index, poly, vertnum); // 2nd pass next_index = phosphor_pass(rt, ct, next_index, poly, vertnum); @@ -2161,7 +2161,7 @@ static void get_vector(const char *data, int count, float *out, bool report_erro static slider_state *slider_alloc(running_machine &machine, int id, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg) { int size = sizeof(slider_state) + strlen(title); - slider_state *state = (slider_state *)auto_alloc_array_clear(machine, UINT8, size); + slider_state *state = reinterpret_cast<slider_state *>(auto_alloc_array_clear(machine, UINT8, size)); state->minval = minval; state->defval = defval; @@ -2169,7 +2169,6 @@ static slider_state *slider_alloc(running_machine &machine, int id, const char * state->incval = incval; state->update = update; state->arg = arg; - state->hidden = false; state->id = id; strcpy(state->description, title); @@ -2652,6 +2651,7 @@ void uniform::update() static_cast<float>(static_cast<int>(shadersys->curr_poly->get_prim_width() + 0.5f)), static_cast<float>(static_cast<int>(shadersys->curr_poly->get_prim_height() + 0.5f)) }; m_shader->set_vector("QuadDims", 2, quaddims); + printf("Quad Dims: %f, %f\n", quaddims[0], quaddims[1]); } break; } diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h index 74dd433a406..5fde8b93067 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.h +++ b/src/osd/modules/render/d3d/d3dhlsl.h @@ -267,17 +267,17 @@ struct hlsl_options struct slider_desc { - const char * name; - int minval; - int defval; - int maxval; - int step; - int slider_type; - int screen_type; - int id; - float scale; - const char * format; - std::vector<const char *> strings; + const char * name; + int minval; + int defval; + int maxval; + int step; + int slider_type; + int screen_type; + int id; + float scale; + const char * format; + std::vector<const char *> strings; }; class slider diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp index 88257150abd..630a50d73e3 100644 --- a/src/osd/modules/render/drawbgfx.cpp +++ b/src/osd/modules/render/drawbgfx.cpp @@ -23,6 +23,7 @@ // MAMEOS headers #include "emu.h" #include "window.h" +#include "rendutil.h" #include <bgfx/bgfxplatform.h> #include <bgfx/bgfx.h> @@ -31,6 +32,7 @@ #include <algorithm> #include "drawbgfx.h" +#include "copyutil.h" #include "bgfx/texturemanager.h" #include "bgfx/targetmanager.h" #include "bgfx/shadermanager.h" @@ -40,6 +42,9 @@ #include "bgfx/texture.h" #include "bgfx/target.h" #include "bgfx/chain.h" +#include "bgfx/vertex.h" +#include "bgfx/uniform.h" +#include "bgfx/slider.h" //============================================================ // DEBUGGING @@ -52,17 +57,13 @@ const uint16_t renderer_bgfx::CACHE_SIZE = 1024; const uint32_t renderer_bgfx::PACKABLE_SIZE = 128; const uint32_t renderer_bgfx::WHITE_HASH = 0x87654321; +const char* renderer_bgfx::WINDOW_PREFIX = "Window 0, "; //============================================================ // MACROS //============================================================ -#define GIBBERISH (0) - -//============================================================ -// INLINES -//============================================================ - +#define GIBBERISH (0) //============================================================ // TYPES @@ -102,6 +103,7 @@ int renderer_bgfx::create() { // create renderer + osd_options& options = downcast<osd_options &>(window().machine().options()); osd_dim wdim = window().get_size(); m_width[window().m_index] = wdim.width(); m_height[window().m_index] = wdim.height(); @@ -124,25 +126,54 @@ int renderer_bgfx::create() #else bgfx::sdlSetWindow(window().sdl_window()); #endif - bgfx::init(); + std::string backend(options.bgfx_backend()); + if (backend == "auto") + { + bgfx::init(); + } + else if (backend == "dx9" || backend == "d3d9") + { + bgfx::init(bgfx::RendererType::Direct3D9); + } + else if (backend == "dx11" || backend == "d3d11") + { + bgfx::init(bgfx::RendererType::Direct3D11); + } + else if (backend == "gles") + { + bgfx::init(bgfx::RendererType::OpenGLES); + } + else if (backend == "glsl" || backend == "opengl") + { + bgfx::init(bgfx::RendererType::OpenGL); + } + else if (backend == "metal") + { + bgfx::init(bgfx::RendererType::Metal); + } + else + { + printf("Unknown backend type '%s', going with auto-detection\n", backend.c_str()); + bgfx::init(); + } bgfx::reset(m_width[window().m_index], m_height[window().m_index], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); // Enable debug text. - bgfx::setDebug(window().machine().options().verbose() ? BGFX_DEBUG_STATS : BGFX_DEBUG_TEXT); + bgfx::setDebug(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_effects = new effect_manager(*m_shaders); - m_chains = new chain_manager(*m_textures, *m_targets, *m_effects, m_width[window().m_index], m_height[window().m_index]); + m_targets = new target_manager(options, *m_textures); + + m_shaders = new shader_manager(options); + m_effects = new effect_manager(options, *m_shaders); if (window().m_index != 0) { #ifdef OSD_WINDOWS - m_framebuffer = m_targets->create_target("backbuffer", window().m_hwnd, m_width[window().m_index], m_height[window().m_index]); + m_framebuffer = m_targets->create_backbuffer(window().m_hwnd, m_width[window().m_index], m_height[window().m_index]); #else - m_framebuffer = m_targets->create_target("backbuffer", sdlNativeWindowHandle(window().sdl_window()), m_width[window().m_index], m_height[window().m_index]); + m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(window().sdl_window()), m_width[window().m_index], m_height[window().m_index]); #endif bgfx::touch(window().m_index); } @@ -158,12 +189,17 @@ int renderer_bgfx::create() m_screen_effect[2] = m_effects->effect("screen_multiply"); m_screen_effect[3] = m_effects->effect("screen_add"); - //m_screen_chain[0] = m_chains->chain("test"); + m_chains = new chain_manager(options, *m_textures, *m_targets, *m_effects, m_width[window().m_index], m_height[window().m_index]); + m_screen_chain = m_chains->chain(options.bgfx_screen_chain(), window().machine(), window().m_index); + m_sliders_dirty = true; uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT; m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::RGBA8, CACHE_SIZE, CACHE_SIZE, nullptr, flags); - memset(m_white, 0xff, sizeof(uint32_t) * 16 * 16); + uint32_t shadow_flags = 0;//BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT; + m_textures->create_png_texture(window().machine().options().art_path(), options.bgfx_shadow_mask(), "shadow", shadow_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)); return 0; @@ -210,7 +246,7 @@ int renderer_bgfx::xy_to_render_target(int x, int y, int *xt, int *yt) // drawbgfx_window_draw //============================================================ -bgfx::VertexDecl renderer_bgfx::ScreenVertex::ms_decl; +bgfx::VertexDecl ScreenVertex::ms_decl; void renderer_bgfx::put_packed_quad(render_primitive *prim, UINT32 hash, ScreenVertex* vertex) { @@ -295,9 +331,120 @@ 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) +{ + uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP; + if (video_config.filter == 0) + { + texture_flags |= BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT; + } + + uint16_t tex_width(prim->texture.width); + uint16_t tex_height(prim->texture.height); + + const bgfx::Memory* mem = mame_texture_data_to_bgfx_texture_data(prim->flags & PRIMFLAG_TEXFORMAT_MASK, + tex_width, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base); + + 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_screen_chain->process(prim, view, view / m_screen_chain->applicable_passes(), *m_textures, window(), get_blend_state(PRIMFLAG_GET_BLENDMODE(prim->flags))); + + m_textures->add_provider("screen", nullptr); + delete texture; +} + +void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen) +{ + ScreenVertex* vertex = 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 }; + float u[4] = { prim->texcoords.tl.u, prim->texcoords.tr.u, prim->texcoords.bl.u, prim->texcoords.br.u }; + float v[4] = { prim->texcoords.tl.v, prim->texcoords.tr.v, prim->texcoords.bl.v, prim->texcoords.br.v }; + + if (false)//PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_SWAP_XY) + { + std::swap(u[1], u[2]); + std::swap(v[1], v[2]); + } + + if (false)//PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_FLIP_X) + { + std::swap(u[0], u[1]); + std::swap(v[0], v[1]); + std::swap(u[2], u[3]); + std::swap(v[2], v[3]); + } + + if (false)//PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_FLIP_Y) + { + std::swap(u[0], u[2]); + std::swap(v[0], v[2]); + std::swap(u[1], u[3]); + std::swap(v[1], v[3]); + } + + vertex[0].m_x = x[0]; + vertex[0].m_y = y[0]; + vertex[0].m_z = 0; + vertex[0].m_rgba = 0xffffffff; + vertex[0].m_u = u[0]; + vertex[0].m_v = v[0]; + + vertex[1].m_x = x[1]; + vertex[1].m_y = y[1]; + vertex[1].m_z = 0; + vertex[1].m_rgba = 0xffffffff; + vertex[1].m_u = u[1]; + vertex[1].m_v = v[1]; + + vertex[2].m_x = x[3]; + vertex[2].m_y = y[3]; + vertex[2].m_z = 0; + vertex[2].m_rgba = 0xffffffff; + vertex[2].m_u = u[3]; + vertex[2].m_v = v[3]; + + vertex[3].m_x = x[3]; + vertex[3].m_y = y[3]; + vertex[3].m_z = 0; + vertex[3].m_rgba = 0xffffffff; + vertex[3].m_u = u[3]; + vertex[3].m_v = v[3]; + + vertex[4].m_x = x[2]; + vertex[4].m_y = y[2]; + vertex[4].m_z = 0; + vertex[4].m_rgba = 0xffffffff; + vertex[4].m_u = u[2]; + vertex[4].m_v = v[2]; + + vertex[5].m_x = x[0]; + vertex[5].m_y = y[0]; + vertex[5].m_z = 0; + vertex[5].m_rgba = 0xffffffff; + vertex[5].m_u = u[0]; + vertex[5].m_v = v[0]; + + UINT32 blend = PRIMFLAG_GET_BLENDMODE(prim->flags); + bgfx::setVertexBuffer(buffer); + bgfx::setTexture(0, m_screen_effect[blend]->uniform("s_tex")->handle(), m_targets->target("output" + std::to_string(screen))->texture()); + m_screen_effect[blend]->submit(view); +} + void renderer_bgfx::render_textured_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer) { - ScreenVertex* vertex = (ScreenVertex*)buffer->data; + ScreenVertex* vertex = reinterpret_cast<ScreenVertex*>(buffer->data); UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255); @@ -342,7 +489,6 @@ void renderer_bgfx::render_textured_quad(int view, render_primitive* prim, bgfx: vertex[5].m_rgba = rgba; vertex[5].m_u = prim->texcoords.tl.u; vertex[5].m_v = prim->texcoords.tl.v; - bgfx::setVertexBuffer(buffer); uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP; if (video_config.filter == 0) @@ -350,13 +496,18 @@ void renderer_bgfx::render_textured_quad(int view, render_primitive* prim, bgfx: texture_flags |= BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT; } - const bgfx::Memory* mem = mame_texture_data_to_bgfx_texture_data(prim->flags & PRIMFLAG_TEXFORMAT_MASK, - prim->texture.width, prim->texture.height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base); + uint16_t tex_width(prim->texture.width); + uint16_t tex_height(prim->texture.height); - bgfx::TextureHandle texture = bgfx::createTexture2D((uint16_t)prim->texture.width, (uint16_t)prim->texture.height, 1, bgfx::TextureFormat::RGBA8, texture_flags, mem); + const bgfx::Memory* mem = mame_texture_data_to_bgfx_texture_data(prim->flags & PRIMFLAG_TEXFORMAT_MASK, + tex_width, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base); + + bgfx::TextureHandle texture = bgfx::createTexture2D(tex_width, tex_height, 1, bgfx::TextureFormat::RGBA8, texture_flags, mem); bgfx_effect** effects = PRIMFLAG_GET_SCREENTEX(prim->flags) ? m_screen_effect : m_gui_effect; + UINT32 blend = PRIMFLAG_GET_BLENDMODE(prim->flags); + bgfx::setVertexBuffer(buffer); bgfx::setTexture(0, effects[blend]->uniform("s_tex")->handle(), texture); effects[blend]->submit(view); @@ -552,176 +703,6 @@ uint32_t renderer_bgfx::u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a return (a << 24) | (b << 16) | (g << 8) | r; } -//============================================================ -// copyline_palette16 -//============================================================ - -static inline void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette) -{ - for (int x = 0; x < width; x++) - { - rgb_t srcpixel = palette[*src++]; - *dst++ = 0xff000000 | (srcpixel.b() << 16) | (srcpixel.g() << 8) | srcpixel.r(); - } -} - - -//============================================================ -// copyline_palettea16 -//============================================================ - -static inline void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette) -{ - for (int x = 0; x < width; x++) - { - rgb_t srcpixel = palette[*src++]; - *dst++ = (srcpixel.a() << 24) | (srcpixel.b() << 16) | (srcpixel.g() << 8) | srcpixel.r(); - } -} - - -//============================================================ -// copyline_rgb32 -//============================================================ - -static inline void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette) -{ - int x; - - // palette (really RGB map) case - if (palette != nullptr) - { - for (x = 0; x < width; x++) - { - rgb_t srcpix = *src++; - *dst++ = 0xff000000 | palette[0x200 + srcpix.b()] | palette[0x100 + srcpix.g()] | palette[srcpix.r()]; - } - } - - // direct case - else - { - for (x = 0; x < width; x++) - { - rgb_t srcpix = *src++; - *dst++ = 0xff000000 | (srcpix.b() << 16) | (srcpix.g() << 8) | srcpix.r(); - } - } -} - - -//============================================================ -// copyline_argb32 -//============================================================ - -static inline void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette) -{ - int x; - // palette (really RGB map) case - if (palette != nullptr) - { - for (x = 0; x < width; x++) - { - rgb_t srcpix = *src++; - *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.b()] | palette[0x100 + srcpix.g()] | palette[srcpix.r()]; - } - } - - // direct case - else - { - for (x = 0; x < width; x++) - { - rgb_t srcpix = *src++; - *dst++ = (srcpix.a() << 24) | (srcpix.b() << 16) | (srcpix.g() << 8) | srcpix.r(); - } - } -} - -static inline UINT32 ycc_to_rgb(UINT8 y, UINT8 cb, UINT8 cr) -{ - /* original equations: - - C = Y - 16 - D = Cb - 128 - E = Cr - 128 - - R = clip(( 298 * C + 409 * E + 128) >> 8) - G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) - B = clip(( 298 * C + 516 * D + 128) >> 8) - - R = clip(( 298 * (Y - 16) + 409 * (Cr - 128) + 128) >> 8) - G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8) - B = clip(( 298 * (Y - 16) + 516 * (Cb - 128) + 128) >> 8) - - R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) - G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) - B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) - - R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) - G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) - B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) - */ - int r, g, b, common; - - common = 298 * y - 298 * 16; - r = (common + 409 * cr - 409 * 128 + 128) >> 8; - g = (common - 100 * cb + 100 * 128 - 208 * cr + 208 * 128 + 128) >> 8; - b = (common + 516 * cb - 516 * 128 + 128) >> 8; - - if (r < 0) r = 0; - else if (r > 255) r = 255; - if (g < 0) g = 0; - else if (g > 255) g = 255; - if (b < 0) b = 0; - else if (b > 255) b = 255; - - return 0xff000000 | (b << 16) | (g << 8) | r; -} - -//============================================================ -// copyline_yuy16_to_argb -//============================================================ - -static inline void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xprescale) -{ - int x; - - assert(width % 2 == 0); - - // palette (really RGB map) case - if (palette != nullptr) - { - for (x = 0; x < width / 2; x++) - { - UINT16 srcpix0 = *src++; - UINT16 srcpix1 = *src++; - UINT8 cb = srcpix0 & 0xff; - UINT8 cr = srcpix1 & 0xff; - for (int x2 = 0; x2 < xprescale; x2++) - *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); - for (int x2 = 0; x2 < xprescale; x2++) - *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); - } - } - - // direct case - else - { - for (x = 0; x < width; x += 2) - { - UINT16 srcpix0 = *src++; - UINT16 srcpix1 = *src++; - UINT8 cb = srcpix0 & 0xff; - UINT8 cr = srcpix1 & 0xff; - for (int x2 = 0; x2 < xprescale; x2++) - *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); - for (int x2 = 0; x2 < xprescale; x2++) - *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); - } - } -} - const bgfx::Memory* renderer_bgfx::mame_texture_data_to_bgfx_texture_data(UINT32 format, int width, int height, int rowpixels, const rgb_t *palette, void *base) { const bgfx::Memory* mem = bgfx::alloc(width * height * 4); @@ -730,19 +711,19 @@ const bgfx::Memory* renderer_bgfx::mame_texture_data_to_bgfx_texture_data(UINT32 switch (format) { case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16): - copyline_palette16((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette); + copy_util::copyline_palette16((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette); break; case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTEA16): - copyline_palettea16((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette); + copy_util::copyline_palettea16((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette); break; case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16): - copyline_yuy16_to_argb((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette, 1); + copy_util::copyline_yuy16_to_argb((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette, 1); break; case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32): - copyline_argb32((UINT32*)mem->data + y * width, (UINT32*)base + y * rowpixels, width, palette); + copy_util::copyline_argb32((UINT32*)mem->data + y * width, (UINT32*)base + y * rowpixels, width, palette); break; case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32): - copyline_rgb32((UINT32*)mem->data + y * width, (UINT32*)base + y * rowpixels, width, palette); + copy_util::copyline_rgb32((UINT32*)mem->data + y * width, (UINT32*)base + y * rowpixels, width, palette); break; default: break; @@ -751,67 +732,99 @@ const bgfx::Memory* renderer_bgfx::mame_texture_data_to_bgfx_texture_data(UINT32 return mem; } +int renderer_bgfx::handle_screen_chains() +{ + if (!m_screen_chain) + { + return 0; + } + + window().m_primlist->acquire_lock(); + + // process + render_primitive *prim = window().m_primlist->first(); + + int seen = 0; + while (prim != nullptr) + { + if (PRIMFLAG_GET_SCREENTEX(prim->flags)) + { + process_screen_quad(m_screen_chain->applicable_passes() * seen, prim); + seen++; + } + prim = prim->next(); + } + + window().m_primlist->release_lock(); + + uint32_t total_passes = seen * m_screen_chain->applicable_passes(); + bgfx::setViewFrameBuffer(total_passes, BGFX_INVALID_HANDLE); + + return total_passes; +} + int renderer_bgfx::draw(int update) { - int index = window().m_index; - // Set view 0 default viewport. + int window_index = window().m_index; + int post_view_index = handle_screen_chains(); + int view_index = window_index; + int first_view_index = 0; + if (m_screen_chain && post_view_index > 0) + { + view_index += post_view_index; + first_view_index = post_view_index; + } + + // Set view 0 default viewport. osd_dim wdim = window().get_size(); - m_width[index] = wdim.width(); - m_height[index] = wdim.height(); - if (index == 0) + m_width[window_index] = wdim.width(); + m_height[window_index] = wdim.height(); + if (window_index == 0) { - if ((m_dimensions != osd_dim(m_width[index], m_height[index]))) + if ((m_dimensions != osd_dim(m_width[window_index], m_height[window_index]))) { - bgfx::reset(m_width[index], m_height[index], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); - m_dimensions = osd_dim(m_width[index], m_height[index]); + bgfx::reset(m_width[window_index], m_height[window_index], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); + m_dimensions = osd_dim(m_width[window_index], m_height[window_index]); } } else { - if ((m_dimensions != osd_dim(m_width[index], m_height[index]))) + if ((m_dimensions != osd_dim(m_width[window_index], m_height[window_index]))) { bgfx::reset(window().m_main->get_size().width(), window().m_main->get_size().height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); delete m_framebuffer; #ifdef OSD_WINDOWS - m_framebuffer = m_targets->create_target("backbuffer", window().m_hwnd, m_width[index], m_height[index]); + m_framebuffer = m_targets->create_backbuffer(window().m_hwnd, m_width[window_index], m_height[window_index]); #else - m_framebuffer = m_targets->create_target("backbuffer", sdlNativeWindowHandle(window().sdl_window()), m_width[index], m_height[index]); + m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(window().sdl_window()), m_width[window_index], m_height[window_index]); #endif - bgfx::setViewFrameBuffer(index, m_framebuffer->target()); - m_dimensions = osd_dim(m_width[index], m_height[index]); - bgfx::setViewClear(index + bgfx::setViewFrameBuffer(view_index, m_framebuffer->target()); + m_dimensions = osd_dim(m_width[window_index], m_height[window_index]); + bgfx::setViewClear(view_index , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH , 0x000000ff , 1.0f , 0 ); - bgfx::touch(index); + bgfx::touch(view_index); bgfx::frame(); return 0; } } - if (index != 0) + if (view_index != first_view_index) { - bgfx::setViewFrameBuffer(index, m_framebuffer->target()); + bgfx::setViewFrameBuffer(view_index, m_framebuffer->target()); } - bgfx::setViewSeq(index, true); - bgfx::setViewRect(index, 0, 0, m_width[index], m_height[index]); + bgfx::setViewSeq(view_index, true); + bgfx::setViewRect(view_index, 0, 0, m_width[window_index], m_height[window_index]); // Setup view transform. - { - float view[16]; - bx::mtxIdentity(view); - - float left = 0.0f; - float top = 0.0f; - float right = m_width[index]; - float bottom = m_height[index]; - float proj[16]; - bx::mtxOrtho(proj, left, right, bottom, top, 0.0f, 100.0f); - bgfx::setViewTransform(index, view, proj); - } - bgfx::setViewClear(index + float proj[16]; + bx::mtxOrtho(proj, 0.0f, m_width[window_index], m_height[window_index], 0.0f, 0.0f, 100.0f); + bgfx::setViewTransform(view_index, nullptr, proj); + + bgfx::setViewClear(view_index , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH , 0x000000ff , 1.0f @@ -824,6 +837,7 @@ int renderer_bgfx::draw(int update) bool atlas_valid = update_atlas(); render_primitive *prim = window().m_primlist->first(); + int32_t screen = 0; while (prim != nullptr) { UINT32 blend = PRIMFLAG_GET_BLENDMODE(prim->flags); @@ -831,13 +845,18 @@ int renderer_bgfx::draw(int update) bgfx::TransientVertexBuffer buffer; allocate_buffer(prim, blend, &buffer); - buffer_status status = buffer_primitives(index, atlas_valid, &prim, &buffer); + buffer_status status = buffer_primitives(view_index, atlas_valid, &prim, &buffer, screen); + + if (status == BUFFER_SCREEN) + { + screen++; + } - if (status != BUFFER_EMPTY) + if (status != BUFFER_EMPTY && status != BUFFER_SCREEN) { bgfx::setVertexBuffer(&buffer); - bgfx::setTexture(0, m_gui_effect[blend]->uniform("s_tex")->handle(), m_texture_cache->handle()); - m_gui_effect[blend]->submit(index); + bgfx::setTexture(0, m_gui_effect[blend]->uniform("s_tex")->handle(), m_texture_cache->texture()); + m_gui_effect[blend]->submit(view_index); } if (status != BUFFER_DONE && status != BUFFER_PRE_FLUSH) @@ -850,16 +869,19 @@ int renderer_bgfx::draw(int update) // This dummy draw call is here to make sure that view 0 is cleared // if no other draw calls are submitted to view 0. - bgfx::touch(index); + bgfx::touch(view_index); // Advance to next frame. Rendering thread will be kicked to // process submitted rendering primitives. - if (index==0) bgfx::frame(); + if (view_index == first_view_index) + { + bgfx::frame(); + } return 0; } -renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(int view, bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer) +renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(int view, bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen) { int vertices = 0; @@ -893,8 +915,17 @@ renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(int view, bool atl { return BUFFER_PRE_FLUSH; } - render_textured_quad(view, *prim, buffer); - return BUFFER_EMPTY; + + if (PRIMFLAG_GET_SCREENTEX((*prim)->flags) && m_screen_chain != nullptr) + { + render_post_screen_quad(view, *prim, buffer, screen); + return BUFFER_SCREEN; + } + else + { + render_textured_quad(view, *prim, buffer); + return BUFFER_EMPTY; + } } } break; @@ -923,25 +954,26 @@ renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(int view, bool atl return BUFFER_FLUSH; } -void renderer_bgfx::set_bgfx_state(UINT32 blend) +uint64_t renderer_bgfx::get_blend_state(UINT32 blend) { - uint64_t flags = BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_DEPTH_TEST_ALWAYS; - switch (blend) { - case BLENDMODE_NONE: - bgfx::setState(flags); - break; case BLENDMODE_ALPHA: - bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)); - break; + return BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA); case BLENDMODE_RGB_MULTIPLY: - bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO)); - break; + return BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO); case BLENDMODE_ADD: - bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE)); - break; + return BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE); + default: + return 0L; } + return 0L; +} + +void renderer_bgfx::set_bgfx_state(UINT32 blend) +{ + uint64_t flags = BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_DEPTH_TEST_ALWAYS; + bgfx::setState(flags | get_blend_state(blend)); } bool renderer_bgfx::update_atlas() @@ -985,7 +1017,7 @@ void renderer_bgfx::process_atlas_packs(std::vector<std::vector<rectangle_packer } m_hash_to_entry[rect.hash()] = rect; const bgfx::Memory* mem = mame_texture_data_to_bgfx_texture_data(rect.format(), rect.width(), rect.height(), rect.rowpixels(), rect.palette(), rect.base()); - bgfx::updateTexture2D(m_texture_cache->handle(), 0, rect.x(), rect.y(), rect.width(), rect.height(), mem); + bgfx::updateTexture2D(m_texture_cache->texture(), 0, rect.x(), rect.y(), rect.width(), rect.height(), mem); } } } @@ -1053,7 +1085,6 @@ bool renderer_bgfx::check_for_dirty_atlas() void renderer_bgfx::allocate_buffer(render_primitive *prim, UINT32 blend, bgfx::TransientVertexBuffer *buffer) { int vertices = 0; - bool mode_switched = false; while (prim != nullptr && !mode_switched) { @@ -1072,11 +1103,11 @@ void renderer_bgfx::allocate_buffer(render_primitive *prim, UINT32 blend, bgfx:: } else { - mode_switched = true; if (vertices == 0) { vertices += 6; } + mode_switched = true; } } else @@ -1105,5 +1136,30 @@ void renderer_bgfx::allocate_buffer(render_primitive *prim, UINT32 blend, bgfx:: slider_state* renderer_bgfx::get_slider_list() { - return nullptr; + if (!m_screen_chain) + { + return nullptr; + } + + slider_state *listhead = nullptr; + slider_state **tailptr = &listhead; + std::vector<bgfx_slider*> sliders = m_screen_chain->sliders(); + for (bgfx_slider* slider : sliders) + { + if (*tailptr == nullptr) + { + *tailptr = slider->core_slider(); + } + else + { + (*tailptr)->next = slider->core_slider(); + tailptr = &(*tailptr)->next; + } + } + if (*tailptr != nullptr) + { + (*tailptr)->next = nullptr; + } + m_sliders_dirty = false; + return listhead; } diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h index 806bc651344..793f0340767 100644 --- a/src/osd/modules/render/drawbgfx.h +++ b/src/osd/modules/render/drawbgfx.h @@ -11,6 +11,7 @@ #include <vector> #include "binpacker.h" +#include "bgfx/vertex.h" class texture_manager; class target_manager; @@ -38,7 +39,9 @@ public: virtual int create() override; virtual slider_state* get_slider_list() override; + virtual bool multi_window_sliders() override { return true; } virtual int draw(const int update) override; + #ifdef OSD_SDL virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; #else @@ -46,54 +49,42 @@ public: virtual void record() override { } virtual void toggle_fsfx() override { } #endif - virtual render_primitive_list *get_primitives() override + + virtual render_primitive_list *get_primitives() override { osd_dim wdim = window().get_size(); window().target()->set_bounds(wdim.width(), wdim.height(), window().aspect()); return &window().target()->get_primitives(); } + static const char* WINDOW_PREFIX; + private: - struct ScreenVertex - { - float m_x; - float m_y; - float m_z; - UINT32 m_rgba; - float m_u; - float m_v; - - static void init() - { - ms_decl.begin() - .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) - .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) - .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float) - .end(); - } - - static bgfx::VertexDecl ms_decl; - }; + int handle_screen_chains(); void allocate_buffer(render_primitive *prim, UINT32 blend, bgfx::TransientVertexBuffer *buffer); enum buffer_status { BUFFER_PRE_FLUSH, BUFFER_FLUSH, + BUFFER_SCREEN, BUFFER_EMPTY, BUFFER_DONE }; - buffer_status buffer_primitives(int view, bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer); + buffer_status buffer_primitives(int view, bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen); + void process_screen_quad(int view, render_primitive* prim); void render_textured_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer); + void render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen); void put_packed_quad(render_primitive *prim, UINT32 hash, ScreenVertex* vertex); void put_polygon(const float* coords, UINT32 num_coords, float r, UINT32 rgba, ScreenVertex* vertex); void put_line(float x0, float y0, float x1, float y1, float r, UINT32 rgba, ScreenVertex* vertex, float fth = 1.0f); void set_bgfx_state(UINT32 blend); + uint64_t get_blend_state(UINT32 blend); - uint32_t u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a); + static uint32_t u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a); bool check_for_dirty_atlas(); bool update_atlas(); @@ -115,7 +106,7 @@ private: bgfx_effect* m_gui_effect[4]; bgfx_effect* m_screen_effect[4]; - //bgfx_chain* m_screen_chain[4]; + bgfx_chain* m_screen_chain; std::map<UINT32, rectangle_packer::packed_rectangle> m_hash_to_entry; std::vector<rectangle_packer::packable_rectangle> m_texinfo; @@ -124,6 +115,7 @@ private: uint32_t m_width[16]; uint32_t m_height[16]; uint32_t m_white[16*16]; + static const uint16_t CACHE_SIZE; static const uint32_t PACKABLE_SIZE; static const uint32_t WHITE_HASH; diff --git a/src/osd/sdl/osdsdl.h b/src/osd/sdl/osdsdl.h index c4749be03c5..ddeabebc386 100644 --- a/src/osd/sdl/osdsdl.h +++ b/src/osd/sdl/osdsdl.h @@ -142,6 +142,9 @@ public: virtual void init(running_machine &machine) override; virtual void update(bool skip_redraw) override; + // video overridables + virtual slider_state *get_slider_list() override; + // input overridables virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override; @@ -165,6 +168,10 @@ public: sdl_options &options() { return m_options; } +protected: + virtual void build_slider_list() override; + virtual void update_slider_list() override; + private: virtual void osd_exit() override; @@ -173,7 +180,7 @@ private: sdl_options &m_options; watchdog *m_watchdog; - + slider_state * m_sliders; }; //============================================================ diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp index b089988c84a..051b8d07c44 100644 --- a/src/osd/sdl/video.cpp +++ b/src/osd/sdl/video.cpp @@ -140,6 +140,60 @@ float osd_monitor_info::aspect() +//============================================================ +// update_slider_list +//============================================================ + +void sdl_osd_interface::update_slider_list() +{ + for (sdl_window_info *window = sdl_window_list; window != nullptr; window = window->m_next) + { + if (window->renderer().sliders_dirty()) + { + build_slider_list(); + return; + } + } +} + +//============================================================ +// get_slider_list +//============================================================ + +slider_state *sdl_osd_interface::get_slider_list() +{ + return m_sliders; +} + +//============================================================ +// build_slider_list +//============================================================ + +void sdl_osd_interface::build_slider_list() +{ + m_sliders = nullptr; + slider_state *curr = m_sliders; + for (sdl_window_info *info = sdl_window_list; info != nullptr; info = info->m_next) + { + slider_state *window_sliders = info->renderer().get_slider_list(); + if (window_sliders != nullptr) + { + if (m_sliders == nullptr) + { + m_sliders = window_sliders; + curr = m_sliders; + } + else + { + while (curr->next != nullptr) + { + curr = curr->next; + } + curr->next = window_sliders; + } + } + } +} //============================================================ // update @@ -152,6 +206,8 @@ void sdl_osd_interface::update(bool skip_redraw) if (m_watchdog != NULL) m_watchdog->reset(); + update_slider_list(); + // if we're not skipping this redraw, update all windows if (!skip_redraw) { @@ -380,10 +436,10 @@ void sdl_osd_interface::extract_video_config() if (options().seconds_to_run() == 0) osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n"); } -#if (USE_OPENGL) +#if (USE_OPENGL) else if (strcmp(stemp, SDLOPTVAL_OPENGL) == 0) video_config.mode = VIDEO_MODE_OPENGL; -#endif +#endif else if ((strcmp(stemp, SDLOPTVAL_SDL2ACCEL) == 0)) { video_config.mode = VIDEO_MODE_SDL2ACCEL; diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp index b58167f128c..f0f947ba503 100644 --- a/src/osd/sdl/window.cpp +++ b/src/osd/sdl/window.cpp @@ -90,9 +90,6 @@ sdl_window_info *sdl_window_list; static sdl_window_info **last_window_ptr; // event handling -static int multithreading_enabled; -static osd_work_queue *work_queue; - static SDL_threadID main_threadid; static SDL_threadID window_threadid; @@ -145,12 +142,7 @@ static inline void execute_async(osd_work_callback callback, const worker_param { worker_param *wp_temp = (worker_param *) osd_malloc(sizeof(worker_param)); *wp_temp = wp; - - if (multithreading_enabled) - { - osd_work_item_queue(work_queue, callback, (void *) wp_temp, WORK_ITEM_FLAG_AUTO_RELEASE); - } else - callback((void *) wp_temp, 0); + callback((void *) wp_temp, 0); } static inline void execute_sync(osd_work_callback callback, const worker_param &wp) @@ -202,28 +194,13 @@ static OSDWORK_CALLBACK(sdlwindow_thread_id) bool sdl_osd_interface::window_init() { osd_printf_verbose("Enter sdlwindow_init\n"); - // determine if we are using multithreading or not - multithreading_enabled = false;//options().multithreading(); // get the main thread ID before anything else main_threadid = SDL_ThreadID(); - // if multithreading, create a thread to run the windows - if (multithreading_enabled) - { - // create a thread to run the windows from - work_queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_IO); - if (work_queue == nullptr) - return false; - osd_work_item_queue(work_queue, &sdlwindow_thread_id, nullptr, WORK_ITEM_FLAG_AUTO_RELEASE); - sdlwindow_sync(); - } - else - { - // otherwise, treat the window thread as the main thread - //window_threadid = main_threadid; - sdlwindow_thread_id(nullptr, 0); - } + // otherwise, treat the window thread as the main thread + //window_threadid = main_threadid; + sdlwindow_thread_id(nullptr, 0); // initialize the drawers if (video_config.mode == VIDEO_MODE_BGFX) @@ -304,15 +281,7 @@ bool sdl_osd_interface::window_init() static void sdlwindow_sync(void) { - if (multithreading_enabled) - { - // Fallback - while (!osd_work_queue_wait(work_queue, osd_ticks_per_second()*10)) - { - osd_printf_warning("sdlwindow_sync: Sleeping...\n"); - osd_sleep(osd_ticks_per_second() / 1000 * 100); - } - } + // haha, do nothing, losers } @@ -370,19 +339,8 @@ void sdl_osd_interface::window_exit() break; } - // if we're multithreaded, clean up the window thread - if (multithreading_enabled) - { - sdlwindow_sync(); - } - execute_async_wait(&sdlwindow_exit_wt, wp_dummy); - if (multithreading_enabled) - { - osd_work_queue_wait(work_queue, 1000000); - osd_work_queue_free(work_queue); - } osd_printf_verbose("Leave sdlwindow_exit\n"); } @@ -726,18 +684,7 @@ int sdl_window_info::window_init() wp->set_window(this); - // FIXME: pass error back in a different way - if (multithreading_enabled) - { - osd_work_item *wi; - - wi = osd_work_item_queue(work_queue, &sdl_window_info::complete_create_wt, (void *) wp, 0); - sdlwindow_sync(); - result = *((int *) (osd_work_item_result)(wi)); - osd_work_item_release(wi); - } - else - result = *((int *) sdl_window_info::complete_create_wt((void *) wp, 0)); + result = *((int *) sdl_window_info::complete_create_wt((void *) wp, 0)); // handle error conditions if (result == 1) @@ -786,10 +733,6 @@ void sdl_window_info::destroy() sdl_window_info **prevptr; ASSERT_MAIN_THREAD(); - if (multithreading_enabled) - { - sdlwindow_sync(); - } //osd_event_wait(window->rendered_event, osd_ticks_per_second()*10); diff --git a/src/osd/sdl/window.h b/src/osd/sdl/window.h index 6cb2a497ebb..c7ba6201e7b 100644 --- a/src/osd/sdl/window.h +++ b/src/osd/sdl/window.h @@ -87,6 +87,7 @@ public: osd_dim blit_surface_size() override; int prescale() const { return m_prescale; } + osd_renderer &renderer() const { return *m_renderer; } // Pointer to next window sdl_window_info * m_next; @@ -122,8 +123,7 @@ private: } static OSDWORK_CALLBACK( complete_create_wt ); -protected: - osd_renderer &renderer() { return *m_renderer; } + private: int wnd_extra_width(); int wnd_extra_height(); diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp index db8330cc858..a5da299cddd 100644 --- a/src/osd/windows/window.cpp +++ b/src/osd/windows/window.cpp @@ -101,8 +101,6 @@ static int in_background; static int ui_temp_pause; static int ui_temp_was_paused; -static int multithreading_enabled; - static HANDLE window_thread; static DWORD window_threadid; @@ -158,7 +156,6 @@ static void mtlog_dump(void) } #else void mtlog_add(const char *event) { } -static void mtlog_dump(void) { } #endif @@ -170,11 +167,6 @@ static void mtlog_dump(void) { } bool windows_osd_interface::window_init() { - size_t temp; - - // determine if we are using multithreading or not - multithreading_enabled = false;//downcast<windows_options &>(machine().options()).multithreading(); - // get the main thread ID before anything else main_threadid = GetCurrentThreadId(); @@ -186,30 +178,8 @@ bool windows_osd_interface::window_init() if (!ui_pause_event) fatalerror("Failed to create pause event\n"); - // if multithreading, create a thread to run the windows - if (multithreading_enabled) - { - // create an event to signal when the window thread is ready - window_thread_ready_event = CreateEvent(nullptr, TRUE, FALSE, nullptr); - if (!window_thread_ready_event) - fatalerror("Failed to create window thread ready event\n"); - - // create a thread to run the windows from - temp = _beginthreadex(nullptr, 0, win_window_info::thread_entry, this, 0, (unsigned *)&window_threadid); - window_thread = (HANDLE)temp; - if (window_thread == nullptr) - fatalerror("Failed to create window thread\n"); - - // set the thread priority equal to the main MAME thread - SetThreadPriority(window_thread, GetThreadPriority(GetCurrentThread())); - } - - // otherwise, treat the window thread as the main thread - else - { - window_thread = GetCurrentThread(); - window_threadid = main_threadid; - } + window_thread = GetCurrentThread(); + window_threadid = main_threadid; const int fallbacks[VIDEO_MODE_COUNT] = { -1, // NONE -> no fallback @@ -290,6 +260,16 @@ void windows_osd_interface::update_slider_list() } } +int windows_osd_interface::window_count() +{ + int count = 0; + for (win_window_info *info = win_window_list; info != nullptr; info = info->m_next) + { + count++; + } + return count; +} + void windows_osd_interface::build_slider_list() { // FIXME: take all sliders from all windows without concatenate them by slider_state->next @@ -343,15 +323,6 @@ void windows_osd_interface::window_exit() break; } - // if we're multithreaded, clean up the window thread - if (multithreading_enabled) - { - PostThreadMessage(window_threadid, WM_USER_SELF_TERMINATE, 0, 0); - WaitForSingleObject(window_thread, INFINITE); - - mtlog_dump(); - } - // kill the UI pause event if (ui_pause_event) CloseHandle(ui_pause_event); @@ -815,21 +786,7 @@ void win_window_info::create(running_machine &machine, int index, osd_monitor_in // set the initial maximized state window->m_startmaximized = options.maximize(); - // finish the window creation on the window thread - if (multithreading_enabled) - { - // wait until the window thread is ready to respond to events - WaitForSingleObject(window_thread_ready_event, INFINITE); - - PostThreadMessage(window_threadid, WM_USER_FINISH_CREATE_WINDOW, 0, (LPARAM)window); - while (window->m_init_state == 0) - { - winwindow_process_events(machine, 0, 1); //pump the message queue - Sleep(1); - } - } - else - window->m_init_state = window->complete_create() ? -1 : 1; + window->m_init_state = window->complete_create() ? -1 : 1; // handle error conditions if (window->m_init_state == -1) @@ -930,10 +887,7 @@ void win_window_info::update() // post a redraw request with the primitive list as a parameter last_update_time = timeGetTime(); mtlog_add("winwindow_video_window_update: PostMessage start"); - if (multithreading_enabled) - PostMessage(m_hwnd, WM_USER_REDRAW, 0, (LPARAM)primlist); - else - SendMessage(m_hwnd, WM_USER_REDRAW, 0, (LPARAM)primlist); + SendMessage(m_hwnd, WM_USER_REDRAW, 0, (LPARAM)primlist); mtlog_add("winwindow_video_window_update: PostMessage end"); } } @@ -1089,21 +1043,7 @@ void winwindow_ui_pause_from_main_thread(running_machine &machine, int pause) void winwindow_ui_pause_from_window_thread(running_machine &machine, int pause) { assert(GetCurrentThreadId() == window_threadid); - - // if we're multithreaded, we have to request a pause on the main thread - if (multithreading_enabled) - { - // request a pause from the main thread - PostThreadMessage(main_threadid, WM_USER_UI_TEMP_PAUSE, pause, 0); - - // if we're pausing, block until it happens - if (pause) - WaitForSingleObject(ui_pause_event, INFINITE); - } - - // otherwise, we just do it directly - else - winwindow_ui_pause_from_main_thread(machine, pause); + winwindow_ui_pause_from_main_thread(machine, pause); } @@ -1117,16 +1057,7 @@ void winwindow_ui_exec_on_main_thread(void (*func)(void *), void *param) { assert(GetCurrentThreadId() == window_threadid); - // if we're multithreaded, we have to request a pause on the main thread - if (multithreading_enabled) - { - // request a pause from the main thread - PostThreadMessage(main_threadid, WM_USER_EXEC_FUNC, (WPARAM) func, (LPARAM) param); - } - - // otherwise, we just do it directly - else - (*func)(param); + (*func)(param); } @@ -1525,10 +1456,7 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR // close: cause MAME to exit case WM_CLOSE: - if (multithreading_enabled) - PostThreadMessage(main_threadid, WM_QUIT, 0, 0); - else - window->machine().schedule_exit(); + window->machine().schedule_exit(); break; // destroy: clean up all attached rendering bits and nullptr out our hwnd diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp index 3a29e5f19ec..e81037c48b1 100644 --- a/src/osd/windows/winmain.cpp +++ b/src/osd/windows/winmain.cpp @@ -279,7 +279,7 @@ const options_entry windows_options::s_option_entries[] = { nullptr, nullptr, OPTION_HEADER, "DIRECTDRAW-SPECIFIC OPTIONS" }, { WINOPTION_HWSTRETCH ";hws", "1", OPTION_BOOLEAN, "enables hardware stretching" }, - // post-processing options + // D3D post-processing options { nullptr, nullptr, OPTION_HEADER, "DIRECT3D POST-PROCESSING OPTIONS" }, { WINOPTION_HLSL_ENABLE";hlsl", "0", OPTION_BOOLEAN, "enables HLSL post-processing (PS3.0 required)" }, { WINOPTION_HLSLPATH, "hlsl", OPTION_STRING, "path to hlsl files" }, @@ -561,7 +561,6 @@ void windows_osd_interface::init(running_machine &machine) if (profile > 0) { options.set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM, error_string); - options.set_value(OSDOPTION_MULTITHREADING, false, OPTION_PRIORITY_MAXIMUM, error_string); options.set_value(OSDOPTION_NUMPROCESSORS, 1, OPTION_PRIORITY_MAXIMUM, error_string); assert(error_string.empty()); } diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index 6ceecd2173a..9b5bac624fd 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -294,10 +294,14 @@ public: windows_options &options() { return m_options; } + int window_count(); + +protected: + virtual void build_slider_list() override; + virtual void update_slider_list() override; + private: virtual void osd_exit() override; - void build_slider_list(); - void update_slider_list(); windows_options & m_options; slider_state * m_sliders; |