diff options
Diffstat (limited to 'src/osd/modules/render')
215 files changed, 5860 insertions, 4402 deletions
diff --git a/src/osd/modules/render/aviwrite.cpp b/src/osd/modules/render/aviwrite.cpp index 9148244111b..e86d8f99ba6 100644 --- a/src/osd/modules/render/aviwrite.cpp +++ b/src/osd/modules/render/aviwrite.cpp @@ -32,7 +32,7 @@ avi_write::~avi_write() } } -void avi_write::record(const char *name) +void avi_write::record(std::string_view name) { if (m_recording) { @@ -48,7 +48,7 @@ void avi_write::stop() end_avi_recording(); } -void avi_write::begin_avi_recording(const char *name) +void avi_write::begin_avi_recording(std::string_view name) { // stop any existing recording end_avi_recording(); @@ -81,7 +81,7 @@ void avi_write::begin_avi_recording(const char *name) // create a new temporary movie file emu_file tempfile(m_machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - const std::error_condition filerr = (!name || !name[0] || !std::strcmp(name, OSDOPTVAL_AUTO)) + const std::error_condition filerr = (name.empty() || name == OSDOPTVAL_AUTO) ? m_machine.video().open_next(tempfile, "avi") : tempfile.open(name); diff --git a/src/osd/modules/render/aviwrite.h b/src/osd/modules/render/aviwrite.h index e59ce275168..a933dc2a3e6 100644 --- a/src/osd/modules/render/aviwrite.h +++ b/src/osd/modules/render/aviwrite.h @@ -6,13 +6,20 @@ // //============================================================ +#ifndef MAME_RENDER_AVIWRITE_H +#define MAME_RENDER_AVIWRITE_H + #pragma once -#ifndef __RENDER_AVIWRITE__ -#define __RENDER_AVIWRITE__ +// emu +#include "attotime.h" +// lib/util #include "aviio.h" +#include <string_view> + + class running_machine; class avi_write @@ -21,7 +28,7 @@ public: avi_write(running_machine& machine, uint32_t width, uint32_t height); ~avi_write(); - void record(const char *name); + void record(std::string_view name); void stop(); void audio_frame(const int16_t *buffer, int samples_this_frame); void video_frame(bitmap_rgb32& snap); @@ -30,7 +37,7 @@ public: bool recording() const { return m_recording; } private: - void begin_avi_recording(const char *name); + void begin_avi_recording(std::string_view name); void end_avi_recording(); running_machine& m_machine; @@ -47,4 +54,4 @@ private: attotime m_next_frame_time; }; -#endif // __RENDER_AVIWRITE__ +#endif // MAME_RENDER_AVIWRITE_H diff --git a/src/osd/modules/render/bgfx/blendreader.cpp b/src/osd/modules/render/bgfx/blendreader.cpp index 9e7ddb17ce3..53cd57a9f4a 100644 --- a/src/osd/modules/render/bgfx/blendreader.cpp +++ b/src/osd/modules/render/bgfx/blendreader.cpp @@ -44,8 +44,11 @@ uint64_t blend_reader::read_from_value(const Value& value) uint64_t equation = get_enum_from_value(value, "equation", BGFX_STATE_BLEND_EQUATION_ADD, EQUATION_NAMES, EQUATION_COUNT); uint64_t srccolor = get_enum_from_value(value, "srcColor", BGFX_STATE_BLEND_ONE, FUNCTION_NAMES, FUNCTION_COUNT); uint64_t dstcolor = get_enum_from_value(value, "dstColor", BGFX_STATE_BLEND_ZERO, FUNCTION_NAMES, FUNCTION_COUNT); - uint64_t srcalpha = get_enum_from_value(value, "srcAlpha", BGFX_STATE_BLEND_ONE, FUNCTION_NAMES, FUNCTION_COUNT); - uint64_t dstalpha = get_enum_from_value(value, "dstAlpha", BGFX_STATE_BLEND_ZERO, FUNCTION_NAMES, FUNCTION_COUNT); - - return BGFX_STATE_BLEND_EQUATION(equation) | BGFX_STATE_BLEND_FUNC_SEPARATE(srccolor, dstcolor, srcalpha, dstalpha); + if (value.HasMember("srcAlpha") && value.HasMember("dstAlpha")) + { + uint64_t srcalpha = get_enum_from_value(value, "srcAlpha", BGFX_STATE_BLEND_ONE, FUNCTION_NAMES, FUNCTION_COUNT); + uint64_t dstalpha = get_enum_from_value(value, "dstAlpha", BGFX_STATE_BLEND_ZERO, FUNCTION_NAMES, FUNCTION_COUNT); + return BGFX_STATE_BLEND_EQUATION(equation) | BGFX_STATE_BLEND_FUNC_SEPARATE(srccolor, dstcolor, srcalpha, dstalpha); + } + return BGFX_STATE_BLEND_EQUATION(equation) | BGFX_STATE_BLEND_FUNC(srccolor, dstcolor); } diff --git a/src/osd/modules/render/bgfx/chain.cpp b/src/osd/modules/render/bgfx/chain.cpp index b677569a67f..8d5adb0ec25 100644 --- a/src/osd/modules/render/bgfx/chain.cpp +++ b/src/osd/modules/render/bgfx/chain.cpp @@ -27,15 +27,24 @@ #include "clear.h" #include "modules/osdwindow.h" -bgfx_chain::bgfx_chain(std::string name, std::string author, bool transform, target_manager& targets, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries, std::vector<bgfx_target*> target_list, std::uint32_t screen_index) - : m_name(name) - , m_author(author) +bgfx_chain::bgfx_chain( + std::string &&name, + std::string &&author, + bool transform, + target_manager& targets, + std::vector<bgfx_slider*> &&sliders, + std::vector<bgfx_parameter*> &¶ms, + std::vector<bgfx_chain_entry*> &&entries, + std::vector<bgfx_target*> &&target_list, + std::uint32_t screen_index) + : m_name(std::move(name)) + , m_author(std::move(author)) , m_transform(transform) , m_targets(targets) - , m_sliders(sliders) - , m_params(params) - , m_entries(entries) - , m_target_list(target_list) + , m_sliders(std::move(sliders)) + , m_params(std::move(params)) + , m_entries(std::move(entries)) + , m_target_list(std::move(target_list)) , m_current_time(0) , m_screen_index(screen_index) , m_has_converter(false) @@ -78,7 +87,7 @@ void bgfx_chain::repopulate_targets() } } -void bgfx_chain::process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window& window, uint64_t blend) +void bgfx_chain::process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window& window) { screen_device_enumerator screen_iterator(window.machine().root_device()); screen_device* screen_device = screen_iterator.byindex(screen); @@ -108,11 +117,12 @@ void bgfx_chain::process(chain_manager::screen_prim &prim, int view, int screen, } int current_view = view; - for (bgfx_chain_entry* entry : m_entries) + for (size_t i = 0; i < m_entries.size(); i++) { - if (!entry->skip()) + if (!m_entries[i]->skip()) { - entry->submit(current_view, prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, blend, screen); + m_entries[i]->submit(current_view, prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, + rotation_type, swap_xy, screen); current_view++; } } @@ -145,7 +155,7 @@ uint32_t bgfx_chain::applicable_passes() return applicable_passes; } -void bgfx_chain::insert_effect(uint32_t index, bgfx_effect *effect, std::string name, std::string source, chain_manager &chains) +void bgfx_chain::insert_effect(uint32_t index, bgfx_effect *effect, const bool apply_tint, std::string name, std::string source, chain_manager &chains) { auto *clear = new clear_state(BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL, 0, 1.0f, 0); std::vector<bgfx_suppressor*> suppressors; @@ -164,11 +174,15 @@ void bgfx_chain::insert_effect(uint32_t index, bgfx_effect *effect, std::string uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_tex_size1", bgfx::UniformType::Vec4), values, 4)); uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_inv_tex_size0", bgfx::UniformType::Vec4), values, 4)); uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_inv_tex_size1", bgfx::UniformType::Vec4), values, 4)); + uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_tex_bounds0", bgfx::UniformType::Vec4), values, 4)); + uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_tex_bounds1", bgfx::UniformType::Vec4), values, 4)); + uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_inv_tex_bounds0", bgfx::UniformType::Vec4), values, 4)); + uniforms.push_back(new bgfx_value_uniform(new bgfx_uniform("u_inv_tex_bounds1", bgfx::UniformType::Vec4), values, 4)); - m_entries.insert(m_entries.begin() + index, new bgfx_chain_entry(name, effect, clear, suppressors, inputs, uniforms, m_targets, "screen", false)); + m_entries.insert(m_entries.begin() + index, new bgfx_chain_entry(name, effect, clear, suppressors, inputs, uniforms, m_targets, "screen", apply_tint)); const uint32_t screen_width = chains.targets().width(TARGET_STYLE_GUEST, m_screen_index); const uint32_t screen_height = chains.targets().height(TARGET_STYLE_GUEST, m_screen_index); m_targets.destroy_target("screen", m_screen_index); - m_targets.create_target("screen", bgfx::TextureFormat::BGRA8, screen_width, screen_height, TARGET_STYLE_GUEST, true, false, 1, m_screen_index); + m_targets.create_target("screen", bgfx::TextureFormat::BGRA8, screen_width, screen_height, 1, 1, TARGET_STYLE_GUEST, true, false, 1, m_screen_index); } diff --git a/src/osd/modules/render/bgfx/chain.h b/src/osd/modules/render/bgfx/chain.h index 5080532210c..5d84bb1ed0c 100644 --- a/src/osd/modules/render/bgfx/chain.h +++ b/src/osd/modules/render/bgfx/chain.h @@ -6,17 +6,17 @@ // //============================================================ +#ifndef MAME_RENDER_BGFX_CHAIN_H +#define MAME_RENDER_BGFX_CHAIN_H + #pragma once -#ifndef __DRAWBGFX_CHAIN__ -#define __DRAWBGFX_CHAIN__ +#include "chainentry.h" #include <string> #include <vector> #include <map> -#include "chainentry.h" - class bgfx_slider; class bgfx_parameter; class texture_manager; @@ -27,13 +27,14 @@ class osd_window; class bgfx_chain { public: - bgfx_chain(std::string name, std::string author, bool transform, target_manager& targets, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries, std::vector<bgfx_target*> target_list, uint32_t screen_index); + bgfx_chain(std::string &&name, std::string &&author, bool transform, target_manager& targets, std::vector<bgfx_slider*> &&sliders, std::vector<bgfx_parameter*> &¶ms, std::vector<bgfx_chain_entry*> &&entries, std::vector<bgfx_target*> &&target_list, uint32_t screen_index); ~bgfx_chain(); - void process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window &window, uint64_t blend = 0L); + void process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window &window); void repopulate_targets(); // Getters + const std::string &name() const { return m_name; } std::vector<bgfx_slider*>& sliders() { return m_sliders; } std::vector<bgfx_chain_entry*>& entries() { return m_entries; } uint32_t applicable_passes(); @@ -44,7 +45,7 @@ public: // Setters void set_has_converter(bool has_converter) { m_has_converter = has_converter; } void set_has_adjuster(bool has_adjuster) { m_has_adjuster = has_adjuster; } - void insert_effect(uint32_t index, bgfx_effect *effect, std::string name, std::string source, chain_manager &chains); + void insert_effect(uint32_t index, bgfx_effect *effect, const bool apply_tint, std::string name, std::string source, chain_manager &chains); private: std::string m_name; @@ -63,4 +64,4 @@ private: bool m_has_adjuster; }; -#endif // __DRAWBGFX_CHAIN__ +#endif // MAME_RENDER_BGFX_CHAIN_H diff --git a/src/osd/modules/render/bgfx/chainentry.cpp b/src/osd/modules/render/bgfx/chainentry.cpp index 45c0b805882..c3f3ee3a8e3 100644 --- a/src/osd/modules/render/bgfx/chainentry.cpp +++ b/src/osd/modules/render/bgfx/chainentry.cpp @@ -30,7 +30,8 @@ #include "render.h" -bgfx_chain_entry::bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output, bool apply_tint) +bgfx_chain_entry::bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs, + std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output, bool apply_tint) : m_name(name) , m_effect(effect) , m_clear(clear) @@ -55,12 +56,18 @@ bgfx_chain_entry::~bgfx_chain_entry() delete uniform; } m_uniforms.clear(); - delete m_clear; + if (m_clear) + { + delete m_clear; + } } -void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen) +void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, + float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen) { - if (!setup_view(textures, view, screen_width, screen_height, screen)) + uint16_t view_width = screen_width; + uint16_t view_height = screen_height; + if (!setup_view(textures, view, screen_width, screen_height, screen, view_width, view_height)) { return; } @@ -73,18 +80,19 @@ void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, textur uint32_t tint = 0xffffffff; if (m_apply_tint) { - const auto a = (uint8_t)std::round(prim.m_prim->color.a * 255); - const auto r = (uint8_t)std::round(prim.m_prim->color.r * 255); - const auto g = (uint8_t)std::round(prim.m_prim->color.g * 255); - const auto b = (uint8_t)std::round(prim.m_prim->color.b * 255); + const uint8_t a = (uint8_t)std::round(prim.m_prim->color.a * 255); + const uint8_t r = (uint8_t)std::round(prim.m_prim->color.r * 255); + const uint8_t g = (uint8_t)std::round(prim.m_prim->color.g * 255); + const uint8_t b = (uint8_t)std::round(prim.m_prim->color.b * 255); tint = (a << 24) | (b << 16) | (g << 8) | r; } bgfx::TransientVertexBuffer buffer; - put_screen_buffer(prim.m_screen_width, prim.m_screen_height, tint, &buffer); + put_screen_buffer(view_width, view_height, tint, &buffer); bgfx::setVertexBuffer(0, &buffer); - setup_auto_uniforms(prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, screen); + setup_auto_uniforms(prim, textures, screen_count, view_width, view_height, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, + rotation_type, swap_xy, screen); for (bgfx_entry_uniform* uniform : m_uniforms) { @@ -94,7 +102,7 @@ void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, textur } } - m_effect->submit(view, blend); + m_effect->submit(view); if (m_targets.target(screen, m_output) != nullptr) { @@ -102,6 +110,43 @@ void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, textur } } +void bgfx_chain_entry::setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t view_width, uint16_t view_height, + uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, + uint32_t rotation_type, bool swap_xy, int32_t screen) +{ + setup_viewsize_uniforms(view_width, view_height); + setup_screensize_uniforms(textures, screen_width, screen_height, screen); + setup_screenscale_uniforms(screen_scale_x, screen_scale_y); + setup_screenoffset_uniforms(screen_offset_x, screen_offset_y); + setup_screencount_uniforms(screen_count); + setup_sourcesize_uniform(prim); + setup_targetsize_uniform(screen); + setup_targetscale_uniform(screen); + setup_rotationtype_uniform(rotation_type); + setup_swapxy_uniform(swap_xy); + setup_quaddims_uniform(prim); + setup_screenindex_uniform(screen); +} + +void bgfx_chain_entry::setup_viewsize_uniforms(uint16_t view_width, uint16_t view_height) +{ + float width(view_width); + float height(view_height); + bgfx_uniform* view_dims = m_effect->uniform("u_view_dims"); + if (view_dims != nullptr) + { + float values[2] = { width, height }; + view_dims->set(values, sizeof(float) * 2); + } + + bgfx_uniform* inv_view_dims = m_effect->uniform("u_inv_view_dims"); + if (inv_view_dims != nullptr) + { + float values[2] = { -1.0f / width, 1.0f / height }; + inv_view_dims->set(values, sizeof(float) * 2); + } +} + void bgfx_chain_entry::setup_screensize_uniforms(texture_manager& textures, uint16_t screen_width, uint16_t screen_height, int32_t screen) { float width = screen_width; @@ -235,22 +280,8 @@ void bgfx_chain_entry::setup_screenindex_uniform(int32_t screen) const } } -void bgfx_chain_entry::setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen) -{ - setup_screensize_uniforms(textures, screen_width, screen_height, screen); - setup_screenscale_uniforms(screen_scale_x, screen_scale_y); - setup_screenoffset_uniforms(screen_offset_x, screen_offset_y); - setup_screencount_uniforms(screen_count); - setup_sourcesize_uniform(prim); - setup_targetsize_uniform(screen); - setup_targetscale_uniform(screen); - setup_rotationtype_uniform(rotation_type); - setup_swapxy_uniform(swap_xy); - setup_quaddims_uniform(prim); - setup_screenindex_uniform(screen); -} - -bool bgfx_chain_entry::setup_view(texture_manager &textures, int view, uint16_t screen_width, uint16_t screen_height, int32_t screen) const +bool bgfx_chain_entry::setup_view(texture_manager &textures, int view, uint16_t screen_width, uint16_t screen_height, int32_t screen, + uint16_t &out_view_width, uint16_t &out_view_height) const { bgfx::FrameBufferHandle handle = BGFX_INVALID_HANDLE; uint16_t width = screen_width; @@ -269,11 +300,13 @@ bool bgfx_chain_entry::setup_view(texture_manager &textures, int view, uint16_t bgfx::setViewFrameBuffer(view, handle); bgfx::setViewRect(view, 0, 0, width, height); + out_view_width = width; + out_view_height = height; const bgfx::Caps* caps = bgfx::getCaps(); std::string name = m_inputs[0]->texture() + std::to_string(screen); - const float right_ratio = (float)textures.provider(name)->width() / textures.provider(name)->rowpixels(); + const float right_ratio = float(textures.provider(name)->width()) / textures.provider(name)->rowpixels(); float projMat[16]; bx::mtxOrtho(projMat, 0.0f, right_ratio, 1.0f, 0.0f, 0.0f, 100.0f, 0.0f, caps->homogeneousDepth); @@ -307,14 +340,6 @@ void bgfx_chain_entry::put_screen_buffer(uint16_t screen_width, uint16_t screen_ v[0] = v[1] = 1; v[2] = v[3] = 0; } - else if (renderer_type == bgfx::RendererType::Direct3D9) - { - for (int i = 0; i < 4; i++) - { - u[i] += 0.5f / screen_width; - v[i] += 0.5f / screen_height; - } - } vertex[0].m_x = x[0]; vertex[0].m_y = y[0]; diff --git a/src/osd/modules/render/bgfx/chainentry.h b/src/osd/modules/render/bgfx/chainentry.h index 3fb1dd54ca6..a7504187879 100644 --- a/src/osd/modules/render/bgfx/chainentry.h +++ b/src/osd/modules/render/bgfx/chainentry.h @@ -34,10 +34,12 @@ class target_manager; class bgfx_chain_entry { public: - bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output, bool apply_tint); + bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs, + std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output, bool apply_tint); ~bgfx_chain_entry(); - void submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen); + void submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, + float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen); // Getters std::string name() const { return m_name; } @@ -45,7 +47,10 @@ public: bool skip(); private: - void setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen); + void setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t view_width, uint16_t view_height, + uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, + uint32_t rotation_type, bool swap_xy, int32_t screen); + void setup_viewsize_uniforms(uint16_t view_width, uint16_t view_height); void setup_screensize_uniforms(texture_manager& textures, uint16_t screen_width, uint16_t screen_height, int32_t screen); void setup_screenscale_uniforms(float screen_scale_x, float screen_scale_y); void setup_screenoffset_uniforms(float screen_offset_x, float screen_offset_y); @@ -58,7 +63,8 @@ private: void setup_quaddims_uniform(chain_manager::screen_prim &prim) const; void setup_screenindex_uniform(int32_t screen) const; - bool setup_view(texture_manager& textures, int view, uint16_t screen_width, uint16_t screen_height, int32_t screen) const; + bool setup_view(texture_manager& textures, int view, uint16_t screen_width, uint16_t screen_height, int32_t screen, + uint16_t &out_view_width, uint16_t &out_view_height) const; void put_screen_buffer(uint16_t screen_width, uint16_t screen_height, uint32_t screen_tint, bgfx::TransientVertexBuffer* buffer) const; std::string m_name; diff --git a/src/osd/modules/render/bgfx/chainentryreader.cpp b/src/osd/modules/render/bgfx/chainentryreader.cpp index c6b9953603f..ce58816e827 100644 --- a/src/osd/modules/render/bgfx/chainentryreader.cpp +++ b/src/osd/modules/render/bgfx/chainentryreader.cpp @@ -29,7 +29,13 @@ #include "clear.h" #include "clearreader.h" -bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params, uint32_t screen_index) +bgfx_chain_entry* chain_entry_reader::read_from_value( + const Value &value, + const std::string &prefix, + chain_manager &chains, + std::map<std::string, bgfx_slider*> &sliders, + std::map<std::string, bgfx_parameter*> ¶ms, + uint32_t screen_index) { if (!validate_parameters(value, prefix)) { @@ -52,18 +58,18 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s for (uint32_t i = 0; i < input_array.Size(); i++) { const Value& input = input_array[i]; - if (!READER_CHECK(input.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["sampler"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'sampler' must be a string\n").c_str())) return nullptr; + if (!READER_CHECK(input.HasMember("sampler"), "%sinput[%u]: Must have string value 'sampler' (what sampler are we binding to?)\n", prefix, i)) return nullptr; + if (!READER_CHECK(input["sampler"].IsString(), "%sinput[%u]: Value 'sampler' must be a string\n", prefix, i)) return nullptr; bool has_texture = input.HasMember("texture"); bool has_target = input.HasMember("target"); bool has_option = input.HasMember("option"); - if (!READER_CHECK(has_texture || has_target || has_option, (prefix + "input[" + std::to_string(i) + ": Must have string value 'target', 'texture' or 'option' (what source are we using?)\n").c_str())) return nullptr; - if (!READER_CHECK(!has_texture || input["texture"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'texture' must be a string\n").c_str())) return nullptr; - if (!READER_CHECK(!has_target || input["target"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'target' must be a string\n").c_str())) return nullptr; - if (!READER_CHECK(!has_option || input["option"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'option' must be a string\n").c_str())) return nullptr; - if (!READER_CHECK(has_target || !input.HasMember("bilinear") || input["bilinear"].IsBool(), (prefix + "input[" + std::to_string(i) + ": Value 'bilinear' must be a boolean\n").c_str())) return nullptr; - if (!READER_CHECK(has_target || !input.HasMember("clamp") || input["clamp"].IsBool(), (prefix + "input[" + std::to_string(i) + ": Value 'clamp' must be a boolean\n").c_str())) return nullptr; - if (!READER_CHECK(has_texture || has_option || !input.HasMember("selection") || input["selection"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'selection' must be a string\n").c_str())) return nullptr; + if (!READER_CHECK(has_texture || has_target || has_option, "%sinput[%u]: Must have string value 'target', 'texture' or 'option' (what source are we using?)\n", prefix, i)) return nullptr; + if (!READER_CHECK(!has_texture || input["texture"].IsString(), "%sinput[%u]: Value 'texture' must be a string\n", prefix, i)) return nullptr; + if (!READER_CHECK(!has_target || input["target"].IsString(), "%sinput[%u]: Value 'target' must be a string\n", prefix, i)) return nullptr; + if (!READER_CHECK(!has_option || input["option"].IsString(), "%sinput[%u]: Value 'option' must be a string\n", prefix, i)) return nullptr; + if (!READER_CHECK(has_target || !input.HasMember("bilinear") || input["bilinear"].IsBool(), "%sinput[%u]: Value 'bilinear' must be a boolean\n", prefix, i)) return nullptr; + if (!READER_CHECK(has_target || !input.HasMember("clamp") || input["clamp"].IsBool(), "%sinput[%u]: Value 'clamp' must be a boolean\n", prefix, i)) return nullptr; + if (!READER_CHECK(has_texture || has_option || !input.HasMember("selection") || input["selection"].IsString(), "%sinput[%u]: Value 'selection' must be a string\n", prefix, i)) return nullptr; bool bilinear = get_bool(input, "bilinear", true); bool clamp = get_bool(input, "clamp", false); std::string selection = get_string(input, "selection", ""); @@ -223,17 +229,17 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s return new bgfx_chain_entry(name, effect, clear, suppressors, inputs, uniforms, chains.targets(), output, applytint); } -bool chain_entry_reader::validate_parameters(const Value& value, std::string prefix) +bool chain_entry_reader::validate_parameters(const Value& value, const 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("applytint") || value["applytint"].IsBool(), (prefix + "Value 'applytint' must be a bool\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("effect"), "%sMust have string value 'effect' (what effect does this entry use?)\n", prefix)) return false; + if (!READER_CHECK(value["effect"].IsString(), "%sValue 'effect' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'effect' (what effect does this entry use?)\n", prefix)) return false; + if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("output"), "%sMust have string value 'offset' (what target are we rendering to?)\n", prefix)) return false; + if (!READER_CHECK(value["output"].IsString(), "%sValue 'output' must be a string\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("input") || value["input"].IsArray(), "%sValue 'input' must be an array\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("uniforms") || value["uniforms"].IsArray(), "%sValue 'uniforms' must be an array\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("disablewhen") || value["disablewhen"].IsArray(), "%sValue 'disablewhen' must be an array\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("applytint") || value["applytint"].IsBool(), "%sValue 'applytint' must be a bool\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/chainentryreader.h b/src/osd/modules/render/bgfx/chainentryreader.h index 0f604e9a71f..583e972732c 100644 --- a/src/osd/modules/render/bgfx/chainentryreader.h +++ b/src/osd/modules/render/bgfx/chainentryreader.h @@ -5,15 +5,15 @@ // chainentryreader.h - BGFX chain entry JSON reader // //============================================================ +#ifndef MAME_RENDER_BGFX_CHAINENTRYREADER_H +#define MAME_RENDER_BGFX_CHAINENTRYREADER_H #pragma once -#ifndef __DRAWBGFX_CHAIN_ENTRY_READER__ -#define __DRAWBGFX_CHAIN_ENTRY_READER__ +#include "statereader.h" #include <map> -#include "statereader.h" class bgfx_chain_entry; class bgfx_slider; @@ -23,10 +23,10 @@ class chain_manager; class chain_entry_reader : public state_reader { public: - static bgfx_chain_entry* read_from_value(const Value& value, std::string prefix, chain_manager& chains, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params, uint32_t screen_index); + static bgfx_chain_entry* read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params, uint32_t screen_index); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); }; -#endif // __DRAWBGFX_CHAIN_ENTRY_READER__ +#endif // MAME_RENDER_BGFX_CHAINENTRYREADER_H diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp index c3b80e88d14..a15f2f1e584 100644 --- a/src/osd/modules/render/bgfx/chainmanager.cpp +++ b/src/osd/modules/render/bgfx/chainmanager.cpp @@ -26,45 +26,62 @@ #include "bgfxutil.h" -#include "chainreader.h" #include "chain.h" - -#include "texture.h" -#include "target.h" +#include "chainreader.h" #include "slider.h" +#include "target.h" +#include "texture.h" #include "sliderdirtynotifier.h" +#include "util/path.h" +#include "util/unicode.h" +#include "util/xmlfile.h" + #include "osdcore.h" #include "osdfile.h" -using namespace rapidjson; +#include <algorithm> +#include <locale> + -const uint32_t chain_manager::CHAIN_NONE = 0; +using namespace rapidjson; chain_manager::screen_prim::screen_prim(render_primitive *prim) { m_prim = prim; - m_screen_width = (uint16_t)floorf(prim->get_full_quad_width() + 0.5f); - m_screen_height = (uint16_t)floorf(prim->get_full_quad_height() + 0.5f); - m_quad_width = (uint16_t)floorf(prim->get_quad_width() + 0.5f); - m_quad_height = (uint16_t)floorf(prim->get_quad_height() + 0.5f); - m_tex_width = (float)prim->texture.width; - m_tex_height = (float)prim->texture.height; + m_screen_width = uint16_t(floorf(prim->get_full_quad_width() + 0.5f)); + m_screen_height = uint16_t(floorf(prim->get_full_quad_height() + 0.5f)); + m_quad_width = uint16_t(floorf(prim->get_quad_width() + 0.5f)); + m_quad_height = uint16_t(floorf(prim->get_quad_height() + 0.5f)); + m_tex_width = prim->texture.width; + m_tex_height = prim->texture.height; m_rowpixels = prim->texture.rowpixels; m_palette_length = prim->texture.palette_length; m_flags = prim->flags; } -chain_manager::chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, slider_dirty_notifier& slider_notifier) +chain_manager::chain_manager( + running_machine& machine, + const osd_options& options, + texture_manager& textures, + target_manager& targets, + effect_manager& effects, + uint32_t window_index, + slider_dirty_notifier& slider_notifier, + uint16_t user_prescale, + uint16_t max_prescale_size) : m_machine(machine) , m_options(options) , m_textures(textures) , m_targets(targets) , m_effects(effects) , m_window_index(window_index) + , m_user_prescale(user_prescale) + , m_max_prescale_size(max_prescale_size) , m_slider_notifier(slider_notifier) , m_screen_count(0) + , m_default_chain_index(-1) { m_converters.clear(); refresh_available_chains(); @@ -87,13 +104,55 @@ void chain_manager::init_texture_converters() m_adjuster = m_effects.get_or_load_effect(m_options, "misc/bcg_adjust"); } +void chain_manager::get_default_chain_info(std::string &out_chain_name, int32_t &out_chain_index) +{ + if (m_default_chain_index == -1) + { + out_chain_index = CHAIN_NONE; + out_chain_name = ""; + return; + } + + out_chain_index = m_default_chain_index; + out_chain_name = "default"; + return; +} + void chain_manager::refresh_available_chains() { m_available_chains.clear(); - m_available_chains.push_back(chain_desc("none", "")); - - const std::string chains_path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "chains", m_options.bgfx_path())); - find_available_chains(chains_path, ""); + m_available_chains.emplace_back("none", ""); + + find_available_chains(util::path_concat(m_options.bgfx_path(), "chains"), ""); + std::collate<wchar_t> const &coll = std::use_facet<std::collate<wchar_t> >(std::locale()); + std::sort( + m_available_chains.begin(), + m_available_chains.end(), + [&coll] (chain_desc const &x, chain_desc const &y) -> bool + { + if (x.m_name == "none") + return y.m_name != "none"; + else if (y.m_name == "none") + return false; + else if (x.m_name == "default") + return y.m_name != "default"; + else if (y.m_name == "default") + return false; + std::wstring const xstr = wstring_from_utf8(x.m_name); + std::wstring const ystr = wstring_from_utf8(y.m_name); + return coll.compare(xstr.data(), xstr.data() + xstr.size(), ystr.data(), ystr.data() + ystr.size()) < 0; + }); + + if (m_default_chain_index == -1) + { + for (size_t i = 0; i < m_available_chains.size(); i++) + { + if (m_available_chains[i].m_name == "default") + { + m_default_chain_index = int32_t(i); + } + } + } destroy_unloaded_chains(); } @@ -103,7 +162,7 @@ void chain_manager::destroy_unloaded_chains() // O(shaders*available_chains), but we don't care because asset reloading happens rarely for (int i = 0; i < m_chain_names.size(); i++) { - std::string name = m_chain_names[i]; + const std::string &name = m_chain_names[i]; if (name.length() > 0) { for (chain_desc desc : m_available_chains) @@ -112,8 +171,7 @@ void chain_manager::destroy_unloaded_chains() { delete m_screen_chains[i]; m_screen_chains[i] = nullptr; - m_chain_names[i] = ""; - m_current_chain[i] = CHAIN_NONE; + get_default_chain_info(m_chain_names[i], m_current_chain[i]); break; } } @@ -121,56 +179,53 @@ void chain_manager::destroy_unloaded_chains() } } -void chain_manager::find_available_chains(std::string root, std::string path) +void chain_manager::find_available_chains(std::string_view root, std::string_view path) { - osd::directory::ptr directory = osd::directory::open(root + path); - if (directory != nullptr) + osd::directory::ptr directory = osd::directory::open(path.empty() ? std::string(root) : util::path_concat(root, path)); + if (directory) { - for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) + for (const osd::directory::entry *entry = directory->read(); entry; entry = directory->read()) { if (entry->type == osd::directory::entry::entry_type::FILE) { - std::string name(entry->name); - std::string extension(".json"); + const std::string_view name(entry->name); + const std::string_view extension(".json"); // Does the name has at least one character in addition to ".json"? if (name.length() > extension.length()) { size_t start = name.length() - extension.length(); - std::string test_segment = name.substr(start, extension.length()); + const std::string_view test_segment = name.substr(start, extension.length()); // Does it end in .json? if (test_segment == extension) { - m_available_chains.push_back(chain_desc(name.substr(0, start), path)); + m_available_chains.emplace_back(std::string(name.substr(0, start)), std::string(path)); } } } else if (entry->type == osd::directory::entry::entry_type::DIR) { - std::string name = entry->name; - if (!(name == "." || name == "..")) + const std::string_view name = entry->name; + if ((name != ".") && (name != "..")) { - std::string appended_path = path + "/" + name; - if (path.length() == 0) - { - appended_path = name; - } - find_available_chains(root, path + "/" + name); + if (path.empty()) + find_available_chains(root, name); + else + find_available_chains(root, util::path_concat(path, name)); } } } } } -bgfx_chain* chain_manager::load_chain(std::string name, uint32_t screen_index) +std::unique_ptr<bgfx_chain> chain_manager::load_chain(std::string name, uint32_t screen_index) { if (name.length() < 5 || (name.compare(name.length() - 5, 5, ".json") != 0)) { - name = name + ".json"; + name += ".json"; } - std::string path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "chains" PATH_SEPARATOR, m_options.bgfx_path())); - path += name; + const std::string path = util::path_concat(m_options.bgfx_path(), "chains", name); bx::FileReader reader; if (!bx::open(&reader, path.c_str())) @@ -179,29 +234,35 @@ bgfx_chain* chain_manager::load_chain(std::string name, uint32_t screen_index) return nullptr; } - int32_t size(bx::getSize(&reader)); + const int32_t size(bx::getSize(&reader)); - char* data = new char[size + 1]; - bx::read(&reader, reinterpret_cast<void*>(data), size); + bx::ErrorAssert err; + std::unique_ptr<char []> data(new (std::nothrow) char [size + 1]); + if (!data) + { + osd_printf_error("Out of memory reading chain file %s\n", path); + bx::close(&reader); + return nullptr; + } + + bx::read(&reader, reinterpret_cast<void*>(data.get()), size, &err); bx::close(&reader); data[size] = 0; Document document; - document.Parse<kParseCommentsFlag>(data); - - delete [] data; + document.Parse<kParseCommentsFlag>(data.get()); + data.reset(); if (document.HasParseError()) { std::string error(GetParseError_En(document.GetParseError())); - osd_printf_warning("Unable to parse chain %s. Errors returned:\n", path); - osd_printf_warning("%s\n", error); + osd_printf_warning("Unable to parse chain %s. Errors returned:\n%s\n", path, error); return nullptr; } - bgfx_chain* chain = chain_reader::read_from_value(document, name + ": ", *this, screen_index); + std::unique_ptr<bgfx_chain> chain = chain_reader::read_from_value(document, name + ": ", *this, screen_index, m_user_prescale, m_max_prescale_size); - if (chain == nullptr) + if (!chain) { osd_printf_warning("Unable to load chain %s, falling back to no post processing\n", path); return nullptr; @@ -210,17 +271,17 @@ bgfx_chain* chain_manager::load_chain(std::string name, uint32_t screen_index) return chain; } -void chain_manager::parse_chain_selections(std::string chain_str) +void chain_manager::parse_chain_selections(std::string_view chain_str) { - std::vector<std::string> chain_names = split_option_string(chain_str); + std::vector<std::string_view> chain_names = split_option_string(chain_str); if (chain_names.empty()) chain_names.push_back("default"); - while (m_current_chain.size() != chain_names.size()) + while (m_current_chain.size() < chain_names.size()) { - m_screen_chains.push_back(nullptr); - m_chain_names.push_back(""); + m_screen_chains.emplace_back(nullptr); + m_chain_names.emplace_back(); m_current_chain.push_back(CHAIN_NONE); } @@ -230,9 +291,7 @@ void chain_manager::parse_chain_selections(std::string chain_str) for (chain_index = 0; chain_index < m_available_chains.size(); chain_index++) { if (m_available_chains[chain_index].m_name == chain_names[index]) - { break; - } } if (chain_index < m_available_chains.size()) @@ -248,24 +307,35 @@ void chain_manager::parse_chain_selections(std::string chain_str) } } -std::vector<std::string> chain_manager::split_option_string(std::string chain_str) const +std::vector<std::string_view> chain_manager::split_option_string(std::string_view chain_str) const { - std::vector<std::string> chain_names; + std::vector<std::string_view> chain_names; - uint32_t length = chain_str.length(); + const uint32_t length = chain_str.length(); uint32_t win = 0; uint32_t last_start = 0; - for (uint32_t i = 0; i < length + 1; i++) + for (uint32_t i = 0; i <= length; i++) { - if (i == length || chain_str[i] == ',' || chain_str[i] == ':') + if (i == length || (chain_str[i] == ',') || (chain_str[i] == ':')) { - if (win == m_window_index) + if ((win == 0) || (win == m_window_index)) { - chain_names.push_back(chain_str.substr(last_start, i - last_start)); + // treat an empty string as equivalent to "default" + if (i > last_start) + chain_names.push_back(chain_str.substr(last_start, i - last_start)); + else + chain_names.push_back("default"); } + last_start = i + 1; - if (chain_str[i] == ':') + if ((i < length) && (chain_str[i] == ':')) { + // no point walking the rest of the string if this was our window + if (win == m_window_index) + break; + + // don't use first for all if more than one window is specified + chain_names.clear(); win++; } } @@ -282,7 +352,7 @@ void chain_manager::load_chains() { chain_desc& desc = m_available_chains[m_current_chain[chain]]; m_chain_names[chain] = desc.m_name; - m_screen_chains[chain] = load_chain(desc.m_path + "/" + desc.m_name, uint32_t(chain)); + m_screen_chains[chain] = load_chain(util::path_concat(desc.m_path, desc.m_name), uint32_t(chain)).release(); } } } @@ -319,7 +389,7 @@ bgfx_chain* chain_manager::screen_chain(uint32_t screen) void chain_manager::process_screen_quad(uint32_t view, uint32_t screen, screen_prim &prim, osd_window& window) { - const bool any_targets_rebuilt = m_targets.update_target_sizes(screen, prim.m_tex_width, prim.m_tex_height, TARGET_STYLE_GUEST); + const bool any_targets_rebuilt = m_targets.update_target_sizes(screen, prim.m_tex_width, prim.m_tex_height, TARGET_STYLE_GUEST, m_user_prescale, m_max_prescale_size); if (any_targets_rebuilt) { for (bgfx_chain* chain : m_screen_chains) @@ -332,7 +402,7 @@ void chain_manager::process_screen_quad(uint32_t view, uint32_t screen, screen_p } bgfx_chain* chain = screen_chain(screen); - chain->process(prim, view, screen, m_textures, window, bgfx_util::get_blend_state(PRIMFLAG_GET_BLENDMODE(prim.m_flags))); + chain->process(prim, view, screen, m_textures, window); view += chain->applicable_passes(); } @@ -359,7 +429,7 @@ uint32_t chain_manager::count_screens(render_primitive* prim) if (screen_count > 0) { update_screen_count(screen_count); - m_targets.update_screen_count(screen_count); + m_targets.update_screen_count(screen_count, m_user_prescale, m_max_prescale_size); } if (screen_count < m_screen_prims.size()) @@ -381,8 +451,12 @@ void chain_manager::update_screen_count(uint32_t screen_count) while (m_screen_chains.size() < m_screen_count) { m_screen_chains.push_back(nullptr); - m_chain_names.push_back(""); - m_current_chain.push_back(CHAIN_NONE); + + int32_t chain_index = CHAIN_NONE; + std::string chain_name; + get_default_chain_info(chain_name, chain_index); + m_chain_names.emplace_back(std::move(chain_name)); + m_current_chain.push_back(chain_index); } // Ensure we have a screen chain selection slider per screen @@ -395,11 +469,20 @@ void chain_manager::update_screen_count(uint32_t screen_count) } } +void chain_manager::set_current_chain(uint32_t screen, int32_t chain_index) +{ + if (chain_index < m_available_chains.size() && screen < m_current_chain.size() && screen < m_chain_names.size()) + { + m_current_chain[screen] = chain_index; + m_chain_names[screen] = m_available_chains[chain_index].m_name; + } +} + int32_t chain_manager::slider_changed(int id, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) { - m_current_chain[id] = newval; + set_current_chain(id, newval); std::vector<std::vector<float>> settings = slider_settings(); reload_chains(); @@ -428,11 +511,11 @@ void chain_manager::create_selection_slider(uint32_t screen_index) int32_t maxval = m_available_chains.size() - 1; int32_t incval = 1; - std::string description = "Window " + std::to_string(m_window_index) + ", Screen " + std::to_string(screen_index) + " Effect:"; - using namespace std::placeholders; - auto state = std::make_unique<slider_state>(std::move(description), minval, defval, maxval, incval, - std::bind(&chain_manager::slider_changed, this, screen_index, _1, _2)); + auto state = std::make_unique<slider_state>( + util::string_format("Window %1$u, Screen %2$u Effect", m_window_index, screen_index), + minval, defval, maxval, incval, + std::bind(&chain_manager::slider_changed, this, screen_index, _1, _2)); ui::menu_item item(ui::menu_item_type::SLIDER, state.get()); item.set_text(state->description); @@ -457,23 +540,17 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive * const uint32_t src_format = (prim.m_flags & PRIMFLAG_TEXFORMAT_MASK) >> PRIMFLAG_TEXFORMAT_SHIFT; const bool needs_conversion = m_converters[src_format] != nullptr; const bool needs_adjust = prim.m_prim->texture.palette != nullptr && src_format != TEXFORMAT_PALETTE16; - std::string screen_index = std::to_string(screen); - std::string source_name = "source" + screen_index; - std::string screen_name = "screen" + screen_index; - std::string palette_name = "palette" + screen_index; - std::string full_name = (needs_conversion || needs_adjust) ? source_name : screen_name; + const std::string screen_index = std::to_string(screen); + const std::string source_name = "source" + screen_index; + const std::string screen_name = "screen" + screen_index; + const std::string palette_name = "palette" + screen_index; + const std::string &full_name = (needs_conversion || needs_adjust) ? source_name : screen_name; if (texture && (texture->width() != tex_width || texture->height() != tex_height)) { - m_textures.add_provider(full_name, nullptr); - delete texture; + m_textures.remove_provider(full_name); + m_textures.remove_provider(palette_name); texture = nullptr; - - if (palette) - { - m_textures.add_provider(palette_name, nullptr); - delete palette; - palette = nullptr; - } + palette = nullptr; } bgfx::TextureFormat::Enum dst_format = bgfx::TextureFormat::BGRA8; @@ -481,36 +558,38 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive * int width_div_factor = 1; int width_mul_factor = 1; const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, prim.m_flags & PRIMFLAG_TEXFORMAT_MASK, - prim.m_rowpixels, tex_height, prim.m_prim->texture.palette, prim.m_prim->texture.base, pitch, width_div_factor, width_mul_factor); + prim.m_rowpixels, prim.m_prim->texture.width_margin, tex_height, prim.m_prim->texture.palette, prim.m_prim->texture.base, pitch, width_div_factor, width_mul_factor); - if (texture == nullptr) + if (!texture) { uint32_t flags = BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT; if (!PRIMFLAG_GET_TEXWRAP(prim.m_flags)) flags |= BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; - bgfx_texture *texture = new bgfx_texture(full_name, dst_format, tex_width, tex_height, mem, flags, pitch, prim.m_rowpixels, width_div_factor, width_mul_factor); - m_textures.add_provider(full_name, texture); + auto newtex = std::make_unique<bgfx_texture>(full_name, dst_format, tex_width, prim.m_prim->texture.width_margin, tex_height, mem, flags, pitch, prim.m_rowpixels, width_div_factor, width_mul_factor); + texture = newtex.get(); + m_textures.add_provider(full_name, std::move(newtex)); if (prim.m_prim->texture.palette) { - uint16_t palette_width = (uint16_t)std::min(prim.m_palette_length, 256U); - uint16_t palette_height = (uint16_t)std::max((prim.m_palette_length + 255) / 256, 1U); + uint16_t palette_width = uint16_t(std::min(prim.m_palette_length, 256U)); + uint16_t palette_height = uint16_t(std::max((prim.m_palette_length + 255) / 256, 1U)); m_palette_temp.resize(palette_width * palette_height * 4); memcpy(&m_palette_temp[0], prim.m_prim->texture.palette, prim.m_palette_length * 4); const bgfx::Memory *palmem = bgfx::copy(&m_palette_temp[0], palette_width * palette_height * 4); - palette = new bgfx_texture(palette_name, bgfx::TextureFormat::BGRA8, palette_width, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width * 4); - m_textures.add_provider(palette_name, palette); + auto newpal = std::make_unique<bgfx_texture>(palette_name, bgfx::TextureFormat::BGRA8, palette_width, 0, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width * 4); + palette = newpal.get(); + m_textures.add_provider(palette_name, std::move(newpal)); } while (screen >= m_screen_textures.size()) { - m_screen_textures.push_back(nullptr); + m_screen_textures.emplace_back(nullptr); } m_screen_textures[screen] = texture; while (screen >= m_screen_palettes.size()) { - m_screen_palettes.push_back(nullptr); + m_screen_palettes.emplace_back(nullptr); } if (palette) { @@ -519,12 +598,12 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive * } else { - texture->update(mem, pitch); + texture->update(mem, pitch, prim.m_prim->texture.width_margin); if (prim.m_prim->texture.palette) { - uint16_t palette_width = (uint16_t)std::min(prim.m_palette_length, 256U); - uint16_t palette_height = (uint16_t)std::max((prim.m_palette_length + 255) / 256, 1U); + uint16_t palette_width = uint16_t(std::min(prim.m_palette_length, 256U)); + uint16_t palette_height = uint16_t(std::max((prim.m_palette_length + 255) / 256, 1U)); const uint32_t palette_size = palette_width * palette_height * 4; m_palette_temp.resize(palette_size); memcpy(&m_palette_temp[0], prim.m_prim->texture.palette, prim.m_palette_length * 4); @@ -536,26 +615,29 @@ uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive * } else { - palette = new bgfx_texture(palette_name, bgfx::TextureFormat::BGRA8, palette_width, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width * 4); - m_textures.add_provider(palette_name, palette); + auto newpal = std::make_unique<bgfx_texture>(palette_name, bgfx::TextureFormat::BGRA8, palette_width, 0, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width * 4); + palette = newpal.get(); + m_textures.add_provider(palette_name, std::move(newpal)); while (screen >= m_screen_palettes.size()) { - m_screen_palettes.push_back(nullptr); + m_screen_palettes.emplace_back(nullptr); } m_screen_palettes[screen] = palette; } } } + const bool has_tint = (prim.m_prim->color.a != 1.0f) || (prim.m_prim->color.r != 1.0f) || (prim.m_prim->color.g != 1.0f) || (prim.m_prim->color.b != 1.0f); bgfx_chain* chain = screen_chain(screen); if (chain && needs_adjust && !chain->has_adjuster()) { - chain->insert_effect(chain->has_converter() ? 1 : 0, m_adjuster, "XXadjust", needs_conversion ? "screen" : "source", *this); + const bool apply_tint = !needs_conversion && has_tint; + chain->insert_effect(chain->has_converter() ? 1 : 0, m_adjuster, apply_tint, "XXadjust", needs_conversion ? "screen" : "source", *this); chain->set_has_adjuster(true); } if (chain && needs_conversion && !chain->has_converter()) { - chain->insert_effect(0, m_converters[src_format], "XXconvert", "source", *this); + chain->insert_effect(0, m_converters[src_format], has_tint, "XXconvert", "source", *this); chain->set_has_converter(true); } } @@ -583,7 +665,7 @@ uint32_t chain_manager::process_screen_chains(uint32_t view, osd_window& window) std::swap(screen_width, screen_height); } - const bool any_targets_rebuilt = m_targets.update_target_sizes(screen_index, screen_width, screen_height, TARGET_STYLE_NATIVE); + const bool any_targets_rebuilt = m_targets.update_target_sizes(screen_index, screen_width, screen_height, TARGET_STYLE_NATIVE, m_user_prescale, m_max_prescale_size); if (any_targets_rebuilt) { for (bgfx_chain* chain : m_screen_chains) @@ -608,12 +690,12 @@ uint32_t chain_manager::process_screen_chains(uint32_t view, osd_window& window) bool chain_manager::has_applicable_chain(uint32_t screen) { - return screen < m_screen_count && m_current_chain[screen] != CHAIN_NONE && m_screen_chains[screen] != nullptr; + return (screen < m_screen_count) && (m_current_chain[screen] != CHAIN_NONE) && m_screen_chains[screen]; } bool chain_manager::needs_sliders() { - return m_screen_count > 0 && m_available_chains.size() > 1; + return (m_screen_count > 0) && (m_available_chains.size() > 1); } void chain_manager::restore_slider_settings(int32_t id, std::vector<std::vector<float>>& settings) @@ -636,7 +718,7 @@ void chain_manager::restore_slider_settings(int32_t id, std::vector<std::vector< continue; } - std::vector<bgfx_slider*> chain_sliders = chain->sliders(); + const std::vector<bgfx_slider*> &chain_sliders = chain->sliders(); for (size_t slider = 0; slider < chain_sliders.size(); slider++) { chain_sliders[slider]->import(settings[index][slider]); @@ -644,6 +726,151 @@ void chain_manager::restore_slider_settings(int32_t id, std::vector<std::vector< } } +void chain_manager::load_config(util::xml::data_node const &windownode) +{ + // treat source INI files or more specific as higher priority than CFG + // FIXME: leaky abstraction - this depends on a front-end implementation detail + bool const persist = windownode.get_attribute_int("persist", 1) != 0; + bool const default_chains = (OPTION_PRIORITY_NORMAL + 5) > m_options.get_entry(OSDOPTION_BGFX_SCREEN_CHAINS)->priority(); + bool const explicit_chains = !persist && !default_chains && *m_options.bgfx_screen_chains(); + + // if chains weren't explicitly specified, restore the chains from the config file + if (explicit_chains) + { + osd_printf_verbose( + "BGFX: Ignoring chain selection from window 0 configuration due to explicitly specified chains\n", + m_window_index); + } + else + { + bool changed = false; + util::xml::data_node const *screennode = windownode.get_child("screen"); + while (screennode) + { + auto const index = screennode->get_attribute_int("index", -1); + if ((0 <= index) && (m_screen_count > index)) + { + char const *const chainname = screennode->get_attribute_string("chain", nullptr); + if (chainname) + { + auto const found = std::find_if( + m_available_chains.begin(), + m_available_chains.end(), + [&chainname] (auto const &avail) { return avail.m_name == chainname; }); + if (m_available_chains.end() != found) + { + auto const chainnum = found - m_available_chains.begin(); + if (chainnum != m_current_chain[index]) + { + m_current_chain[index] = chainnum; + changed = true; + } + } + } + } + + screennode = screennode->get_next_sibling("screen"); + } + + if (changed) + reload_chains(); + } + + // now apply slider settings for screens with chains matching config + util::xml::data_node const *screennode = windownode.get_child("screen"); + while (screennode) + { + auto const index = screennode->get_attribute_int("index", -1); + if ((0 <= index) && (m_screen_count > index) && (m_screen_chains.size() > index)) + { + bgfx_chain *const chain = m_screen_chains[index]; + char const *const chainname = screennode->get_attribute_string("chain", nullptr); + if (chain && chainname && (m_available_chains[m_current_chain[index]].m_name == chainname)) + { + auto const &sliders = chain->sliders(); + + util::xml::data_node const *slidernode = screennode->get_child("slider"); + while (slidernode) + { + char const *const slidername = slidernode->get_attribute_string("name", nullptr); + if (slidername) + { + auto const found = std::find_if( + sliders.begin(), + sliders.end(), + [&slidername] (auto const &slider) { return slider->name() == slidername; }); + if (sliders.end() != found) + { + bgfx_slider &slider = **found; + switch (slider.type()) + { + case bgfx_slider::SLIDER_INT_ENUM: + case bgfx_slider::SLIDER_INT: + { + slider_state const &core = *slider.core_slider(); + int32_t const val = slidernode->get_attribute_int("value", core.defval); + slider.update(nullptr, std::clamp(val, core.minval, core.maxval)); + } + break; + default: + { + float const val = slidernode->get_attribute_float("value", slider.default_value()); + slider.import(std::clamp(val, slider.min_value(), slider.max_value())); + } + } + } + } + + slidernode = slidernode->get_next_sibling("slider"); + } + } + } + screennode = screennode->get_next_sibling("screen"); + } +} + +void chain_manager::save_config(util::xml::data_node &parentnode) +{ + if (!needs_sliders()) + return; + + util::xml::data_node *const windownode = parentnode.add_child("window", nullptr); + windownode->set_attribute_int("index", m_window_index); + + for (size_t index = 0; index < m_screen_chains.size() && index < m_screen_count; index++) + { + bgfx_chain *const chain = m_screen_chains[index]; + if (!chain) + continue; + + util::xml::data_node *const screennode = windownode->add_child("screen", nullptr); + screennode->set_attribute_int("index", index); + screennode->set_attribute("chain", m_available_chains[m_current_chain[index]].m_name.c_str()); + + for (bgfx_slider *slider : chain->sliders()) + { + auto const val = slider->update(nullptr, SLIDER_NOCHANGE); + if (val == slider->core_slider()->defval) + continue; + + util::xml::data_node *const slidernode = screennode->add_child("slider", nullptr); + slidernode->set_attribute("name", slider->name().c_str()); + switch (slider->type()) + { + case bgfx_slider::SLIDER_INT_ENUM: + case bgfx_slider::SLIDER_INT: + slidernode->set_attribute_int("value", val); + break; + default: + slidernode->set_attribute_float("value", slider->value()); + } + } + } + + if (!windownode->get_first_child()) + windownode->delete_node(); +} + std::vector<std::vector<float>> chain_manager::slider_settings() { std::vector<std::vector<float>> curr; @@ -663,7 +890,7 @@ std::vector<std::vector<float>> chain_manager::slider_settings() continue; } - std::vector<bgfx_slider*> chain_sliders = chain->sliders(); + const std::vector<bgfx_slider*> &chain_sliders = chain->sliders(); for (bgfx_slider* slider : chain_sliders) { curr[index].push_back(slider->value()); @@ -692,24 +919,24 @@ std::vector<ui::menu_item> chain_manager::get_slider_list() continue; } - std::vector<bgfx_chain_entry*> chain_entries = chain->entries(); + const std::vector<bgfx_chain_entry*> &chain_entries = chain->entries(); for (bgfx_chain_entry* entry : chain_entries) { - std::vector<bgfx_input_pair*> entry_inputs = entry->inputs(); + const std::vector<bgfx_input_pair*> &entry_inputs = entry->inputs(); for (bgfx_input_pair* input : entry_inputs) { std::vector<ui::menu_item> input_sliders = input->get_slider_list(); - for (ui::menu_item slider : input_sliders) + for (ui::menu_item &slider : input_sliders) { sliders.emplace_back(slider); } } } - std::vector<bgfx_slider*> chain_sliders = chain->sliders(); + const std::vector<bgfx_slider*> &chain_sliders = chain->sliders(); for (bgfx_slider* slider : chain_sliders) { - slider_state* core_slider = slider->core_slider(); + slider_state *const core_slider = slider->core_slider(); ui::menu_item item(ui::menu_item_type::SLIDER, core_slider); item.set_text(core_slider->description); diff --git a/src/osd/modules/render/bgfx/chainmanager.h b/src/osd/modules/render/bgfx/chainmanager.h index 59a65dc59cf..0d489d0bd72 100644 --- a/src/osd/modules/render/bgfx/chainmanager.h +++ b/src/osd/modules/render/bgfx/chainmanager.h @@ -9,19 +9,24 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_CHAINMANAGER_H +#define MAME_RENDER_BGFX_CHAINMANAGER_H -#ifndef __DRAWBGFX_CHAIN_MANAGER__ -#define __DRAWBGFX_CHAIN_MANAGER__ +#pragma once -#include "texturemanager.h" -#include "targetmanager.h" #include "effectmanager.h" +#include "targetmanager.h" +#include "texturemanager.h" + +#include "util/utilfwd.h" #include <map> #include <string> +#include <string_view> +#include <utility> #include <vector> + class running_machine; class osd_window; struct slider_state; @@ -33,23 +38,29 @@ namespace ui { class menu_item; } class bgfx_chain; class bgfx_slider; -class chain_desc +class chain_manager { public: - chain_desc(std::string name, std::string path) - : m_name(name) - , m_path(path) + class screen_prim { - } + public: + screen_prim() = default; + screen_prim(render_primitive *prim); - const std::string m_name; - const std::string m_path; -}; + render_primitive *m_prim = nullptr; + uint16_t m_screen_width = 0; + uint16_t m_screen_height = 0; + uint16_t m_quad_width = 0; + uint16_t m_quad_height = 0; + float m_tex_width = 0.0f; + float m_tex_height = 0.0f; + int m_rowpixels = 0; + uint32_t m_palette_length = 0; + uint32_t m_flags = 0; + }; -class chain_manager -{ -public: - chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, slider_dirty_notifier& slider_notifier); + chain_manager(running_machine& machine, const osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, + slider_dirty_notifier& slider_notifier, uint16_t user_prescale, uint16_t max_prescale_size); ~chain_manager(); uint32_t update_screen_textures(uint32_t view, render_primitive *starting_prim, osd_window& window); @@ -57,7 +68,7 @@ public: // Getters running_machine& machine() const { return m_machine; } - osd_options& options() const { return m_options; } + const osd_options& options() const { return m_options; } texture_manager& textures() const { return m_textures; } target_manager& targets() const { return m_targets; } effect_manager& effects() const { return m_effects; } @@ -65,7 +76,7 @@ public: uint32_t window_index() const { return m_window_index; } uint32_t screen_count() const { return m_screen_count; } bgfx_chain* screen_chain(uint32_t screen); - bgfx_chain* load_chain(std::string name, uint32_t screen_index); + std::unique_ptr<bgfx_chain> load_chain(std::string name, uint32_t screen_index); bool has_applicable_chain(uint32_t screen); std::vector<ui::menu_item> get_slider_list(); std::vector<std::vector<float>> slider_settings(); @@ -73,43 +84,44 @@ public: // Setters void restore_slider_settings(int32_t id, std::vector<std::vector<float>>& settings); - class screen_prim + void load_config(util::xml::data_node const &screennode); + void save_config(util::xml::data_node &parentnode); + +private: + class chain_desc { public: - screen_prim() : m_prim(nullptr), m_screen_width(0), m_screen_height(0), m_quad_width(0), m_quad_height(0) - , m_tex_width(0), m_tex_height(0), m_rowpixels(0), m_palette_length(0), m_flags(0) + chain_desc(const chain_desc &) = default; + chain_desc(chain_desc &&) = default; + chain_desc &operator=(const chain_desc &) = default; + chain_desc &operator=(chain_desc &&) = default; + + chain_desc(std::string &&name, std::string &&path) + : m_name(std::move(name)) + , m_path(std::move(path)) { } - screen_prim(render_primitive *prim); - - render_primitive *m_prim; - uint16_t m_screen_width; - uint16_t m_screen_height; - uint16_t m_quad_width; - uint16_t m_quad_height; - float m_tex_width; - float m_tex_height; - int m_rowpixels; - uint32_t m_palette_length; - uint32_t m_flags; + std::string m_name; + std::string m_path; }; -private: void load_chains(); void destroy_chains(); void reload_chains(); void init_texture_converters(); + void get_default_chain_info(std::string &out_chain_name, int32_t &out_chain_index); void refresh_available_chains(); void destroy_unloaded_chains(); - void find_available_chains(std::string root, std::string path); - void parse_chain_selections(std::string chain_str); - std::vector<std::string> split_option_string(std::string chain_str) const; + void find_available_chains(std::string_view root, std::string_view path); + void parse_chain_selections(std::string_view chain_str); + std::vector<std::string_view> split_option_string(std::string_view chain_str) const; void update_screen_count(uint32_t screen_count); + void set_current_chain(uint32_t screen, int32_t chain_index); int32_t slider_changed(int id, std::string *str, int32_t newval); void create_selection_slider(uint32_t screen_index); bool needs_sliders(); @@ -118,13 +130,16 @@ private: void process_screen_quad(uint32_t view, uint32_t screen, screen_prim &prim, osd_window& window); running_machine& m_machine; - osd_options& m_options; + const osd_options& m_options; texture_manager& m_textures; target_manager& m_targets; effect_manager& m_effects; uint32_t m_window_index; + uint16_t m_user_prescale; + uint16_t m_max_prescale_size; slider_dirty_notifier& m_slider_notifier; uint32_t m_screen_count; + int32_t m_default_chain_index; std::vector<chain_desc> m_available_chains; std::vector<bgfx_chain*> m_screen_chains; std::vector<std::string> m_chain_names; @@ -138,7 +153,7 @@ private: std::vector<screen_prim> m_screen_prims; std::vector<uint8_t> m_palette_temp; - static const uint32_t CHAIN_NONE; + static inline constexpr uint32_t CHAIN_NONE = 0; }; -#endif // __DRAWBGFX_CHAIN_MANAGER__ +#endif // MAME_RENDER_BGFX_CHAINMANAGER_H diff --git a/src/osd/modules/render/bgfx/chainreader.cpp b/src/osd/modules/render/bgfx/chainreader.cpp index 92e30df0b33..362baa42c82 100644 --- a/src/osd/modules/render/bgfx/chainreader.cpp +++ b/src/osd/modules/render/bgfx/chainreader.cpp @@ -8,21 +8,26 @@ #include "chainreader.h" -#include <string> -#include <vector> -#include <map> - #include "chain.h" +#include "chainentryreader.h" #include "chainmanager.h" -#include "sliderreader.h" +#include "parameter.h" #include "paramreader.h" -#include "chainentryreader.h" -#include "targetreader.h" -#include "targetmanager.h" #include "slider.h" -#include "parameter.h" +#include "sliderreader.h" +#include "targetmanager.h" +#include "targetreader.h" + +#include <vector> +#include <map> -bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index) +std::unique_ptr<bgfx_chain> chain_reader::read_from_value( + const Value& value, + const std::string &prefix, + chain_manager& chains, + uint32_t screen_index, + uint16_t user_prescale, + uint16_t max_prescale_size) { if (!validate_parameters(value, prefix)) { @@ -96,7 +101,7 @@ bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix // TODO: Move into its own reader for (uint32_t i = 0; i < target_array.Size(); i++) { - bgfx_target* target = target_reader::read_from_value(target_array[i], prefix + "targets[" + std::to_string(i) + "]: ", chains, screen_index); + bgfx_target* target = target_reader::read_from_value(target_array[i], prefix + "targets[" + std::to_string(i) + "]: ", chains, screen_index, user_prescale, max_prescale_size); if (target == nullptr) { return nullptr; @@ -121,19 +126,28 @@ bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix } } - return new bgfx_chain(name, author, transform, chains.targets(), sliders, parameters, entries, target_list, screen_index); + return std::make_unique<bgfx_chain>( + std::move(name), + std::move(author), + transform, + chains.targets(), + std::move(sliders), + std::move(parameters), + std::move(entries), + std::move(target_list), + screen_index); } -bool chain_reader::validate_parameters(const Value& value, std::string prefix) +bool chain_reader::validate_parameters(const Value& value, const 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("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; + if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name'\n", prefix)) return false; + if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("author"), "%sMust have string value 'author'\n", prefix)) return false; + if (!READER_CHECK(value["author"].IsString(), "%sValue 'author' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("passes"), "%sMust have array value 'passes'\n", prefix)) return false; + if (!READER_CHECK(value["passes"].IsArray(), "%sValue 'passes' must be an array\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("sliders") || value["sliders"].IsArray(), "%sValue 'sliders' must be an array\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("parameters") || value["parameters"].IsArray(), "%sValue 'parameters' must be an array\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("targets") || value["targets"].IsArray(), "%sValue 'targets' must be an array\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/chainreader.h b/src/osd/modules/render/bgfx/chainreader.h index a2fa3ba28a5..6bbd2058501 100644 --- a/src/osd/modules/render/bgfx/chainreader.h +++ b/src/osd/modules/render/bgfx/chainreader.h @@ -6,23 +6,26 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_CHAINREADER_H +#define MAME_RENDER_BGFX_CHAINREADER_H -#ifndef __DRAWBGFX_CHAIN_READER__ -#define __DRAWBGFX_CHAIN_READER__ +#pragma once #include "statereader.h" +#include <memory> +#include <string> + class bgfx_chain; class chain_manager; class chain_reader : public state_reader { public: - static bgfx_chain* read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index); + static std::unique_ptr<bgfx_chain> read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, uint32_t screen_index, uint16_t user_prescale, uint16_t max_prescale_size); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); }; -#endif // __DRAWBGFX_CHAIN_READER__ +#endif // MAME_RENDER_BGFX_CHAINREADER_H diff --git a/src/osd/modules/render/bgfx/clearreader.cpp b/src/osd/modules/render/bgfx/clearreader.cpp index 948d96a7393..58c4d5f01aa 100644 --- a/src/osd/modules/render/bgfx/clearreader.cpp +++ b/src/osd/modules/render/bgfx/clearreader.cpp @@ -6,13 +6,15 @@ // //============================================================ -#include <bgfx/bgfx.h> - #include "clearreader.h" #include "clear.h" -clear_state* clear_reader::read_from_value(const Value& value, std::string prefix) +#include <bgfx/bgfx.h> + +#include <algorithm> + +clear_state* clear_reader::read_from_value(const Value& value, const std::string &prefix) { if (!validate_parameters(value, prefix)) { @@ -29,10 +31,8 @@ clear_state* clear_reader::read_from_value(const Value& value, std::string prefi const Value& colors = value["clearcolor"]; for (int i = 0; i < colors.Size(); i++) { - if (!READER_CHECK(colors[i].IsNumber(), (prefix + "clearcolor[" + std::to_string(i) + "] must be a numeric value\n").c_str())) return nullptr; - auto val = int32_t(float(colors[i].GetDouble()) * 255.0f); - if (val > 255) val = 255; - if (val < 0) val = 0; + if (!READER_CHECK(colors[i].IsNumber(), "%sclearcolor[%d] must be a numeric value\n", prefix, i)) return nullptr; + auto val = std::clamp<int32_t>(float(colors[i].GetDouble()) * 255.0f, 0, 255); clear_color |= val << (24 - (i * 3)); } clear_flags |= BGFX_CLEAR_COLOR; @@ -53,10 +53,10 @@ clear_state* clear_reader::read_from_value(const Value& value, std::string prefi return new clear_state(clear_flags, clear_color, clear_depth, clear_stencil); } -bool clear_reader::validate_parameters(const Value& value, std::string prefix) +bool clear_reader::validate_parameters(const Value& value, const std::string &prefix) { - if (!READER_CHECK(!value.HasMember("clearcolor") || (value["clearcolor"].IsArray() && value["clearcolor"].GetArray().Size() == 4), (prefix + "'clearcolor' must be an array of four numeric RGBA values representing the color to which to clear the color buffer\n").c_str())) return false; - if (!READER_CHECK(!value.HasMember("cleardepth") || value["cleardepth"].IsNumber(), (prefix + "'cleardepth' must be a numeric value representing the depth to which to clear the depth buffer\n").c_str())) return false; - if (!READER_CHECK(!value.HasMember("clearstencil") || value["clearstencil"].IsNumber(), (prefix + "'clearstencil' must be a numeric value representing the stencil value to which to clear the stencil buffer\n").c_str())) return false; + if (!READER_CHECK(!value.HasMember("clearcolor") || (value["clearcolor"].IsArray() && value["clearcolor"].GetArray().Size() == 4), "%s'clearcolor' must be an array of four numeric RGBA values representing the color to which to clear the color buffer\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("cleardepth") || value["cleardepth"].IsNumber(), "%s'cleardepth' must be a numeric value representing the depth to which to clear the depth buffer\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("clearstencil") || value["clearstencil"].IsNumber(), "%s'clearstencil' must be a numeric value representing the stencil value to which to clear the stencil buffer\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/clearreader.h b/src/osd/modules/render/bgfx/clearreader.h index 80605ea35f3..1c2063e95de 100644 --- a/src/osd/modules/render/bgfx/clearreader.h +++ b/src/osd/modules/render/bgfx/clearreader.h @@ -6,26 +6,26 @@ // //============================================================ +#ifndef MAME_RENDER_BGFX_CLEARREADER_H +#define MAME_RENDER_BGFX_CLEARREADER_H + #pragma once -#ifndef __DRAWBGFX_CLEAR_READER__ -#define __DRAWBGFX_CLEAR_READER__ +#include "statereader.h" #include <string> -#include "statereader.h" - class clear_state; class clear_reader : public state_reader { public: - static clear_state* read_from_value(const Value& value, std::string prefix); + static clear_state* read_from_value(const Value& value, const std::string &prefix); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); static const int FLAG_COUNT = 3; static const string_to_enum FLAG_NAMES[FLAG_COUNT]; }; -#endif // __DRAWBGFX_CLEAR_READER__ +#endif // MAME_RENDER_BGFX_CLEARREADER_H diff --git a/src/osd/modules/render/bgfx/depthreader.cpp b/src/osd/modules/render/bgfx/depthreader.cpp index 97502d9028e..bcfc568b0da 100644 --- a/src/osd/modules/render/bgfx/depthreader.cpp +++ b/src/osd/modules/render/bgfx/depthreader.cpp @@ -6,10 +6,10 @@ // //============================================================ -#include <bgfx/bgfx.h> - #include "depthreader.h" +#include <bgfx/bgfx.h> + const depth_reader::string_to_enum depth_reader::FUNCTION_NAMES[depth_reader::FUNCTION_COUNT] = { { "never", BGFX_STATE_DEPTH_TEST_NEVER }, { "less", BGFX_STATE_DEPTH_TEST_LESS }, @@ -21,12 +21,12 @@ 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, std::string prefix) +uint64_t depth_reader::read_from_value(const Value& value, const std::string &prefix) { uint64_t write_enable = 0; if (value.HasMember("writeenable")) { - if (!READER_CHECK(value["writeenable"].IsBool(), (prefix + "Value 'writeenable' must be a boolean\n").c_str())) return 0; + if (!READER_CHECK(value["writeenable"].IsBool(), "%sValue 'writeenable' must be a boolean\n", prefix)) return 0; write_enable = value["writeenable"].GetBool() ? BGFX_STATE_WRITE_Z : 0; } diff --git a/src/osd/modules/render/bgfx/depthreader.h b/src/osd/modules/render/bgfx/depthreader.h index 9e2c99a0b29..0815732850f 100644 --- a/src/osd/modules/render/bgfx/depthreader.h +++ b/src/osd/modules/render/bgfx/depthreader.h @@ -6,10 +6,10 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_DEPTHREADER_H +#define MAME_RENDER_BGFX_DEPTHREADER_H -#ifndef __DRAWBGFX_DEPTH_READER__ -#define __DRAWBGFX_DEPTH_READER__ +#pragma once #include <string> @@ -17,11 +17,11 @@ class depth_reader : public state_reader { public: - static uint64_t read_from_value(const Value& value, std::string prefix); + static uint64_t read_from_value(const Value& value, const std::string &prefix); private: static const int FUNCTION_COUNT = 8; static const string_to_enum FUNCTION_NAMES[FUNCTION_COUNT]; }; -#endif // __DRAWBGFX_DEPTH_READER__ +#endif // MAME_RENDER_BGFX_DEPTHREADER_H diff --git a/src/osd/modules/render/bgfx/effect.cpp b/src/osd/modules/render/bgfx/effect.cpp index c5ea8555dce..18b43cca9bf 100644 --- a/src/osd/modules/render/bgfx/effect.cpp +++ b/src/osd/modules/render/bgfx/effect.cpp @@ -13,46 +13,50 @@ #include "modules/osdmodule.h" #include "osdcore.h" -bgfx_effect::bgfx_effect(uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<bgfx_uniform*> uniforms) - : m_state(state) +#include <utility> + + +bgfx_effect::bgfx_effect(std::string &&name, uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<std::unique_ptr<bgfx_uniform> > &uniforms) + : m_name(std::move(name)) + , m_state(state) { m_program_handle = bgfx::createProgram(vertex_shader, fragment_shader, false); - for (int i = 0; i < uniforms.size(); i++) + for (auto &uniform : uniforms) { - if (m_uniforms[uniforms[i]->name()] != nullptr) + const auto existing = m_uniforms.find(uniform->name()); + if (existing != m_uniforms.end()) { - osd_printf_verbose("Uniform %s appears to be duplicated in one or more effects, please double-check the effect JSON files.\n", uniforms[i]->name()); - delete uniforms[i]; + osd_printf_verbose("Uniform %s appears to be duplicated in one or more effects, please double-check the effect JSON files.\n", uniform->name()); + uniform.reset(); continue; } - uniforms[i]->create(); - m_uniforms[uniforms[i]->name()] = uniforms[i]; + uniform->create(); + m_uniforms.emplace(uniform->name(), std::move(uniform)); } } bgfx_effect::~bgfx_effect() { - for (std::pair<std::string, bgfx_uniform*> uniform : m_uniforms) - { - delete uniform.second; - } m_uniforms.clear(); bgfx::destroy(m_program_handle); } void bgfx_effect::submit(int view, uint64_t blend) { - for (std::pair<std::string, bgfx_uniform*> uniform_pair : m_uniforms) + for (auto &[name, uniform] : m_uniforms) { - (uniform_pair.second)->upload(); + uniform->upload(); } - bgfx::setState(m_state | blend); + + const uint64_t final_state = (blend != ~0ULL) ? ((m_state & ~BGFX_STATE_BLEND_MASK) | blend) : m_state; + + bgfx::setState(final_state); bgfx::submit(view, m_program_handle); } -bgfx_uniform* bgfx_effect::uniform(std::string name) +bgfx_uniform* bgfx_effect::uniform(const std::string &name) { - auto iter = m_uniforms.find(name); - return iter != m_uniforms.end() ? iter->second : nullptr; + const auto iter = m_uniforms.find(name); + return (iter != m_uniforms.end()) ? iter->second.get() : nullptr; } diff --git a/src/osd/modules/render/bgfx/effect.h b/src/osd/modules/render/bgfx/effect.h index ca1be77c73d..07646e6302e 100644 --- a/src/osd/modules/render/bgfx/effect.h +++ b/src/osd/modules/render/bgfx/effect.h @@ -6,33 +6,36 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_EFFECT_H +#define MAME_RENDER_BGFX_EFFECT_H -#ifndef __DRAWBGFX_EFFECT__ -#define __DRAWBGFX_EFFECT__ +#pragma once #include <bgfx/bgfx.h> -#include <vector> #include <map> +#include <memory> #include <string> +#include <vector> + class bgfx_uniform; class bgfx_effect { public: - bgfx_effect(uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<bgfx_uniform*> uniforms); + bgfx_effect(std::string &&name, uint64_t state, bgfx::ShaderHandle vertex_shader, bgfx::ShaderHandle fragment_shader, std::vector<std::unique_ptr<bgfx_uniform> > &uniforms); ~bgfx_effect(); - void submit(int view, uint64_t blend = 0L); - bgfx_uniform *uniform(std::string name); - bool is_valid() { return m_program_handle.idx != bgfx::kInvalidHandle; } + void submit(int view, uint64_t blend = ~0ULL); + bgfx_uniform *uniform(const std::string &name); + bool is_valid() const { return m_program_handle.idx != bgfx::kInvalidHandle; } private: + std::string m_name; uint64_t m_state; bgfx::ProgramHandle m_program_handle; - std::map<std::string, bgfx_uniform*> m_uniforms; + std::map<std::string, std::unique_ptr<bgfx_uniform> > m_uniforms; }; -#endif // __DRAWBGFX_EFFECT__ +#endif // MAME_RENDER_BGFX_EFFECT_H diff --git a/src/osd/modules/render/bgfx/effectmanager.cpp b/src/osd/modules/render/bgfx/effectmanager.cpp index f57f56f708d..e5e5d1698f6 100644 --- a/src/osd/modules/render/bgfx/effectmanager.cpp +++ b/src/osd/modules/render/bgfx/effectmanager.cpp @@ -11,8 +11,11 @@ #include "effectmanager.h" -#include "effectreader.h" #include "effect.h" +#include "effectreader.h" +#include "shadermanager.h" + +#include "path.h" #include "osdfile.h" #include "modules/lib/osdobj_common.h" @@ -25,66 +28,75 @@ #include <bgfx/bgfx.h> -static bool prepare_effect_document(std::string &name, osd_options &options, rapidjson::Document &document) +#include <utility> + + +static bool prepare_effect_document(const std::string &name, const osd_options &options, rapidjson::Document &document) { std::string full_name = name; if (full_name.length() < 5 || (full_name.compare(full_name.length() - 5, 5, ".json") != 0)) { - full_name = full_name + ".json"; + full_name += ".json"; } - std::string path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "effects" PATH_SEPARATOR, options.bgfx_path())); - path += full_name; + const std::string path = util::path_concat(options.bgfx_path(), "effects", full_name); bx::FileReader reader; if (!bx::open(&reader, path.c_str())) { - osd_printf_error("Unable to open effect file %s\n", path.c_str()); + osd_printf_error("Unable to open effect file %s\n", path); return false; } - int32_t size (bx::getSize(&reader)); - char* data = new char[size + 1]; - bx::read(&reader, reinterpret_cast<void*>(data), size); + const int32_t size = bx::getSize(&reader); + std::unique_ptr<char []> data(new (std::nothrow) char [size + 1]); + if (!data) + { + osd_printf_error("Out of memory reading effect file %s\n", path); + bx::close(&reader); + return false; + } + + bx::ErrorAssert err; + bx::read(&reader, reinterpret_cast<void*>(data.get()), size, &err); bx::close(&reader); data[size] = 0; - document.Parse<rapidjson::kParseCommentsFlag>(data); - - delete [] data; + document.Parse<rapidjson::kParseCommentsFlag>(data.get()); + data.reset(); if (document.HasParseError()) { std::string error(rapidjson::GetParseError_En(document.GetParseError())); - osd_printf_error("Unable to parse effect %s. Errors returned:\n", path.c_str()); - osd_printf_error("%s\n", error.c_str()); + osd_printf_error("Unable to parse effect %s. Errors returned:\n%s\n", path, error); return false; } return true; } + +// keep constructor and destructor out-of-line so the header works with forward declarations + +effect_manager::effect_manager(shader_manager& shaders) : m_shaders(shaders) +{ +} + effect_manager::~effect_manager() { - for (std::pair<std::string, bgfx_effect*> effect : m_effects) - { - delete effect.second; - } - m_effects.clear(); + // the map will automatically dispose of the effects } -bgfx_effect* effect_manager::get_or_load_effect(osd_options &options, std::string name) +bgfx_effect* effect_manager::get_or_load_effect(const osd_options &options, const std::string &name) { - std::map<std::string, bgfx_effect*>::iterator iter = m_effects.find(name); + const auto iter = m_effects.find(name); if (iter != m_effects.end()) - { - return iter->second; - } + return iter->second.get(); return load_effect(options, name); } -bgfx_effect* effect_manager::load_effect(osd_options &options, std::string name) +bgfx_effect* effect_manager::load_effect(const osd_options &options, const std::string &name) { rapidjson::Document document; if (!prepare_effect_document(name, options, document)) @@ -92,20 +104,18 @@ bgfx_effect* effect_manager::load_effect(osd_options &options, std::string name) return nullptr; } - bgfx_effect* effect = effect_reader::read_from_value(document, "Effect '" + name + "': ", options, m_shaders); + std::unique_ptr<bgfx_effect> effect = effect_reader::read_from_value(name, document, "Effect '" + name + "': ", options, m_shaders); - if (effect == nullptr) + if (!effect) { - osd_printf_error("Unable to load effect %s\n", name.c_str()); + osd_printf_error("Unable to load effect %s\n", name); return nullptr; } - m_effects[name] = effect; - - return effect; + return m_effects.emplace(name, std::move(effect)).first->second.get(); } -bool effect_manager::validate_effect(osd_options &options, std::string name) +bool effect_manager::validate_effect(const osd_options &options, const std::string &name) { rapidjson::Document document; if (!prepare_effect_document(name, options, document)) diff --git a/src/osd/modules/render/bgfx/effectmanager.h b/src/osd/modules/render/bgfx/effectmanager.h index 5d8bf3f5c93..697d468dc5c 100644 --- a/src/osd/modules/render/bgfx/effectmanager.h +++ b/src/osd/modules/render/bgfx/effectmanager.h @@ -9,34 +9,35 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_EFFECTMANAGER_H +#define MAME_RENDER_BGFX_EFFECTMANAGER_H -#ifndef __DRAWBGFX_EFFECT_MANAGER__ -#define __DRAWBGFX_EFFECT_MANAGER__ +#pragma once #include <map> +#include <memory> #include <string> -#include <bgfx/bgfx.h> - -#include "shadermanager.h" class bgfx_effect; +class osd_options; +class shader_manager; -class effect_manager { +class effect_manager +{ public: - effect_manager(shader_manager& shaders) : m_shaders(shaders) { } + effect_manager(shader_manager& shaders); ~effect_manager(); // Getters - bgfx_effect* get_or_load_effect(osd_options &options, std::string name); - static bool validate_effect(osd_options &options, std::string name); + bgfx_effect* get_or_load_effect(const osd_options &options, const std::string &name); + static bool validate_effect(const osd_options &options, const std::string &name); private: - bgfx_effect* load_effect(osd_options& options, std::string name); + bgfx_effect* load_effect(const osd_options &options, const std::string &name); - shader_manager& m_shaders; - std::map<std::string, bgfx_effect*> m_effects; + shader_manager &m_shaders; + std::map<std::string, std::unique_ptr<bgfx_effect> > m_effects; }; -#endif // __DRAWBGFX_EFFECT_MANAGER__ +#endif // MAME_RENDER_BGFX_EFFECTMANAGER_H diff --git a/src/osd/modules/render/bgfx/effectreader.cpp b/src/osd/modules/render/bgfx/effectreader.cpp index 36acee2f9ea..befdc598537 100644 --- a/src/osd/modules/render/bgfx/effectreader.cpp +++ b/src/osd/modules/render/bgfx/effectreader.cpp @@ -8,80 +8,79 @@ #include "effectreader.h" -#include "effect.h" #include "blendreader.h" -#include "depthreader.h" #include "cullreader.h" -#include "writereader.h" +#include "depthreader.h" +#include "effect.h" #include "shadermanager.h" -#include "uniformreader.h" #include "uniform.h" +#include "uniformreader.h" +#include "writereader.h" -bgfx_effect *effect_reader::read_from_value(const Value& value, std::string prefix, osd_options &options, shader_manager& shaders) +#include <utility> + + +std::unique_ptr<bgfx_effect> effect_reader::read_from_value( + const std::string &name, + const Value &value, + const std::string &prefix, + const osd_options &options, + shader_manager &shaders) { uint64_t flags = 0; std::string vertex_name; std::string fragment_name; - bgfx::ShaderHandle vertex_shader = BGFX_INVALID_HANDLE; - bgfx::ShaderHandle fragment_shader = BGFX_INVALID_HANDLE; - std::vector<bgfx_uniform *> uniforms; + std::vector<std::unique_ptr<bgfx_uniform> > uniforms; if (!get_base_effect_data(value, prefix, flags, vertex_name, fragment_name, uniforms)) { return nullptr; } + bgfx::ShaderHandle vertex_shader = BGFX_INVALID_HANDLE; + bgfx::ShaderHandle fragment_shader = BGFX_INVALID_HANDLE; + if (!get_shader_data(value, options, shaders, vertex_name, vertex_shader, fragment_name, fragment_shader)) { - clear_uniform_list(uniforms); return nullptr; } - bgfx_effect *effect = new bgfx_effect(flags, vertex_shader, fragment_shader, uniforms); - if (effect->is_valid()) - { - return effect; - } - - delete effect; + std::unique_ptr<bgfx_effect> effect(new bgfx_effect(std::string(name), flags, vertex_shader, fragment_shader, uniforms)); + if (!effect->is_valid()) + return nullptr; - return nullptr; + return effect; } -bool effect_reader::validate_value(const Value& value, std::string prefix, osd_options &options) +bool effect_reader::validate_value(const Value& value, const std::string &prefix, const osd_options &options) { if (!validate_parameters(value, prefix)) - { return false; - } uint64_t flags = 0; std::string vertex_name; std::string fragment_name; - std::vector<bgfx_uniform *> uniforms; + std::vector<std::unique_ptr<bgfx_uniform> > uniforms; if (!get_base_effect_data(value, prefix, flags, vertex_name, fragment_name, uniforms)) - { return false; - } if (!shader_manager::is_shader_present(options, vertex_name)) - { - clear_uniform_list(uniforms); return false; - } if (!shader_manager::is_shader_present(options, fragment_name)) - { - clear_uniform_list(uniforms); return false; - } return true; } -bool effect_reader::get_base_effect_data(const Value& value, std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name, - std::vector<bgfx_uniform *> &uniforms) +bool effect_reader::get_base_effect_data( + const Value& value, + const std::string &prefix, + uint64_t &flags, + std::string &vertex_name, + std::string &fragment_name, + std::vector<std::unique_ptr<bgfx_uniform> > &uniforms) { if (!validate_parameters(value, prefix)) { @@ -101,12 +100,12 @@ bool effect_reader::get_base_effect_data(const Value& value, std::string &prefix const Value& uniform_array = value["uniforms"]; for (uint32_t i = 0; i < uniform_array.Size(); i++) { - bgfx_uniform *uniform = uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: "); - if (uniform == nullptr) + auto uniform = uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: "); + if (!uniform) { return false; } - uniforms.push_back(uniform); + uniforms.emplace_back(std::move(uniform)); } vertex_name = value["vertex"].GetString(); @@ -127,8 +126,14 @@ bool effect_reader::get_base_effect_data(const Value& value, std::string &prefix return true; } -bool effect_reader::get_shader_data(const Value& value, osd_options &options, shader_manager &shaders, std::string &vertex_name, bgfx::ShaderHandle &vertex_shader, - std::string &fragment_name, bgfx::ShaderHandle &fragment_shader) +bool effect_reader::get_shader_data( + const Value &value, + const osd_options &options, + shader_manager &shaders, + std::string &vertex_name, + bgfx::ShaderHandle &vertex_shader, + std::string &fragment_name, + bgfx::ShaderHandle &fragment_shader) { vertex_shader = shaders.load_shader(options, vertex_name); if (vertex_shader.idx == bgfx::kInvalidHandle) @@ -145,25 +150,17 @@ bool effect_reader::get_shader_data(const Value& value, osd_options &options, sh return true; } -void effect_reader::clear_uniform_list(std::vector<bgfx_uniform *> &uniforms) -{ - for (bgfx_uniform *uniform : uniforms) - { - delete uniform; - } -} - -bool effect_reader::validate_parameters(const Value& value, std::string prefix) +bool effect_reader::validate_parameters(const Value& value, const std::string &prefix) { - 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; + if (!READER_CHECK(value.HasMember("depth"), "%sMust have object value 'depth' (what are our Z-buffer settings?)\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("cull"), "%sMust have object value 'cull' (do we cull triangles based on winding?)\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("write"), "%sMust have object value 'write' (what are our color buffer write settings?)\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("vertex"), "%sMust have string value 'vertex' (what is our vertex shader?)\n", prefix)) return false; + if (!READER_CHECK(value["vertex"].IsString(), "%sValue 'vertex' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("fragment") || value.HasMember("pixel"), "%sMust have string value named 'fragment' or 'pixel' (what is our fragment/pixel shader?)\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("fragment") || value["fragment"].IsString(), "%sValue 'fragment' must be a string\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("pixel") || value["pixel"].IsString(), "%sValue 'pixel' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("uniforms"), "%sMust have array value 'uniforms' (what are our shader's parameters?)\n", prefix)) return false; + if (!READER_CHECK(value["uniforms"].IsArray(), "%sValue 'uniforms' must be an array\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/effectreader.h b/src/osd/modules/render/bgfx/effectreader.h index 095f06a56ea..db590e5eeb3 100644 --- a/src/osd/modules/render/bgfx/effectreader.h +++ b/src/osd/modules/render/bgfx/effectreader.h @@ -6,36 +6,38 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_EFFECTREADER_H +#define MAME_RENDER_BGFX_EFFECTREADER_H -#ifndef __DRAWBGFX_EFFECT_READER__ -#define __DRAWBGFX_EFFECT_READER__ +#pragma once #include "statereader.h" #include <bgfx/bgfx.h> +#include <memory> #include <string> #include <vector> + class bgfx_effect; class bgfx_uniform; class osd_options; class shader_manager; + class effect_reader : public state_reader { public: - static bgfx_effect *read_from_value(const Value& value, std::string prefix, osd_options &options, shader_manager& shaders); - static bool validate_value(const Value& value, std::string prefix, osd_options &options); + static std::unique_ptr<bgfx_effect> read_from_value(const std::string &name, const Value& value, const std::string &prefix, const osd_options &options, shader_manager& shaders); + static bool validate_value(const Value& value, const std::string &prefix, const osd_options &options); private: - static bool get_base_effect_data(const Value& value, std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name, - std::vector<bgfx_uniform *> &uniforms); - static bool get_shader_data(const Value& value, osd_options &options, shader_manager &shaders, std::string &vertex_name, bgfx::ShaderHandle &vertex_shader, + static bool get_base_effect_data(const Value& value, const std::string &prefix, uint64_t &flags, std::string &vertex_name, std::string &fragment_name, + std::vector<std::unique_ptr<bgfx_uniform> > &uniforms); + static bool get_shader_data(const Value& value, const osd_options &options, shader_manager &shaders, std::string &vertex_name, bgfx::ShaderHandle &vertex_shader, std::string &fragment_name, bgfx::ShaderHandle &fragment_shader); - static void clear_uniform_list(std::vector<bgfx_uniform *> &uniforms); - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); }; -#endif // __DRAWBGFX_EFFECT_READER__ +#endif // MAME_RENDER_BGFX_EFFECTREADER_H diff --git a/src/osd/modules/render/bgfx/entryuniform.h b/src/osd/modules/render/bgfx/entryuniform.h index 9c1462f360f..88ccc3e536d 100644 --- a/src/osd/modules/render/bgfx/entryuniform.h +++ b/src/osd/modules/render/bgfx/entryuniform.h @@ -9,15 +9,15 @@ // //============================================================ +#ifndef MAME_RENDER_BGFX_ENTRYUNIFORM_H +#define MAME_RENDER_BGFX_ENTRYUNIFORM_H + #pragma once -#ifndef DRAWBGFX_ENTRY_UNIFORM -#define DRAWBGFX_ENTRY_UNIFORM +#include "uniform.h" #include <bgfx/bgfx.h> -#include "uniform.h" - class bgfx_entry_uniform { public: @@ -25,10 +25,10 @@ public: virtual ~bgfx_entry_uniform() { } virtual void bind() = 0; - std::string name() const { return m_uniform->name(); } + const std::string &name() const { return m_uniform->name(); } protected: bgfx_uniform* m_uniform; }; -#endif // __DRAWBGFX_ENTRY_UNIFORM__ +#endif // MAME_RENDER_BGFX_ENTRYUNIFORM_H diff --git a/src/osd/modules/render/bgfx/entryuniformreader.cpp b/src/osd/modules/render/bgfx/entryuniformreader.cpp index 947f4c56e90..62c618f39a7 100644 --- a/src/osd/modules/render/bgfx/entryuniformreader.cpp +++ b/src/osd/modules/render/bgfx/entryuniformreader.cpp @@ -15,7 +15,7 @@ #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) +bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, const 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)) { @@ -25,7 +25,7 @@ bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, st 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())) + if (!READER_CHECK(uniform != nullptr, "%sUniform '%s' does not appear to exist\n", prefix, name)) { return nullptr; } @@ -44,16 +44,16 @@ bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, st } else { - READER_CHECK(false, (prefix + "Unrecognized uniform type for uniform binding " + name).c_str()); + READER_CHECK(false, "%sUnrecognized uniform type for uniform binding %s", prefix, name); } return nullptr; } -bool entry_uniform_reader::validate_parameters(const Value& value, std::string prefix) +bool entry_uniform_reader::validate_parameters(const Value& value, const 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; + if (!READER_CHECK(value.HasMember("uniform"), "%sMust have string value 'uniform' (what uniform are we mapping?)\n", prefix)) return false; + if (!READER_CHECK(value["uniform"].IsString(), "%sValue 'effect' must be a string\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/entryuniformreader.h b/src/osd/modules/render/bgfx/entryuniformreader.h index 73c66269a5e..c85a2647826 100644 --- a/src/osd/modules/render/bgfx/entryuniformreader.h +++ b/src/osd/modules/render/bgfx/entryuniformreader.h @@ -6,16 +6,16 @@ // //============================================================ +#ifndef MAME_RENDER_BGFX_ENTRYUNIFORMREADER_H +#define MAME_RENDER_BGFX_ENTRYUNIFORMREADER_H + #pragma once -#ifndef __DRAWBGFX_ENTRY_UNIFORM_READER__ -#define __DRAWBGFX_ENTRY_UNIFORM_READER__ +#include "statereader.h" #include <string> #include <map> -#include "statereader.h" - class bgfx_entry_uniform; class bgfx_slider; class bgfx_effect; @@ -24,10 +24,10 @@ 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); + static bgfx_entry_uniform* read_from_value(const Value& value, const 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); + static bool validate_parameters(const Value& value, const std::string &prefix); }; -#endif // __DRAWBGFX_ENTRY_UNIFORM_READER__ +#endif // MAME_RENDER_BGFX_ENTRYUNIFORMREADER_H diff --git a/src/osd/modules/render/bgfx/frameparameter.cpp b/src/osd/modules/render/bgfx/frameparameter.cpp index 841d4d0d2e5..6b16fe1d5fa 100644 --- a/src/osd/modules/render/bgfx/frameparameter.cpp +++ b/src/osd/modules/render/bgfx/frameparameter.cpp @@ -8,8 +8,10 @@ #include "frameparameter.h" -bgfx_frame_parameter::bgfx_frame_parameter(std::string name, parameter_type type, uint32_t period) - : bgfx_parameter(name, type) +#include <utility> + +bgfx_frame_parameter::bgfx_frame_parameter(std::string &&name, parameter_type type, uint32_t period) + : bgfx_parameter(std::move(name), type) , m_current_frame(0) , m_period(period) { @@ -20,7 +22,7 @@ float bgfx_frame_parameter::value() return float(m_current_frame); } -void bgfx_frame_parameter::tick(double /*delta*/) +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 index e559d13c1d8..2a1e8f6094b 100644 --- a/src/osd/modules/render/bgfx/frameparameter.h +++ b/src/osd/modules/render/bgfx/frameparameter.h @@ -6,22 +6,20 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_FRAMEPARAMETER_H +#define MAME_RENDER_BGFX_FRAMEPARAMETER_H -#ifndef __DRAWBGFX_FRAME_PARAMETER__ -#define __DRAWBGFX_FRAME_PARAMETER__ +#pragma once -#include <bgfx/bgfx.h> +#include "parameter.h" +#include <cstdint> #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() { } + bgfx_frame_parameter(std::string &&name, parameter_type type, uint32_t period); virtual float value() override; virtual void tick(double delta) override; @@ -31,4 +29,4 @@ private: uint32_t m_period; }; -#endif // __DRAWBGFX_FRAME_PARAMETER__ +#endif // MAME_RENDER_BGFX_FRAMEPARAMETER_H diff --git a/src/osd/modules/render/bgfx/inputpair.cpp b/src/osd/modules/render/bgfx/inputpair.cpp index 5f1324c2581..154252db04f 100644 --- a/src/osd/modules/render/bgfx/inputpair.cpp +++ b/src/osd/modules/render/bgfx/inputpair.cpp @@ -11,15 +11,18 @@ #include "inputpair.h" -#include "../frontend/mame/ui/slider.h" - -#include "texture.h" -#include "target.h" -#include "effect.h" -#include "uniform.h" #include "chainmanager.h" +#include "effect.h" #include "slider.h" #include "sliderdirtynotifier.h" +#include "target.h" +#include "texture.h" +#include "uniform.h" + +#include "../frontend/mame/ui/slider.h" + +#include "util/strformat.h" + bgfx_input_pair::bgfx_input_pair(int index, std::string sampler, std::string texture, std::vector<std::string> available_textures, std::string selection, chain_manager& chains, uint32_t screen_index) : m_index(index) @@ -53,20 +56,31 @@ void bgfx_input_pair::bind(bgfx_effect *effect, const int32_t screen) const if (!provider) return; + float rowpixels(provider->rowpixels()); + float width_margin(provider->width_margin()); + float height(provider->height()); + bgfx_uniform *tex_size = effect->uniform("u_tex_size" + std::to_string(m_index)); if (tex_size && provider) { - float values[2] = { float(provider->rowpixels()), float(provider->height()) }; + float values[2] = { rowpixels, height }; tex_size->set(values, sizeof(float) * 2); } bgfx_uniform *inv_tex_size = effect->uniform("u_inv_tex_size" + std::to_string(m_index)); if (inv_tex_size && provider) { - float values[2] = { 1.0f / float(provider->rowpixels()), 1.0f / float(provider->height()) }; + float values[2] = { 1.0f / rowpixels, 1.0f / height }; inv_tex_size->set(values, sizeof(float) * 2); } + bgfx_uniform *tex_bounds = effect->uniform("u_tex_bounds" + std::to_string(m_index)); + if (tex_bounds && provider) + { + float values[4] = { width_margin / rowpixels, 0.0f, 1.0f + width_margin / rowpixels, 1.0f }; + tex_bounds->set(values, sizeof(float) * 4); + } + bgfx::setTexture(m_index, effect->uniform(m_sampler)->handle(), chains().textures().handle(name)); } @@ -109,11 +123,11 @@ void bgfx_input_pair::create_selection_slider(uint32_t screen_index) int32_t maxval = m_available_textures.size() - 1; int32_t incval = 1; - std::string description = "Window " + std::to_string(chains().window_index()) + ", Screen " + std::to_string(screen_index) + " " + m_selection + ":"; - using namespace std::placeholders; - m_slider_state = std::make_unique<slider_state>(std::move(description), minval, defval, maxval, incval, - std::bind(&bgfx_input_pair::texture_changed, this, screen_index, _1, _2)); + m_slider_state = std::make_unique<slider_state>( + util::string_format("Window %1$u, Screen %1$u %3$s", chains().window_index(), screen_index, m_selection), + minval, defval, maxval, incval, + std::bind(&bgfx_input_pair::texture_changed, this, screen_index, _1, _2)); ui::menu_item item(ui::menu_item_type::SLIDER, m_slider_state.get()); item.set_text(m_slider_state->description); @@ -130,9 +144,7 @@ std::vector<ui::menu_item> bgfx_input_pair::get_slider_list() std::vector<ui::menu_item> sliders; if (!needs_sliders()) - { return sliders; - } sliders.push_back(m_selection_slider); diff --git a/src/osd/modules/render/bgfx/parameter.h b/src/osd/modules/render/bgfx/parameter.h index 2df18365a4c..baa2ff017ad 100644 --- a/src/osd/modules/render/bgfx/parameter.h +++ b/src/osd/modules/render/bgfx/parameter.h @@ -10,12 +10,13 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_PARAMETER_H +#define MAME_RENDER_BGFX_PARAMETER_H -#ifndef __DRAWBGFX_PARAMETER__ -#define __DRAWBGFX_PARAMETER__ +#pragma once #include <string> +#include <utility> class bgfx_parameter { @@ -27,18 +28,18 @@ public: PARAM_TIME }; - bgfx_parameter(std::string name, parameter_type type) : m_name(name), m_type(type) { } - virtual ~bgfx_parameter() { } + bgfx_parameter(std::string &&name, parameter_type type) : m_name(std::move(name)), m_type(type) { } + virtual ~bgfx_parameter() = default; virtual void tick(double delta) = 0; // Getters virtual float value() = 0; - std::string name() const { return m_name; } + const std::string &name() const { return m_name; } protected: std::string m_name; parameter_type m_type; }; -#endif // __DRAWBGFX_PARAMETER__ +#endif // MAME_RENDER_BGFX_PARAMETER_H diff --git a/src/osd/modules/render/bgfx/paramreader.cpp b/src/osd/modules/render/bgfx/paramreader.cpp index 1b14b2aa56a..0eeb5f22e84 100644 --- a/src/osd/modules/render/bgfx/paramreader.cpp +++ b/src/osd/modules/render/bgfx/paramreader.cpp @@ -6,15 +6,13 @@ // //============================================================ -#include <string> - #include "paramreader.h" -#include "parameter.h" +#include "chainmanager.h" #include "frameparameter.h" -#include "windowparameter.h" +#include "parameter.h" #include "timeparameter.h" -#include "chainmanager.h" +#include "windowparameter.h" const parameter_reader::string_to_enum parameter_reader::TYPE_NAMES[parameter_reader::TYPE_COUNT] = { { "frame", bgfx_parameter::parameter_type::PARAM_FRAME }, @@ -22,7 +20,7 @@ const parameter_reader::string_to_enum parameter_reader::TYPE_NAMES[parameter_re { "time", bgfx_parameter::parameter_type::PARAM_TIME } }; -bgfx_parameter* parameter_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains) +bgfx_parameter* parameter_reader::read_from_value(const Value& value, const std::string &prefix, chain_manager& chains) { if (!validate_parameters(value, prefix)) { @@ -35,32 +33,32 @@ bgfx_parameter* parameter_reader::read_from_value(const Value& value, std::strin if (type == bgfx_parameter::parameter_type::PARAM_FRAME) { uint32_t period = int(value["period"].GetDouble()); - return new bgfx_frame_parameter(name, type, period); + return new bgfx_frame_parameter(std::move(name), type, period); } else if (type == bgfx_parameter::parameter_type::PARAM_WINDOW) { - return new bgfx_window_parameter(name, type, chains.window_index()); + return new bgfx_window_parameter(std::move(name), type, chains.window_index()); } else if (type == bgfx_parameter::parameter_type::PARAM_TIME) { auto limit = float(value["limit"].GetDouble()); - return new bgfx_time_parameter(name, type, limit); + return new bgfx_time_parameter(std::move(name), type, limit); } else { - READER_CHECK(false, (prefix + "Unknown parameter type '" + std::string(value["type"].GetString()) + "'\n").c_str()); + READER_CHECK(false, "%sUnknown parameter type '%s'\n", prefix, value["type"].GetString()); } return nullptr; } -bool parameter_reader::validate_parameters(const Value& value, std::string prefix) +bool parameter_reader::validate_parameters(const Value& value, const 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("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; + if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name'\n", prefix)) return false; + if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("type"), "%sMust have string value 'type'\n", prefix)) return false; + if (!READER_CHECK(value["type"].IsString(), "%sValue 'type' must be a string\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("period") || value["period"].IsNumber(), "%sValue 'period' must be numeric\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("limit") || value["limit"].IsNumber(), "%sValue 'period' must be numeric\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/paramreader.h b/src/osd/modules/render/bgfx/paramreader.h index 013d6589cc3..bfd23b14a42 100644 --- a/src/osd/modules/render/bgfx/paramreader.h +++ b/src/osd/modules/render/bgfx/paramreader.h @@ -6,26 +6,28 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_PARAMREADER_H +#define MAME_RENDER_BGFX_PARAMREADER_H -#ifndef __DRAWBGFX_PARAM_READER__ -#define __DRAWBGFX_PARAM_READER__ +#pragma once #include "statereader.h" +#include <string> + class bgfx_parameter; class chain_manager; class parameter_reader : public state_reader { public: - static bgfx_parameter* read_from_value(const Value& value, std::string prefix, chain_manager& chains); + static bgfx_parameter* read_from_value(const Value& value, const std::string &prefix, chain_manager& chains); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); static const int TYPE_COUNT = 3; static const string_to_enum TYPE_NAMES[TYPE_COUNT]; }; -#endif // __DRAWBGFX_PARAM_READER__ +#endif // MAME_RENDER_BGFX_PARAMREADER_H diff --git a/src/osd/modules/render/bgfx/paramuniform.h b/src/osd/modules/render/bgfx/paramuniform.h index b49fb2c7d61..5f5b69c96a6 100644 --- a/src/osd/modules/render/bgfx/paramuniform.h +++ b/src/osd/modules/render/bgfx/paramuniform.h @@ -6,10 +6,10 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_PARAMUNIFORM_H +#define MAME_RENDER_BGFX_PARAMUNIFORM_H -#ifndef __DRAWBGFX_PARAM_UNIFORM__ -#define __DRAWBGFX_PARAM_UNIFORM__ +#pragma once #include "entryuniform.h" @@ -26,4 +26,4 @@ private: bgfx_parameter* m_param; }; -#endif // __DRAWBGFX_PARAM_UNIFORM__ +#endif // MAME_RENDER_BGFX_PARAMUNIFORM_H diff --git a/src/osd/modules/render/bgfx/paramuniformreader.cpp b/src/osd/modules/render/bgfx/paramuniformreader.cpp index 2b613fc216c..8c5cd265195 100644 --- a/src/osd/modules/render/bgfx/paramuniformreader.cpp +++ b/src/osd/modules/render/bgfx/paramuniformreader.cpp @@ -9,10 +9,10 @@ #include "paramuniformreader.h" #include "entryuniform.h" -#include "paramuniform.h" #include "parameter.h" +#include "paramuniform.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) +bgfx_entry_uniform* param_uniform_reader::read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_parameter*>& params) { if (!validate_parameters(value, prefix)) { @@ -24,9 +24,9 @@ bgfx_entry_uniform* param_uniform_reader::read_from_value(const Value& value, st return new bgfx_param_uniform(uniform, params[parameter]); } -bool param_uniform_reader::validate_parameters(const Value& value, std::string prefix) +bool param_uniform_reader::validate_parameters(const Value& value, const 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; + if (!READER_CHECK(value.HasMember("parameter"), "%sMust have string value 'parameter' (what parameter is being mapped?)\n", prefix)) return false; + if (!READER_CHECK(value["parameter"].IsString(), "%sValue 'parameter' must be a string\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/paramuniformreader.h b/src/osd/modules/render/bgfx/paramuniformreader.h index baf281b562b..b1ed2a87f69 100644 --- a/src/osd/modules/render/bgfx/paramuniformreader.h +++ b/src/osd/modules/render/bgfx/paramuniformreader.h @@ -6,15 +6,15 @@ // //================================================================== +#ifndef MAME_RENDER_BGFX_PARAMUNIFORMREADER_H +#define MAME_RENDER_BGFX_PARAMUNIFORMREADER_H + #pragma once -#ifndef __DRAWBGFX_PARAM_UNIFORM_READER__ -#define __DRAWBGFX_PARAM_UNIFORM_READER__ +#include "statereader.h" -#include <string> #include <map> - -#include "statereader.h" +#include <string> class bgfx_entry_uniform; class bgfx_uniform; @@ -23,10 +23,10 @@ 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); + static bgfx_entry_uniform* read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_parameter*>& params); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); }; -#endif // __DRAWBGFX_PARAM_UNIFORM_READER__ +#endif // MAME_RENDER_BGFX_PARAMUNIFORMREADER_H diff --git a/src/osd/modules/render/bgfx/shadermanager.cpp b/src/osd/modules/render/bgfx/shadermanager.cpp index dd894426794..763a744e4aa 100644 --- a/src/osd/modules/render/bgfx/shadermanager.cpp +++ b/src/osd/modules/render/bgfx/shadermanager.cpp @@ -16,11 +16,10 @@ #include "osdfile.h" #include "modules/lib/osdobj_common.h" +#include <bx/file.h> #include <bx/math.h> #include <bx/readerwriter.h> -#include <bx/file.h> -#include <bgfx/bgfx.h> shader_manager::~shader_manager() { @@ -31,7 +30,7 @@ shader_manager::~shader_manager() m_shaders.clear(); } -bgfx::ShaderHandle shader_manager::get_or_load_shader(osd_options &options, std::string name) +bgfx::ShaderHandle shader_manager::get_or_load_shader(const osd_options &options, const std::string &name) { std::map<std::string, bgfx::ShaderHandle>::iterator iter = m_shaders.find(name); if (iter != m_shaders.end()) @@ -48,7 +47,7 @@ bgfx::ShaderHandle shader_manager::get_or_load_shader(osd_options &options, std: return handle; } -bgfx::ShaderHandle shader_manager::load_shader(osd_options &options, std::string name) +bgfx::ShaderHandle shader_manager::load_shader(const osd_options &options, const std::string &name) { std::string shader_path = make_path_string(options, name); const bgfx::Memory* mem = load_mem(shader_path + name + ".bin"); @@ -60,16 +59,17 @@ bgfx::ShaderHandle shader_manager::load_shader(osd_options &options, std::string return BGFX_INVALID_HANDLE; } -bool shader_manager::is_shader_present(osd_options &options, std::string name) +bool shader_manager::is_shader_present(const osd_options &options, const std::string &name) { std::string shader_path = make_path_string(options, name); std::string file_name = shader_path + name + ".bin"; bx::FileReader reader; + bx::ErrorAssert err; if (bx::open(&reader, file_name.c_str())) { uint32_t expected_size(bx::getSize(&reader)); uint8_t *data = new uint8_t[expected_size]; - uint32_t read_size = (uint32_t)bx::read(&reader, data, expected_size); + uint32_t read_size = (uint32_t)bx::read(&reader, data, expected_size, &err); delete [] data; bx::close(&reader); @@ -79,7 +79,7 @@ bool shader_manager::is_shader_present(osd_options &options, std::string name) return false; } -std::string shader_manager::make_path_string(osd_options &options, std::string name) +std::string shader_manager::make_path_string(const osd_options &options, const std::string &name) { std::string shader_path(options.bgfx_path()); shader_path += PATH_SEPARATOR "shaders" PATH_SEPARATOR; @@ -119,17 +119,18 @@ std::string shader_manager::make_path_string(osd_options &options, std::string n fatalerror("Unknown BGFX renderer type %d", bgfx::getRendererType()); } shader_path += PATH_SEPARATOR; - return osd_subst_env(shader_path); + return shader_path; } -const bgfx::Memory* shader_manager::load_mem(std::string name) +const bgfx::Memory* shader_manager::load_mem(const std::string &name) { bx::FileReader reader; if (bx::open(&reader, name.c_str())) { + bx::ErrorAssert err; uint32_t size(bx::getSize(&reader)); const bgfx::Memory* mem = bgfx::alloc(size + 1); - bx::read(&reader, mem->data, size); + bx::read(&reader, mem->data, size, &err); bx::close(&reader); mem->data[mem->size - 1] = '\0'; @@ -137,7 +138,7 @@ const bgfx::Memory* shader_manager::load_mem(std::string name) } else { - osd_printf_error("Unable to load shader %s\n", name.c_str()); + osd_printf_error("Unable to load shader %s\n", name); } return nullptr; } diff --git a/src/osd/modules/render/bgfx/shadermanager.h b/src/osd/modules/render/bgfx/shadermanager.h index 81fa4260f47..12ac739d35a 100644 --- a/src/osd/modules/render/bgfx/shadermanager.h +++ b/src/osd/modules/render/bgfx/shadermanager.h @@ -9,10 +9,10 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_SHADERMANAGER_H +#define MAME_RENDER_BGFX_SHADERMANAGER_H -#ifndef __DRAWBGFX_SHADER_MANAGER__ -#define __DRAWBGFX_SHADER_MANAGER__ +#pragma once #include <bgfx/bgfx.h> @@ -22,21 +22,23 @@ class osd_options; -class shader_manager { + +class shader_manager +{ public: shader_manager() { } ~shader_manager(); // Getters - bgfx::ShaderHandle get_or_load_shader(osd_options &options, std::string name); - static bgfx::ShaderHandle load_shader(osd_options &options, std::string name); - static bool is_shader_present(osd_options &options, std::string name); + bgfx::ShaderHandle get_or_load_shader(const osd_options &options, const std::string &name); + static bgfx::ShaderHandle load_shader(const osd_options &options, const std::string &name); + static bool is_shader_present(const osd_options &options, const std::string &name); private: - static std::string make_path_string(osd_options &options, std::string name); - static const bgfx::Memory* load_mem(std::string name); + static std::string make_path_string(const osd_options &options, const std::string &name); + static const bgfx::Memory* load_mem(const std::string &name); - std::map<std::string, bgfx::ShaderHandle> m_shaders; + std::map<std::string, bgfx::ShaderHandle> m_shaders; }; -#endif // __DRAWBGFX_SHADER_MANAGER__ +#endif // MAME_RENDER_BGFX_SHADERMANAGER_H diff --git a/src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc b/src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc index 4c688c4d6f4..6ea70cb6aac 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/blurs/fs_smart-blur.sc @@ -39,26 +39,26 @@ uniform vec4 SB_THRESHOLD; bool eq(vec3 c1, vec3 c2) { - vec3 df = abs(c1 - c2); - return df.r < SB_THRESHOLD.r && df.g < SB_THRESHOLD.g && df.b < SB_THRESHOLD.b; + vec3 df = abs(c1 - c2); + return df.r < SB_THRESHOLD.r && df.g < SB_THRESHOLD.g && df.b < SB_THRESHOLD.b; } void main() { - vec3 A = texture2D(s_p, v_texcoord1.xw).xyz; - vec3 B = texture2D(s_p, v_texcoord1.yw).xyz; - vec3 C = texture2D(s_p, v_texcoord1.zw).xyz; - vec3 D = texture2D(s_p, v_texcoord2.xw).xyz; - vec3 E = texture2D(s_p, v_texcoord2.yw).xyz; - vec3 F = texture2D(s_p, v_texcoord2.zw).xyz; - vec3 G = texture2D(s_p, v_texcoord3.xw).xyz; - vec3 H = texture2D(s_p, v_texcoord3.yw).xyz; - vec3 I = texture2D(s_p, v_texcoord3.zw).xyz; + vec3 A = texture2D(s_p, v_texcoord1.xw).xyz; + vec3 B = texture2D(s_p, v_texcoord1.yw).xyz; + vec3 C = texture2D(s_p, v_texcoord1.zw).xyz; + vec3 D = texture2D(s_p, v_texcoord2.xw).xyz; + vec3 E = texture2D(s_p, v_texcoord2.yw).xyz; + vec3 F = texture2D(s_p, v_texcoord2.zw).xyz; + vec3 G = texture2D(s_p, v_texcoord3.xw).xyz; + vec3 H = texture2D(s_p, v_texcoord3.yw).xyz; + vec3 I = texture2D(s_p, v_texcoord3.zw).xyz; - if (eq(E,F) && eq(E,H) && eq(E,I) && eq(E,B) && eq(E,C) && eq(E,A) && eq(E,D) && eq(E,G)) - { - E = (A + B + C + D + E + F + G + H + I) / 9.0; - } + if (eq(E,F) && eq(E,H) && eq(E,I) && eq(E,B) && eq(E,C) && eq(E,A) && eq(E,D) && eq(E,G)) + { + E = (A + B + C + D + E + F + G + H + I) / 9.0; + } - gl_FragColor = vec4(E, 1.0); + gl_FragColor = vec4(E, 1.0); } diff --git a/src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc b/src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc index 1b967f894d4..40b0947da38 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/blurs/vs_smart-blur.sc @@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc index 6863a180ef6..9118e42d5c8 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc @@ -13,12 +13,12 @@ vec4 TEX2D(vec2 c) { - vec2 underscan = step(0.0,c) * step(0.0,vec2_splat(1.0)-c); - vec4 col = texture2D(mpass_texture, c) * vec4_splat(underscan.x*underscan.y); + vec2 underscan = step(0.0,c) * step(0.0,vec2_splat(1.0)-c); + vec4 col = texture2D(mpass_texture, c) * vec4_splat(underscan.x*underscan.y); #ifdef LINEAR_PROCESSING - col = pow(col, vec4_splat(CRTgamma.x)); + col = pow(col, vec4_splat(CRTgamma.x)); #endif - return col; + return col; } // Enable screen curvature. @@ -48,43 +48,43 @@ uniform vec4 cornersmooth; float intersect(vec2 xy , vec2 sinangle, vec2 cosangle) { - float A = dot(xy,xy)+d.x*d.x; - float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x); - float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y; - return (-B-sqrt(B*B-4.0*A*C))/(2.0*A); + float A = dot(xy,xy)+d.x*d.x; + float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x); + float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y; + return (-B-sqrt(B*B-4.0*A*C))/(2.0*A); } vec2 bkwtrans(vec2 xy, vec2 sinangle, vec2 cosangle) { - float c = intersect(xy, sinangle, cosangle); - vec2 pt = vec2_splat(c)*xy; - pt -= vec2_splat(-R.x)*sinangle; - pt /= vec2_splat(R.x); - vec2 tang = sinangle/cosangle; - vec2 poc = pt/cosangle; - float A = dot(tang,tang)+1.0; - float B = -2.0*dot(poc,tang); - float C = dot(poc,poc)-1.0; - float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A); - vec2 uv = (pt-a*sinangle)/cosangle; - float r = FIX(R.x*acos(a)); - return uv*r/sin(r/R.x); + float c = intersect(xy, sinangle, cosangle); + vec2 pt = vec2_splat(c)*xy; + pt -= vec2_splat(-R.x)*sinangle; + pt /= vec2_splat(R.x); + vec2 tang = sinangle/cosangle; + vec2 poc = pt/cosangle; + float A = dot(tang,tang)+1.0; + float B = -2.0*dot(poc,tang); + float C = dot(poc,poc)-1.0; + float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A); + vec2 uv = (pt-a*sinangle)/cosangle; + float r = FIX(R.x*acos(a)); + return uv*r/sin(r/R.x); } vec2 transform(vec2 coord, vec3 stretch, vec2 sinangle, vec2 cosangle) { - coord = (coord-vec2_splat(0.5))*aspect.xy*stretch.z+stretch.xy; - return (bkwtrans(coord, sinangle, cosangle)/overscan.xy/aspect.xy+vec2_splat(0.5)); + coord = (coord-vec2_splat(0.5))*aspect.xy*stretch.z+stretch.xy; + return (bkwtrans(coord, sinangle, cosangle)/overscan.xy/aspect.xy+vec2_splat(0.5)); } float corner(vec2 coord) { - coord = (coord - vec2_splat(0.5)) * overscan.xy + vec2_splat(0.5); - coord = min(coord, vec2_splat(1.0)-coord) * aspect.xy; - vec2 cdist = vec2_splat(cornersize.x); - coord = (cdist - min(coord,cdist)); - float dist = sqrt(dot(coord,coord)); - return clamp((max(cdist.x,1e-3)-dist)*cornersmooth.x,0.0, 1.0); + coord = (coord - vec2_splat(0.5)) * overscan.xy + vec2_splat(0.5); + coord = min(coord, vec2_splat(1.0)-coord) * aspect.xy; + vec2 cdist = vec2_splat(cornersize.x); + coord = (cdist - min(coord,cdist)); + float dist = sqrt(dot(coord,coord)); + return clamp((max(cdist.x,1e-3)-dist)*cornersmooth.x,0.0, 1.0); } // Calculate the influence of a scanline on the current pixel. @@ -95,109 +95,109 @@ float corner(vec2 coord) // the current pixel. vec4 scanlineWeights(float distance, vec4 color) { - // "wid" controls the width of the scanline beam, for each RGB channel - // The "weights" lines basically specify the formula that gives - // you the profile of the beam, i.e. the intensity as - // a function of distance from the vertical center of the - // scanline. In this case, it is gaussian if width=2, and - // becomes nongaussian for larger widths. Ideally this should - // be normalized so that the integral across the beam is - // independent of its width. That is, for a narrower beam - // "weights" should have a higher peak at the center of the - // scanline than for a wider beam. + // "wid" controls the width of the scanline beam, for each RGB channel + // The "weights" lines basically specify the formula that gives + // you the profile of the beam, i.e. the intensity as + // a function of distance from the vertical center of the + // scanline. In this case, it is gaussian if width=2, and + // becomes nongaussian for larger widths. Ideally this should + // be normalized so that the integral across the beam is + // independent of its width. That is, for a narrower beam + // "weights" should have a higher peak at the center of the + // scanline than for a wider beam. #ifdef USEGAUSSIAN - vec4 wid = spot_size.x + spot_growth.x * pow(color, vec4_splat(spot_growth_power.x)); - vec4 weights = vec4(distance / wid); - float maxwid = spot_size.x + spot_growth.x; - float norm = maxwid / ( 1.0 + exp(-1.0/(maxwid*maxwid)) ); - return norm * exp(-weights * weights) / wid; + vec4 wid = spot_size.x + spot_growth.x * pow(color, vec4_splat(spot_growth_power.x)); + vec4 weights = vec4(distance / wid); + float maxwid = spot_size.x + spot_growth.x; + float norm = maxwid / ( 1.0 + exp(-1.0/(maxwid*maxwid)) ); + return norm * exp(-weights * weights) / wid; #else - vec4 wid = 2.0 + 2.0 * pow(color, vec4_splat(4.0)); - vec4 weights = vec4_splat(distance / 0.3); - return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid); + vec4 wid = 2.0 + 2.0 * pow(color, vec4_splat(4.0)); + vec4 weights = vec4_splat(distance / 0.3); + return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid); #endif } vec4 cubic(vec4 x, float B, float C) { - // https://en.wikipedia.org/wiki/Mitchell%E2%80%93Netravali_filters - vec2 a = x.yz; // components in [0,1] - vec2 b = x.xw; // components in [1,2] - vec2 a2 = a*a; - vec2 b2 = b*b; - a = (2.0-1.5*B-1.0*C)*a*a2 + (-3.0+2.0*B+C)*a2 + (1.0-(1.0/3.0)*B); - b = ((-1.0/6.0)*B-C)*b*b2 + (B+5.0*C)*b2 + (-2.0*B-8.0*C)*b + ((4.0/3.0)*B+4.0*C); - return vec4(b.x,a.x,a.y,b.y); + // https://en.wikipedia.org/wiki/Mitchell%E2%80%93Netravali_filters + vec2 a = x.yz; // components in [0,1] + vec2 b = x.xw; // components in [1,2] + vec2 a2 = a*a; + vec2 b2 = b*b; + a = (2.0-1.5*B-1.0*C)*a*a2 + (-3.0+2.0*B+C)*a2 + (1.0-(1.0/3.0)*B); + b = ((-1.0/6.0)*B-C)*b*b2 + (B+5.0*C)*b2 + (-2.0*B-8.0*C)*b + ((4.0/3.0)*B+4.0*C); + return vec4(b.x,a.x,a.y,b.y); } vec4 x_coeffs(vec4 x, float pos_x) { - if (u_interp.x < 0.5) { // box - float wid = length(vec2(dFdx(pos_x),dFdy(pos_x))); - float dx = clamp((0.5 + 0.5*wid - x.y)/wid, 0.0, 1.0); - return vec4(0.0,dx,1.0-dx,0.0); - } else if (u_interp.x < 1.5) { // linear - return vec4(0.0, 1.0-x.y, 1.0-x.z, 0.0); - } else if (u_interp.x < 2.5) { // Lanczos - // Prevent division by zero. - vec4 coeffs = FIX(PI * x); - // Lanczos2 kernel. - coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs); - // Normalize. - coeffs /= dot(coeffs, vec4_splat(1.0)); - return coeffs; - } else if (u_interp.x < 3.5) { // Catmull-Rom - return cubic(x,0.0,0.5); - } else if (u_interp.x < 4.5) { // Mitchell-Netravali - return cubic(x,1.0/3.0,1.0/3.0); - } else /*if (u_interp.x < 5.5)*/ { // B-spline - return cubic(x,1.0,0.0); - } + if (u_interp.x < 0.5) { // box + float wid = length(vec2(dFdx(pos_x),dFdy(pos_x))); + float dx = clamp((0.5 + 0.5*wid - x.y)/wid, 0.0, 1.0); + return vec4(0.0,dx,1.0-dx,0.0); + } else if (u_interp.x < 1.5) { // linear + return vec4(0.0, 1.0-x.y, 1.0-x.z, 0.0); + } else if (u_interp.x < 2.5) { // Lanczos + // Prevent division by zero. + vec4 coeffs = FIX(PI * x); + // Lanczos2 kernel. + coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs); + // Normalize. + coeffs /= dot(coeffs, vec4_splat(1.0)); + return coeffs; + } else if (u_interp.x < 3.5) { // Catmull-Rom + return cubic(x,0.0,0.5); + } else if (u_interp.x < 4.5) { // Mitchell-Netravali + return cubic(x,1.0/3.0,1.0/3.0); + } else /*if (u_interp.x < 5.5)*/ { // B-spline + return cubic(x,1.0,0.0); + } } vec4 sample_scanline(vec2 xy, vec4 coeffs, float onex) { - // Calculate the effective colour of the given - // scanline at the horizontal location of the current pixel, - // using the Lanczos coefficients. - vec4 col = clamp(TEX2D(xy + vec2(-onex, 0.0))*coeffs.x + - TEX2D(xy)*coeffs.y + - TEX2D(xy +vec2(onex, 0.0))*coeffs.z + - TEX2D(xy + vec2(2.0 * onex, 0.0))*coeffs.w , 0.0, 1.0); - return col; + // Calculate the effective colour of the given + // scanline at the horizontal location of the current pixel, + // using the Lanczos coefficients. + vec4 col = clamp(TEX2D(xy + vec2(-onex, 0.0))*coeffs.x + + TEX2D(xy)*coeffs.y + + TEX2D(xy +vec2(onex, 0.0))*coeffs.z + + TEX2D(xy + vec2(2.0 * onex, 0.0))*coeffs.w , 0.0, 1.0); + return col; } vec3 apply_shadow_mask(vec2 coord, vec3 col) { - vec2 xy = coord * u_quad_dims.xy / u_tex_size1.xy; - vec4 mask = texture2D(mask_texture, xy); - // count of total bright pixels is encoded in the mask's alpha channel - float nbright = 255.0 - 255.0*mask.a; - // fraction of bright pixels in the mask - float fbright = nbright / ( u_tex_size1.x * u_tex_size1.y ); - // average darkening factor of the mask - float aperture_average = mix(1.0-aperture_strength.x*(1.0-aperture_brightboost.x), 1.0, fbright); - // colour of dark mask pixels - vec3 clow = vec3_splat(1.0-aperture_strength.x) * col + vec3_splat(aperture_strength.x*(aperture_brightboost.x)) * col * col; - float ifbright = 1.0 / fbright; - // colour of bright mask pixels - vec3 chi = vec3_splat(ifbright*aperture_average) * col - vec3_splat(ifbright - 1.0) * clow; - return mix(clow,chi,mask.rgb); // mask texture selects dark vs bright + vec2 xy = coord * u_quad_dims.xy / u_tex_size1.xy; + vec4 mask = texture2D(mask_texture, xy); + // count of total bright pixels is encoded in the mask's alpha channel + float nbright = 255.0 - 255.0*mask.a; + // fraction of bright pixels in the mask + float fbright = nbright / ( u_tex_size1.x * u_tex_size1.y ); + // average darkening factor of the mask + float aperture_average = mix(1.0-aperture_strength.x*(1.0-aperture_brightboost.x), 1.0, fbright); + // colour of dark mask pixels + vec3 clow = vec3_splat(1.0-aperture_strength.x) * col + vec3_splat(aperture_strength.x*(aperture_brightboost.x)) * col * col; + float ifbright = 1.0 / fbright; + // colour of bright mask pixels + vec3 chi = vec3_splat(ifbright*aperture_average) * col - vec3_splat(ifbright - 1.0) * clow; + return mix(clow,chi,mask.rgb); // mask texture selects dark vs bright } vec3 linear_to_sRGB(vec3 col) { - // only applies the gamma ramp; does not adjust the primaries - vec3 linear_ramp = vec3(lessThan(col, vec3_splat(0.0031308))); - vec3 clin = col * vec3_splat(12.92); - vec3 cpow = pow(col, vec3_splat(1.0/2.4)) * vec3_splat(1.055) - vec3_splat(0.055); - return mix(cpow, clin, linear_ramp); + // only applies the gamma ramp; does not adjust the primaries + vec3 linear_ramp = vec3(lessThan(col, vec3_splat(0.0031308))); + vec3 clin = col * vec3_splat(12.92); + vec3 cpow = pow(col, vec3_splat(1.0/2.4)) * vec3_splat(1.055) - vec3_splat(0.055); + return mix(cpow, clin, linear_ramp); } vec3 linear_to_output(vec3 col) { - if (monitorsRGB.x > 0.5) - return linear_to_sRGB(col); - else - return pow(col, vec3_splat(1.0 / monitorgamma.x)); + if (monitorsRGB.x > 0.5) + return linear_to_sRGB(col); + else + return pow(col, vec3_splat(1.0 / monitorgamma.x)); } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc index 72705bdcb83..5b8a633a642 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc @@ -28,9 +28,9 @@ uniform vec4 rasterbloom; uniform vec4 blurwidth; -vec3 texblur(vec2 c) +vec4 texblur(vec2 c) { - vec3 col = pow(texture2D(blur_texture,c).rgb, vec3_splat(CRTgamma.x)); + vec4 col = pow(texture2D(blur_texture,c), vec4(vec3_splat(CRTgamma.x),1.0)); // taper the blur texture outside its border with a gaussian float w = blurwidth.x / 320.0; c = min(c, vec2_splat(1.0)-c) * aspect.xy * vec2_splat(1.0/w); @@ -38,7 +38,7 @@ vec3 texblur(vec2 c) // approximation of erf gives smooth step // (convolution of gaussian with step) c = (step(0.0,c)-vec2_splat(0.5)) * sqrt(vec2_splat(1.0)-e2c) * (vec2_splat(1.0) + vec2_splat(0.1749)*e2c) + vec2_splat(0.5); - return col * vec3_splat( c.x * c.y ); + return col * vec4_splat( c.x * c.y ); } void main() @@ -125,16 +125,16 @@ void main() weights_prev=weights_prev+scanlineWeights(uv_ratio.y+1.0, col_prev)/3.0; weights_next=weights_next+scanlineWeights(uv_ratio.y-1.0, col_next)/3.0; #endif - vec3 mul_res = (col * weights + col_prev * weights_prev + col_next * weights_next).rgb; + vec4 mul_res = col * weights + col_prev * weights_prev + col_next * weights_next; // halation and corners - vec3 blur = texblur(xy0); + vec4 blur = texblur(xy0); // include factor of rbloom: // (probably imperceptible) brightness reduction when raster grows - mul_res = mix(mul_res, blur, halation.x) * vec3_splat(cval*rbloom); + mul_res = mix(mul_res, blur, halation.x) * vec4_splat(cval*rbloom); // Shadow mask - vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res); + vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res.rgb); // Convert the image gamma for display on our output device. cout = linear_to_output(cout); diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc index c096ebca7e0..5226a9999cc 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc @@ -24,79 +24,79 @@ uniform vec4 u_quad_dims; void main() { - // Here's a helpful diagram to keep in mind while trying to - // understand the code: - // - // | | | | | - // ------------------------------- - // | | | | | - // | 01 | 11 | 21 | 31 | <-- current scanline - // | | @ | | | - // ------------------------------- - // | | | | | - // | 02 | 12 | 22 | 32 | <-- next scanline - // | | | | | - // ------------------------------- - // | | | | | - // - // Each character-cell represents a pixel on the output - // surface, "@" represents the current pixel (always somewhere - // in the bottom half of the current scan-line, or the top-half - // of the next scanline). The grid of lines represents the - // edges of the texels of the underlying texture. - - // Texture coordinates of the texel containing the active pixel. - vec2 xy; - if (curvature.x > 0.5) - xy = transform(v_texCoord, v_stretch, v_sinangle, v_cosangle); - else - xy = (v_texCoord-vec2_splat(0.5))/overscan.xy+vec2_splat(0.5); - float cval = corner(xy); - - // Of all the pixels that are mapped onto the texel we are - // currently rendering, which pixel are we currently rendering? - vec2 ratio_scale = xy * u_tex_size0.xy - vec2_splat(0.5); + // Here's a helpful diagram to keep in mind while trying to + // understand the code: + // + // | | | | | + // ------------------------------- + // | | | | | + // | 01 | 11 | 21 | 31 | <-- current scanline + // | | @ | | | + // ------------------------------- + // | | | | | + // | 02 | 12 | 22 | 32 | <-- next scanline + // | | | | | + // ------------------------------- + // | | | | | + // + // Each character-cell represents a pixel on the output + // surface, "@" represents the current pixel (always somewhere + // in the bottom half of the current scan-line, or the top-half + // of the next scanline). The grid of lines represents the + // edges of the texels of the underlying texture. + + // Texture coordinates of the texel containing the active pixel. + vec2 xy; + if (curvature.x > 0.5) + xy = transform(v_texCoord, v_stretch, v_sinangle, v_cosangle); + else + xy = (v_texCoord-vec2_splat(0.5))/overscan.xy+vec2_splat(0.5); + float cval = corner(xy); + + // Of all the pixels that are mapped onto the texel we are + // currently rendering, which pixel are we currently rendering? + vec2 ratio_scale = xy * u_tex_size0.xy - vec2_splat(0.5); #ifdef OVERSAMPLE - float filter = fwidth(ratio_scale.y); + float filter = fwidth(ratio_scale.y); #endif - vec2 uv_ratio = fract(ratio_scale); + vec2 uv_ratio = fract(ratio_scale); - // Snap to the center of the underlying texel. - xy = (floor(ratio_scale) + vec2_splat(0.5)) / u_tex_size0.xy; + // Snap to the center of the underlying texel. + xy = (floor(ratio_scale) + vec2_splat(0.5)) / u_tex_size0.xy; - // Calculate scaling coefficients describing the effect - // of various neighbour texels in a scanline on the current - // pixel. - vec4 coeffs = x_coeffs(vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x), ratio_scale.x); + // Calculate scaling coefficients describing the effect + // of various neighbour texels in a scanline on the current + // pixel. + vec4 coeffs = x_coeffs(vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x), ratio_scale.x); - vec4 col = sample_scanline(xy, coeffs, v_one.x); - vec4 col2 = sample_scanline(xy + vec2(0.0, v_one.y), coeffs, v_one.x); + vec4 col = sample_scanline(xy, coeffs, v_one.x); + vec4 col2 = sample_scanline(xy + vec2(0.0, v_one.y), coeffs, v_one.x); #ifndef LINEAR_PROCESSING - col = pow(col , vec4_splat(CRTgamma.x)); - col2 = pow(col2, vec4_splat(CRTgamma.x)); + col = pow(col , vec4_splat(CRTgamma.x)); + col2 = pow(col2, vec4_splat(CRTgamma.x)); #endif - // Calculate the influence of the current and next scanlines on - // the current pixel. - vec4 weights = scanlineWeights(uv_ratio.y, col); - vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2); + // Calculate the influence of the current and next scanlines on + // the current pixel. + vec4 weights = scanlineWeights(uv_ratio.y, col); + vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2); #ifdef OVERSAMPLE - uv_ratio.y =uv_ratio.y+1.0/3.0*filter; - weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0; - weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0; - uv_ratio.y =uv_ratio.y-2.0/3.0*filter; - weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0; - weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0; + uv_ratio.y =uv_ratio.y+1.0/3.0*filter; + weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0; + weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0; + uv_ratio.y =uv_ratio.y-2.0/3.0*filter; + weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0; + weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0; #endif - vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3_splat(cval); + vec4 mul_res = col * weights + col2 * weights2 * vec4_splat(cval); - // Shadow mask - vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res); + // Shadow mask + vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res.rgb); - // Convert the image gamma for display on our output device. - cout = linear_to_output(cout); + // Convert the image gamma for display on our output device. + cout = linear_to_output(cout); - gl_FragColor = vec4(cout,1.0); + gl_FragColor = vec4(cout,mul_res.a); } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc index 74faf15a740..6290ae330eb 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc @@ -6,33 +6,33 @@ uniform vec4 u_gamma; uniform vec4 u_tex_size0; SAMPLER2D(s_tex, 0); -#define TEX2D(v) pow(texture2D(s_tex, v).rgb, vec3_splat(u_gamma.x)) +#define TEX2D(v) pow(texture2D(s_tex, v), vec4(vec3_splat(u_gamma.x), 1.0)) void main() { - vec3 sum = vec3_splat(0.0); + vec4 sum = vec4_splat(0.0); float onex = 1.0/u_tex_size0.x; - sum += TEX2D(v_texCoord + vec2(-8.0 * onex, 0.0)) * vec3_splat(v_coeffs2.w); - sum += TEX2D(v_texCoord + vec2(-7.0 * onex, 0.0)) * vec3_splat(v_coeffs2.z); - sum += TEX2D(v_texCoord + vec2(-6.0 * onex, 0.0)) * vec3_splat(v_coeffs2.y); - sum += TEX2D(v_texCoord + vec2(-5.0 * onex, 0.0)) * vec3_splat(v_coeffs2.x); - sum += TEX2D(v_texCoord + vec2(-4.0 * onex, 0.0)) * vec3_splat(v_coeffs.w); - sum += TEX2D(v_texCoord + vec2(-3.0 * onex, 0.0)) * vec3_splat(v_coeffs.z); - sum += TEX2D(v_texCoord + vec2(-2.0 * onex, 0.0)) * vec3_splat(v_coeffs.y); - sum += TEX2D(v_texCoord + vec2(-1.0 * onex, 0.0)) * vec3_splat(v_coeffs.x); + sum += TEX2D(v_texCoord + vec2(-8.0 * onex, 0.0)) * vec4_splat(v_coeffs2.w); + sum += TEX2D(v_texCoord + vec2(-7.0 * onex, 0.0)) * vec4_splat(v_coeffs2.z); + sum += TEX2D(v_texCoord + vec2(-6.0 * onex, 0.0)) * vec4_splat(v_coeffs2.y); + sum += TEX2D(v_texCoord + vec2(-5.0 * onex, 0.0)) * vec4_splat(v_coeffs2.x); + sum += TEX2D(v_texCoord + vec2(-4.0 * onex, 0.0)) * vec4_splat(v_coeffs.w); + sum += TEX2D(v_texCoord + vec2(-3.0 * onex, 0.0)) * vec4_splat(v_coeffs.z); + sum += TEX2D(v_texCoord + vec2(-2.0 * onex, 0.0)) * vec4_splat(v_coeffs.y); + sum += TEX2D(v_texCoord + vec2(-1.0 * onex, 0.0)) * vec4_splat(v_coeffs.x); sum += TEX2D(v_texCoord); - sum += TEX2D(v_texCoord + vec2(+1.0 * onex, 0.0)) * vec3_splat(v_coeffs.x); - sum += TEX2D(v_texCoord + vec2(+2.0 * onex, 0.0)) * vec3_splat(v_coeffs.y); - sum += TEX2D(v_texCoord + vec2(+3.0 * onex, 0.0)) * vec3_splat(v_coeffs.z); - sum += TEX2D(v_texCoord + vec2(+4.0 * onex, 0.0)) * vec3_splat(v_coeffs.w); - sum += TEX2D(v_texCoord + vec2(+5.0 * onex, 0.0)) * vec3_splat(v_coeffs2.x); - sum += TEX2D(v_texCoord + vec2(+6.0 * onex, 0.0)) * vec3_splat(v_coeffs2.y); - sum += TEX2D(v_texCoord + vec2(+7.0 * onex, 0.0)) * vec3_splat(v_coeffs2.z); - sum += TEX2D(v_texCoord + vec2(+8.0 * onex, 0.0)) * vec3_splat(v_coeffs2.w); + sum += TEX2D(v_texCoord + vec2(+1.0 * onex, 0.0)) * vec4_splat(v_coeffs.x); + sum += TEX2D(v_texCoord + vec2(+2.0 * onex, 0.0)) * vec4_splat(v_coeffs.y); + sum += TEX2D(v_texCoord + vec2(+3.0 * onex, 0.0)) * vec4_splat(v_coeffs.z); + sum += TEX2D(v_texCoord + vec2(+4.0 * onex, 0.0)) * vec4_splat(v_coeffs.w); + sum += TEX2D(v_texCoord + vec2(+5.0 * onex, 0.0)) * vec4_splat(v_coeffs2.x); + sum += TEX2D(v_texCoord + vec2(+6.0 * onex, 0.0)) * vec4_splat(v_coeffs2.y); + sum += TEX2D(v_texCoord + vec2(+7.0 * onex, 0.0)) * vec4_splat(v_coeffs2.z); + sum += TEX2D(v_texCoord + vec2(+8.0 * onex, 0.0)) * vec4_splat(v_coeffs2.w); float norm = 1.0 / (1.0 + 2.0*(v_coeffs.x+v_coeffs.y+v_coeffs.z+v_coeffs.w +v_coeffs2.x+v_coeffs2.y+v_coeffs2.z+v_coeffs2.w)); - gl_FragColor = vec4( pow(sum*vec3_splat(norm), vec3_splat(1.0/u_gamma.x)), 1.0 ); + gl_FragColor = pow(sum*vec4_splat(norm), vec4(vec3_splat(1.0/u_gamma.x), 1.0)); } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc index c4fa73cdcce..9f4eace6cbe 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc @@ -6,33 +6,33 @@ uniform vec4 u_gamma; uniform vec4 u_tex_size0; SAMPLER2D(s_tex, 0); -#define TEX2D(v) pow(texture2D(s_tex, v).rgb, vec3_splat(u_gamma.x)) +#define TEX2D(v) pow(texture2D(s_tex, v), vec4(vec3_splat(u_gamma.x), 1.0)) void main() { - vec3 sum = vec3_splat(0.0); + vec4 sum = vec4_splat(0.0); float oney = 1.0/u_tex_size0.y; - sum += TEX2D(v_texCoord + vec2(0.0, -8.0 * oney)) * vec3_splat(v_coeffs2.w); - sum += TEX2D(v_texCoord + vec2(0.0, -7.0 * oney)) * vec3_splat(v_coeffs2.z); - sum += TEX2D(v_texCoord + vec2(0.0, -6.0 * oney)) * vec3_splat(v_coeffs2.y); - sum += TEX2D(v_texCoord + vec2(0.0, -5.0 * oney)) * vec3_splat(v_coeffs2.x); - sum += TEX2D(v_texCoord + vec2(0.0, -4.0 * oney)) * vec3_splat(v_coeffs.w); - sum += TEX2D(v_texCoord + vec2(0.0, -3.0 * oney)) * vec3_splat(v_coeffs.z); - sum += TEX2D(v_texCoord + vec2(0.0, -2.0 * oney)) * vec3_splat(v_coeffs.y); - sum += TEX2D(v_texCoord + vec2(0.0, -1.0 * oney)) * vec3_splat(v_coeffs.x); + sum += TEX2D(v_texCoord + vec2(0.0, -8.0 * oney)) * vec4_splat(v_coeffs2.w); + sum += TEX2D(v_texCoord + vec2(0.0, -7.0 * oney)) * vec4_splat(v_coeffs2.z); + sum += TEX2D(v_texCoord + vec2(0.0, -6.0 * oney)) * vec4_splat(v_coeffs2.y); + sum += TEX2D(v_texCoord + vec2(0.0, -5.0 * oney)) * vec4_splat(v_coeffs2.x); + sum += TEX2D(v_texCoord + vec2(0.0, -4.0 * oney)) * vec4_splat(v_coeffs.w); + sum += TEX2D(v_texCoord + vec2(0.0, -3.0 * oney)) * vec4_splat(v_coeffs.z); + sum += TEX2D(v_texCoord + vec2(0.0, -2.0 * oney)) * vec4_splat(v_coeffs.y); + sum += TEX2D(v_texCoord + vec2(0.0, -1.0 * oney)) * vec4_splat(v_coeffs.x); sum += TEX2D(v_texCoord); - sum += TEX2D(v_texCoord + vec2(0.0, +1.0 * oney)) * vec3_splat(v_coeffs.x); - sum += TEX2D(v_texCoord + vec2(0.0, +2.0 * oney)) * vec3_splat(v_coeffs.y); - sum += TEX2D(v_texCoord + vec2(0.0, +3.0 * oney)) * vec3_splat(v_coeffs.z); - sum += TEX2D(v_texCoord + vec2(0.0, +4.0 * oney)) * vec3_splat(v_coeffs.w); - sum += TEX2D(v_texCoord + vec2(0.0, +5.0 * oney)) * vec3_splat(v_coeffs2.x); - sum += TEX2D(v_texCoord + vec2(0.0, +6.0 * oney)) * vec3_splat(v_coeffs2.y); - sum += TEX2D(v_texCoord + vec2(0.0, +7.0 * oney)) * vec3_splat(v_coeffs2.z); - sum += TEX2D(v_texCoord + vec2(0.0, +8.0 * oney)) * vec3_splat(v_coeffs2.w); + sum += TEX2D(v_texCoord + vec2(0.0, +1.0 * oney)) * vec4_splat(v_coeffs.x); + sum += TEX2D(v_texCoord + vec2(0.0, +2.0 * oney)) * vec4_splat(v_coeffs.y); + sum += TEX2D(v_texCoord + vec2(0.0, +3.0 * oney)) * vec4_splat(v_coeffs.z); + sum += TEX2D(v_texCoord + vec2(0.0, +4.0 * oney)) * vec4_splat(v_coeffs.w); + sum += TEX2D(v_texCoord + vec2(0.0, +5.0 * oney)) * vec4_splat(v_coeffs2.x); + sum += TEX2D(v_texCoord + vec2(0.0, +6.0 * oney)) * vec4_splat(v_coeffs2.y); + sum += TEX2D(v_texCoord + vec2(0.0, +7.0 * oney)) * vec4_splat(v_coeffs2.z); + sum += TEX2D(v_texCoord + vec2(0.0, +8.0 * oney)) * vec4_splat(v_coeffs2.w); float norm = 1.0 / (1.0 + 2.0*(v_coeffs.x+v_coeffs.y+v_coeffs.z+v_coeffs.w +v_coeffs2.x+v_coeffs2.y+v_coeffs2.z+v_coeffs2.w)); - gl_FragColor = vec4( pow(sum*vec3_splat(norm), vec3_splat(1.0/u_gamma.x)), 1.0 ); + gl_FragColor = pow(sum*vec4_splat(norm), vec4(vec3_splat(1.0/u_gamma.x), 1.0)); } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc index 2f48bbac321..37ab685957c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_lowpass.sc @@ -33,5 +33,5 @@ void main() sum +=sample_screen(v_texCoord+vec2(-7.0*onex,0.0))*vec3_splat(v_lpcoeffs2.w); sum +=sample_screen(v_texCoord+vec2( 7.0*onex,0.0))*vec3_splat(v_lpcoeffs2.w); - gl_FragColor = vec4( sum, 1.0 ); + gl_FragColor = vec4( sum, texture2D(s_screen, v_texCoord).a ); } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc index 0f86bdbc7ba..2e0f8038053 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_mipmap8.sc @@ -22,7 +22,7 @@ uniform vec4 u_smooth; const vec2 v05 = vec2(0.5,0.5); // pix has integer coordinates -> average four pixels using bilinear filtering -vec3 sample_screen(vec2 pix) +vec4 sample_screen(vec2 pix) { vec2 border = step(-0.5, u_tex_size0.xy - pix); float weight = border.x * border.y; @@ -34,12 +34,12 @@ vec3 sample_screen(vec2 pix) border = clamp(u_tex_size0.xy-x,0.0,1.0); weight *= border.x * border.y; - vec3 tex = texture2D(s_screen, x / u_tex_size0.xy).rgb; + vec4 tex = texture2D(s_screen, x / u_tex_size0.xy); - return tex * vec3_splat(weight); + return tex * vec4_splat(weight); } -vec3 sample_mipmap(vec2 pix, vec2 offset, vec2 size) +vec4 sample_mipmap(vec2 pix, vec2 offset, vec2 size) { vec2 border = step(-0.5, size - pix) * step(-0.5, pix); float weight = border.x * border.y; @@ -51,9 +51,9 @@ vec3 sample_mipmap(vec2 pix, vec2 offset, vec2 size) border = clamp(size-x,0.0,1.0); weight *= border.x * border.y; - vec3 tex = texture2D(s_mipmap, (x + offset) / u_tex_size0.xy).rgb; + vec4 tex = texture2D(s_mipmap, (x + offset) / u_tex_size0.xy); - return tex * vec3_splat(weight); + return tex * vec4_splat(weight); } void main() @@ -66,7 +66,7 @@ void main() // sample 4x4 grid // each sample uses bilinear filtering to average a 2x2 region // overall reduction by 8x8 - vec3 tex = ( sample_screen(x + vec2(-3.0,-3.0)) + vec4 tex = ( sample_screen(x + vec2(-3.0,-3.0)) + sample_screen(x + vec2(-3.0,-1.0)) + sample_screen(x + vec2(-3.0, 1.0)) + sample_screen(x + vec2(-3.0, 3.0)) @@ -113,7 +113,7 @@ void main() if (fc) x = vec2(4.0,4.0); - vec3 tex = ( sample_mipmap(x + vec2(-3.0,-3.0),offset0,newsize) + vec4 tex = ( sample_mipmap(x + vec2(-3.0,-3.0),offset0,newsize) + sample_mipmap(x + vec2(-3.0,-1.0),offset0,newsize) + sample_mipmap(x + vec2(-3.0, 1.0),offset0,newsize) + sample_mipmap(x + vec2(-3.0, 3.0),offset0,newsize) @@ -133,16 +133,16 @@ void main() if (fc) { // this sample yields average over the whole screen // apply a compensation for the zeros included in the 8^n average float f = fac*fac / (u_tex_size0.x * u_tex_size0.y); - vec3 col = tex * vec3_splat(f); + vec4 col = tex * vec4_splat(f); if (v_texCoord.y * u_tex_size1.y < ( offset0.y + u_tex_size1.y ) * 0.5) { - gl_FragColor = vec4(col,1.0); + gl_FragColor = col; } else { // we are near (1,1): in this region include the temporal filter vec4 old = texture2D(s_mipmap, v_texCoord.xy); - gl_FragColor = vec4(mix(col,old.rgb,u_smooth.x),1.0); + gl_FragColor = mix(col,old,u_smooth.x); } } else { - gl_FragColor = vec4(tex.rgb,1.0); + gl_FragColor = tex; } } } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc index c45fb8f883f..f7e116696cb 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_phosphor_apply.sc @@ -28,15 +28,15 @@ void main() vec4 screen = texture2D(s_screen, v_texCoord); vec4 phosphor = texture2D(s_phosphor, v_texCoord); - vec3 cscrn = pow(screen.rgb, vec3_splat(u_gamma.x)); - vec3 cphos = pow(phosphor.rgb, vec3_splat(u_gamma.x)); + vec4 cscrn = pow(screen, vec4(vec3_splat(u_gamma.x), 1.0)); + vec4 cphos = pow(phosphor, vec4(vec3_splat(u_gamma.x), 1.0)); // encode the upper 2 bits of the time elapsed in the lower 2 bits of b float t = 255.0*phosphor.a + fract(phosphor.b*255.0/4.0)*1024.0; - cphos *= vec3_splat( u_phosphor_amplitude.x * decay(t) ); + cphos *= vec4_splat( u_phosphor_amplitude.x * decay(t) ); - vec3 col = pow(cscrn + cphos, vec3_splat(1.0/u_gamma.x)); + vec4 col = pow(cscrn + cphos, vec4(vec3_splat(1.0/u_gamma.x), 1.0)); - gl_FragColor = vec4(col, 1.0); + gl_FragColor = col; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc index cc3ed09aa14..4f17f0d0ec3 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_crt-geom.sc @@ -19,78 +19,82 @@ uniform vec4 R; uniform vec4 angle; uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; uniform vec4 u_rotation_type; #define FIX(c) max(abs(c), 1e-5) float intersect(vec2 xy , vec2 sinangle, vec2 cosangle) { - float A = dot(xy,xy)+d.x*d.x; - float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x); - float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y; - return (-B-sqrt(B*B-4.0*A*C))/(2.0*A); + float A = dot(xy,xy)+d.x*d.x; + float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x); + float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y; + return (-B-sqrt(B*B-4.0*A*C))/(2.0*A); } vec2 bkwtrans(vec2 xy, vec2 sinangle, vec2 cosangle) { - float c = intersect(xy, sinangle, cosangle); - vec2 pt = vec2_splat(c)*xy; - pt -= vec2_splat(-R.x)*sinangle; - pt /= vec2_splat(R.x); - vec2 tang = sinangle/cosangle; - vec2 poc = pt/cosangle; - float A = dot(tang,tang)+1.0; - float B = -2.0*dot(poc,tang); - float C = dot(poc,poc)-1.0; - float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A); - vec2 uv = (pt-a*sinangle)/cosangle; - float r = FIX(R.x*acos(a)); - return uv*r/sin(r/R.x); + float c = intersect(xy, sinangle, cosangle); + vec2 pt = vec2_splat(c)*xy; + pt -= vec2_splat(-R.x)*sinangle; + pt /= vec2_splat(R.x); + vec2 tang = sinangle/cosangle; + vec2 poc = pt/cosangle; + float A = dot(tang,tang)+1.0; + float B = -2.0*dot(poc,tang); + float C = dot(poc,poc)-1.0; + float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A); + vec2 uv = (pt-a*sinangle)/cosangle; + float r = FIX(R.x*acos(a)); + return uv*r/sin(r/R.x); } vec2 fwtrans(vec2 uv, vec2 sinangle, vec2 cosangle) { - float r = FIX(sqrt(dot(uv,uv))); - uv *= sin(r/R.x)/r; - float x = 1.0-cos(r/R.x); - float D = d.x/R.x + x*cosangle.x*cosangle.y+dot(uv,sinangle); - return d.x*(uv*cosangle-x*sinangle)/D; + float r = FIX(sqrt(dot(uv,uv))); + uv *= sin(r/R.x)/r; + float x = 1.0-cos(r/R.x); + float D = d.x/R.x + x*cosangle.x*cosangle.y+dot(uv,sinangle); + return d.x*(uv*cosangle-x*sinangle)/D; } vec3 maxscale(vec2 sinangle, vec2 cosangle) { - vec2 c = bkwtrans(-R.x * sinangle / (1.0 + R.x/d.x*cosangle.x*cosangle.y), sinangle, cosangle); - vec2 a = vec2(0.5,0.5)*aspect.xy; - vec2 lo = vec2(fwtrans(vec2(-a.x,c.y), sinangle, cosangle).x, - fwtrans(vec2(c.x,-a.y), sinangle, cosangle).y)/aspect.xy; - vec2 hi = vec2(fwtrans(vec2(+a.x,c.y), sinangle, cosangle).x, - fwtrans(vec2(c.x,+a.y), sinangle, cosangle).y)/aspect.xy; - return vec3((hi+lo)*aspect.xy*0.5,max(hi.x-lo.x,hi.y-lo.y)); + vec2 c = bkwtrans(-R.x * sinangle / (1.0 + R.x/d.x*cosangle.x*cosangle.y), sinangle, cosangle); + vec2 a = vec2(0.5,0.5)*aspect.xy; + vec2 lo = vec2(fwtrans(vec2(-a.x,c.y), sinangle, cosangle).x, + fwtrans(vec2(c.x,-a.y), sinangle, cosangle).y)/aspect.xy; + vec2 hi = vec2(fwtrans(vec2(+a.x,c.y), sinangle, cosangle).x, + fwtrans(vec2(c.x,+a.y), sinangle, cosangle).y)/aspect.xy; + return vec3((hi+lo)*aspect.xy*0.5,max(hi.x-lo.x,hi.y-lo.y)); } void main() { - // Do the standard vertex processing. - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); - v_texCoord = a_texcoord0; + // Do the standard vertex processing. + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif + v_texCoord = a_texcoord0; - // Precalculate a bunch of useful values we'll need in the fragment - // shader. - vec2 ang; - // if (u_rotation_type.x < 0.5) - // ang = vec2(0.0,angle.x); - // else if (u_rotation_type.x < 1.5) - // ang = vec2(angle.x,0.0); - // else if (u_rotation_type.x < 2.5) - // ang = vec2(0.0,-angle.x); - // else - // ang = vec2(-angle.x,0.0); - ang = angle.xy; - v_sinangle = sin(ang); - v_cosangle = cos(ang); - v_stretch = maxscale(v_sinangle, v_cosangle); + // Precalculate a bunch of useful values we'll need in the fragment + // shader. + vec2 ang; + // if (u_rotation_type.x < 0.5) + // ang = vec2(0.0,angle.x); + // else if (u_rotation_type.x < 1.5) + // ang = vec2(angle.x,0.0); + // else if (u_rotation_type.x < 2.5) + // ang = vec2(0.0,-angle.x); + // else + // ang = vec2(-angle.x,0.0); + ang = angle.xy; + v_sinangle = sin(ang); + v_cosangle = cos(ang); + v_stretch = maxscale(v_sinangle, v_cosangle); - // The size of one texel, in texture-coordinates. - v_one = 1.0 / u_tex_size0.xy; + // The size of one texel, in texture-coordinates. + v_one = 1.0 / u_tex_size0.xy; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc index e9969187c94..a5fb1d22622 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc @@ -4,16 +4,20 @@ $output v_texCoord, v_coeffs, v_coeffs2 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; uniform vec4 u_width; uniform vec4 u_aspect; void main() { - float wid = u_width.x*u_tex_size0.x/(320.*u_aspect.x); - v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid)); - v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid)); + float wid = u_width.x*u_tex_size0.x/(320.*u_aspect.x); + v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid)); + v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid)); - // Do the standard vertex processing. - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); - v_texCoord = a_texcoord0; + // Do the standard vertex processing. + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif + v_texCoord = a_texcoord0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc index 0b7ff9b411f..93676cde1d5 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc @@ -4,16 +4,20 @@ $output v_texCoord, v_coeffs, v_coeffs2 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; uniform vec4 u_width; uniform vec4 u_aspect; void main() { - float wid = u_width.x*u_tex_size0.y/(320.*u_aspect.y); - v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid)); - v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid)); + float wid = u_width.x*u_tex_size0.y/(320.*u_aspect.y); + v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid)); + v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid)); - // Do the standard vertex processing. - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); - v_texCoord = a_texcoord0; + // Do the standard vertex processing. + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif + v_texCoord = a_texcoord0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc index 4d948a63a89..2ca983d41d7 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_lowpass.sc @@ -4,46 +4,50 @@ $output v_texCoord, v_lpcoeffs1, v_lpcoeffs2 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; uniform vec4 u_lowpass_cutoff; uniform vec4 u_lowpass_width; void main() { - // Do the standard vertex processing. - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); - v_texCoord = a_texcoord0; + // Do the standard vertex processing. + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif + v_texCoord = a_texcoord0; - // interpret the cutoff and width as target resolutions in pixels per scanline - // include factor of 1/2 because max frequency at given resolution is Nyquist - float a = 0.5 * u_lowpass_cutoff.x / u_tex_size0.x; - float b = 0.5 * u_lowpass_width.x / u_tex_size0.x; - float w0 = (a-0.5*b); - float w1 = (a+0.5*b); + // interpret the cutoff and width as target resolutions in pixels per scanline + // include factor of 1/2 because max frequency at given resolution is Nyquist + float a = 0.5 * u_lowpass_cutoff.x / u_tex_size0.x; + float b = 0.5 * u_lowpass_width.x / u_tex_size0.x; + float w0 = (a-0.5*b); + float w1 = (a+0.5*b); - float two_pi = 6.283185307179586; - vec3 n1 = vec3(1.0,2.0,3.0); - vec4 n2 = vec4(4.0,5.0,6.0,7.0); + float two_pi = 6.283185307179586; + vec3 n1 = vec3(1.0,2.0,3.0); + vec4 n2 = vec4(4.0,5.0,6.0,7.0); - // target frequency response: - // 1 for w < w0 - // 0 for w > w1 - // linearly decreasing for w0 < w < w1 - // this will be approximated by including the lowest Fourier modes - if (w0 > 0.5) { // no filtering - v_lpcoeffs1 = vec4(1.0,0.0,0.0,0.0); - v_lpcoeffs2 = vec4_splat(0.0); - } else if (w1 > 0.5) { // don't reach zero - // here the target has a nonzero response at the Nyquist frequency - v_lpcoeffs1.x = w1 + w0 - (w1 - 0.5)*(w1 - 0.5)/(w1 - w0); - v_lpcoeffs1.yzw = 2.0 / ( two_pi*two_pi*(w1-w0)*n1*n1 ) * ( cos(two_pi*w0*n1) - cos(two_pi*0.5*n1) ); - v_lpcoeffs2 = 2.0 / ( two_pi*two_pi*(w1-w0)*n2*n2 ) * ( cos(two_pi*w0*n2) - cos(two_pi*0.5*n2) ); - } else if (w1 == w0) { // sharp cutoff - v_lpcoeffs1.x = 2.0 * w0; - v_lpcoeffs1.yzw = 2.0 / ( two_pi * n1 ) * sin(two_pi*w0*n1); - v_lpcoeffs2 = 2.0 / ( two_pi * n2 ) * sin(two_pi*w0*n2); - } else { - v_lpcoeffs1.x = w1 + w0; - v_lpcoeffs1.yzw = 2.0 / ( two_pi*two_pi*(w1-w0)*n1*n1 ) * ( cos(two_pi*w0*n1) - cos(two_pi*w1*n1) ); - v_lpcoeffs2 = 2.0 / ( two_pi*two_pi*(w1-w0)*n2*n2 ) * ( cos(two_pi*w0*n2) - cos(two_pi*w1*n2) ); - } + // target frequency response: + // 1 for w < w0 + // 0 for w > w1 + // linearly decreasing for w0 < w < w1 + // this will be approximated by including the lowest Fourier modes + if (w0 > 0.5) { // no filtering + v_lpcoeffs1 = vec4(1.0,0.0,0.0,0.0); + v_lpcoeffs2 = vec4_splat(0.0); + } else if (w1 > 0.5) { // don't reach zero + // here the target has a nonzero response at the Nyquist frequency + v_lpcoeffs1.x = w1 + w0 - (w1 - 0.5)*(w1 - 0.5)/(w1 - w0); + v_lpcoeffs1.yzw = 2.0 / ( two_pi*two_pi*(w1-w0)*n1*n1 ) * ( cos(two_pi*w0*n1) - cos(two_pi*0.5*n1) ); + v_lpcoeffs2 = 2.0 / ( two_pi*two_pi*(w1-w0)*n2*n2 ) * ( cos(two_pi*w0*n2) - cos(two_pi*0.5*n2) ); + } else if (w1 == w0) { // sharp cutoff + v_lpcoeffs1.x = 2.0 * w0; + v_lpcoeffs1.yzw = 2.0 / ( two_pi * n1 ) * sin(two_pi*w0*n1); + v_lpcoeffs2 = 2.0 / ( two_pi * n2 ) * sin(two_pi*w0*n2); + } else { + v_lpcoeffs1.x = w1 + w0; + v_lpcoeffs1.yzw = 2.0 / ( two_pi*two_pi*(w1-w0)*n1*n1 ) * ( cos(two_pi*w0*n1) - cos(two_pi*w1*n1) ); + v_lpcoeffs2 = 2.0 / ( two_pi*two_pi*(w1-w0)*n2*n2 ) * ( cos(two_pi*w0*n2) - cos(two_pi*w1*n2) ); + } } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc index bdd09148403..8424e153cdb 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_mipmap8.sc @@ -3,9 +3,14 @@ $output v_texCoord #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { - // Do the standard vertex processing. - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); - v_texCoord = a_texcoord0; + // Do the standard vertex processing. + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif + v_texCoord = a_texcoord0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc index bdd09148403..8424e153cdb 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_apply.sc @@ -3,9 +3,14 @@ $output v_texCoord #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { - // Do the standard vertex processing. - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); - v_texCoord = a_texcoord0; + // Do the standard vertex processing. + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif + v_texCoord = a_texcoord0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc index bdd09148403..8424e153cdb 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_phosphor_update.sc @@ -3,9 +3,14 @@ $output v_texCoord #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { - // Do the standard vertex processing. - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); - v_texCoord = a_texcoord0; + // Do the standard vertex processing. + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif + v_texCoord = a_texcoord0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc b/src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc index 6dead210d9e..ce22c1e7200 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/crt/vs_crt-caligari.sc @@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_color0 // Autos uniform vec4 u_source_size; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; onex = vec2(1.0 / u_source_size.x, 0.0); diff --git a/src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/default/vs_blit.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc b/src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc index 5219614c794..ca769f5dc07 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/eagle/fs_eagle.sc @@ -122,16 +122,16 @@ void main() else { p01 = 0.5 * (C4 + C5); - } + } - if ((c8 == d2) || (c3 == c4)) - { + if ((c8 == d2) || (c3 == c4)) + { p10 = 0.25 * (3.0 * C4 + C7); - } - else - { + } + else + { p10 = 0.5 * (C7 + C8); - } + } } else { diff --git a/src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc b/src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc index 1ab076dfa73..095d5d562e0 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/eagle/vs_eagle.sc @@ -14,10 +14,14 @@ $output v_color0, texCoord, t1, t2, t3, t4, t5, t6, t7, t8 // Autos uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_color0 = a_color0; vec2 ps = vec2(1.0, 1.0) / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc index cfb7b487596..20820f0c0a3 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc @@ -25,7 +25,7 @@ void main() { // previously this pass was applied two times with offsets of 0.25, 0.5, 0.75, 1.0 // now this pass is applied only once with offsets of 0.25, 0.55, 1.0, 1.6 to achieve the same appearance as before till a maximum defocus of 2.0 - // 0.075x² + 0.225x + 0.25 + // 0.075x² + 0.225x + 0.25 const vec2 Coord1Offset = vec2(-1.60, 0.25); const vec2 Coord2Offset = vec2(-1.00, -0.55); const vec2 Coord3Offset = vec2(-0.55, 1.00); diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc index 47201c0661d..ed4f6195944 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc @@ -134,11 +134,11 @@ vec2 GetDistortedCoords(vec2 centerCoord, float amount, float amountCube) 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 + // fit screen bounds f /= 1.0 + amount * 0.25 + amountCube * 0.125; // apply cubic distortion factor - centerCoord *= f; + centerCoord *= f; return centerCoord; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc index 5942c75bab6..2126398062b 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_scanline.sc @@ -37,34 +37,15 @@ SAMPLER2D(s_shadow, 1); // Scanline Pixel Shader //----------------------------------------------------------------------------- -vec2 GetAdjustedCoords(vec2 coord) -{ - // center coordinates - coord -= 0.5; - - // apply screen scale - coord *= u_screen_scale.xy; - - // un-center coordinates - coord += 0.5; - - // apply screen offset - coord += u_screen_offset.xy; - - return coord; -} - void main() { - vec2 BaseCoord = GetAdjustedCoords(v_texcoord0); - // Color - vec4 BaseColor = texture2D(s_tex, BaseCoord); + vec4 BaseColor = texture2D(s_tex, v_texcoord0); // Clamp - if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 || BaseCoord.x > 1.0 || BaseCoord.y > 1.0) + if (v_texcoord0.x < 0.0 || v_texcoord0.y < 0.0 || v_texcoord0.x > 1.0 || v_texcoord0.y > 1.0) { - gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } else { @@ -76,7 +57,7 @@ void main() float ColorBrightness = 0.299 * BaseColor.r + 0.587 * BaseColor.g + 0.114 * BaseColor.b; - float ScanCoord = BaseCoord.y; + float ScanCoord = v_texcoord0.y; ScanCoord += u_swap_xy.x > 0.0 ? u_quad_dims.x <= u_source_dims.x * 2.0 ? 0.5 / u_quad_dims.x // uncenter scanlines if the quad is less than twice the size of the source diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_chroma.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc index b77d85d1ea8..55c2f0e2e34 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc @@ -8,6 +8,7 @@ $output v_color0, v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3 // Autos uniform vec4 u_source_size; +uniform vec4 u_inv_view_dims; // User-supplied uniform vec4 u_converge_red; @@ -20,6 +21,9 @@ uniform vec4 u_radial_converge_blue; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif vec2 half_value = vec2(0.5, 0.5); diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_scanline.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc index 479ed825a8b..3f6c2645ba4 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq2x.sc @@ -60,8 +60,8 @@ void main() vec2 index; index.x = dot(pattern[0], vec3( 1.0, 2.0, 4.0)) + - dot(pattern[1], vec3( 8.0, 0.0, 16.0)) + - dot(pattern[2], vec3(32.0, 64.0, 128.0)); + dot(pattern[1], vec3( 8.0, 0.0, 16.0)) + + dot(pattern[2], vec3(32.0, 64.0, 128.0)); index.y = dot(cross, vec4(1.0, 2.0, 4.0, 8.0)) * SCALE * SCALE + dot(floor(fp * vec2(SCALE, SCALE)), vec2(1.0, SCALE)); vec2 step = vec2(1.0, 1.0) / vec2(256.0, 16.0 * (SCALE * SCALE)); diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc index 1d35cec01e6..1cb08a52da4 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq3x.sc @@ -60,8 +60,8 @@ void main() vec2 index; index.x = dot(pattern[0], vec3( 1.0, 2.0, 4.0)) + - dot(pattern[1], vec3( 8.0, 0.0, 16.0)) + - dot(pattern[2], vec3(32.0, 64.0, 128.0)); + dot(pattern[1], vec3( 8.0, 0.0, 16.0)) + + dot(pattern[2], vec3(32.0, 64.0, 128.0)); index.y = dot(cross, vec4(1.0, 2.0, 4.0, 8.0)) * SCALE * SCALE + dot(floor(fp * vec2(SCALE, SCALE)), vec2(1.0, SCALE)); vec2 step = vec2(1.0, 1.0) / vec2(256.0, 16.0 * (SCALE * SCALE)); diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc index 6f25b0e9cc3..6e87d47dc0c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/fs_hq4x.sc @@ -60,8 +60,8 @@ void main() vec2 index; index.x = dot(pattern[0], vec3( 1.0, 2.0, 4.0)) + - dot(pattern[1], vec3( 8.0, 0.0, 16.0)) + - dot(pattern[2], vec3(32.0, 64.0, 128.0)); + dot(pattern[1], vec3( 8.0, 0.0, 16.0)) + + dot(pattern[2], vec3(32.0, 64.0, 128.0)); index.y = dot(cross, vec4(1.0, 2.0, 4.0, 8.0)) * SCALE * SCALE + dot(floor(fp * vec2(SCALE, SCALE)), vec2(1.0, SCALE)); vec2 step = vec2(1.0, 1.0) / vec2(256.0, 16.0 * (SCALE * SCALE)); diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc index dcff07b17f5..727f5763857 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq2x.sc @@ -8,10 +8,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0 // Autos uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_color0 = a_color0; vec2 ps = vec2(1.0, 1.0) / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc index dcff07b17f5..727f5763857 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq3x.sc @@ -8,10 +8,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0 // Autos uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_color0 = a_color0; vec2 ps = vec2(1.0, 1.0) / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc index dcff07b17f5..727f5763857 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/hqx/vs_hq4x.sc @@ -8,10 +8,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0 // Autos uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_color0 = a_color0; vec2 ps = vec2(1.0, 1.0) / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc index 9ed2a47e801..801d1a2e9a4 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_lcd-grid.sc @@ -22,85 +22,85 @@ uniform vec4 u_subpixsize; vec3 fetch_offset(vec2 coord, vec2 offset) { - vec2 x = coord + offset; - vec3 col = texture2D(s_tex, x).rgb; - vec3 col2 = pow(vec3_splat(u_gain.x) * col + vec3_splat(u_blacklevel.x), vec3_splat(u_LCDgamma.x)) + vec3_splat(u_ambient.x); - // want zero for outside pixels - vec4 b = step(0.0,vec4(x.x,x.y,1.0-x.x,1.0-x.y)); - return vec3_splat(b.x*b.y*b.z*b.w) * col2; + vec2 x = coord + offset; + vec3 col = texture2D(s_tex, x).rgb; + vec3 col2 = pow(vec3_splat(u_gain.x) * col + vec3_splat(u_blacklevel.x), vec3_splat(u_LCDgamma.x)) + vec3_splat(u_ambient.x); + // want zero for outside pixels + vec4 b = step(0.0,vec4(x.x,x.y,1.0-x.x,1.0-x.y)); + return vec3_splat(b.x*b.y*b.z*b.w) * col2; } float intsmear_func(float z, float c1, float c2, float c3, float c4, float c5, float c6) { - float z2 = z*z; - // both cases have c0=1 - return z * (1.0 + z2*(c1 + z2*(c2 + z2*(c3 + z2*(c4 + z2*(c5 + z2*c6)))))); + float z2 = z*z; + // both cases have c0=1 + return z * (1.0 + z2*(c1 + z2*(c2 + z2*(c3 + z2*(c4 + z2*(c5 + z2*c6)))))); } float intsmear_fx(float z) { - // integral of (1 - x^2 - x^4 + x^6)^2 - return intsmear_func(z, -2.0/3.0, -1.0/5.0, 4.0/7.0, -1.0/9.0, -2.0/11.0, 1.0/13.0); + // integral of (1 - x^2 - x^4 + x^6)^2 + return intsmear_func(z, -2.0/3.0, -1.0/5.0, 4.0/7.0, -1.0/9.0, -2.0/11.0, 1.0/13.0); } float intsmear_fy(float z) { - // integral of (1 - 2x^4 + x^6)^2 - return intsmear_func(z, 0.0, -4.0/5.0, 2.0/7.0, 4.0/9.0, -4.0/11.0, 1.0/13.0); + // integral of (1 - 2x^4 + x^6)^2 + return intsmear_func(z, 0.0, -4.0/5.0, 2.0/7.0, 4.0/9.0, -4.0/11.0, 1.0/13.0); } float intsmear_x(float x, float dx, float d) { - float zl = clamp((x-dx*0.5)/d,-1.0,1.0); - float zh = clamp((x+dx*0.5)/d,-1.0,1.0); - return d * ( intsmear_fx(zh) - intsmear_fx(zl) )/dx; + float zl = clamp((x-dx*0.5)/d,-1.0,1.0); + float zh = clamp((x+dx*0.5)/d,-1.0,1.0); + return d * ( intsmear_fx(zh) - intsmear_fx(zl) )/dx; } float intsmear_y(float x, float dx, float d) { - float zl = clamp((x-dx*0.5)/d,-1.0,1.0); - float zh = clamp((x+dx*0.5)/d,-1.0,1.0); - return d * ( intsmear_fy(zh) - intsmear_fy(zl) )/dx; + float zl = clamp((x-dx*0.5)/d,-1.0,1.0); + float zh = clamp((x+dx*0.5)/d,-1.0,1.0); + return d * ( intsmear_fy(zh) - intsmear_fy(zl) )/dx; } void main() { - vec3 cr = pow(u_rsubpix.rgb, vec3_splat(u_monitorgamma.x)); - vec3 cg = pow(u_gsubpix.rgb, vec3_splat(u_monitorgamma.x)); - vec3 cb = pow(u_bsubpix.rgb, vec3_splat(u_monitorgamma.x)); - - vec2 tl = v_texcoord0 * u_tex_size0.xy - vec2(0.5,0.5); - vec2 tli = floor(tl); - float subpix = fract(tl.x) * 3.0; - float rsubpix = u_tex_size0.x / u_quad_dims.x * 3.0; - - vec3 lcol, rcol; - lcol = vec3(intsmear_x(subpix+1.0, rsubpix, 3.0*u_subpixsize.x), - intsmear_x(subpix , rsubpix, 3.0*u_subpixsize.x), - intsmear_x(subpix-1.0, rsubpix, 3.0*u_subpixsize.x)); - rcol = vec3(intsmear_x(subpix-2.0, rsubpix, 3.0*u_subpixsize.x), - intsmear_x(subpix-3.0, rsubpix, 3.0*u_subpixsize.x), - intsmear_x(subpix-4.0, rsubpix, 3.0*u_subpixsize.x)); - - if (u_BGR.x > 0.5) { - lcol.rgb = lcol.bgr; - rcol.rgb = rcol.bgr; - } - - float tcol, bcol; - subpix = fract(tl.y); - rsubpix = u_tex_size0.y / u_quad_dims.y; - tcol = intsmear_y(subpix ,rsubpix, u_subpixsize.y); - bcol = intsmear_y(subpix-1.0,rsubpix, u_subpixsize.y); - - tl = (tli + vec2_splat(0.5)) / u_tex_size0.xy; - vec2 one = vec2_splat(1.0) / u_tex_size0.xy; - - vec3 ul = fetch_offset(tl, vec2(0,0) ) * lcol * vec3_splat(tcol); - vec3 br = fetch_offset(tl, one ) * rcol * vec3_splat(bcol); - vec3 bl = fetch_offset(tl, vec2(0,one.y)) * lcol * vec3_splat(bcol); - vec3 ur = fetch_offset(tl, vec2(one.x,0)) * rcol * vec3_splat(tcol); - - vec3 csum = ul + br + bl + ur; - vec3 col = mul(mtxFromCols(u_rsubpix.rgb, u_gsubpix.rgb, u_bsubpix.rgb), csum); - gl_FragColor = vec4(pow(col, vec3_splat(1.0/u_monitorgamma.x)), 1.0); + vec3 cr = pow(u_rsubpix.rgb, vec3_splat(u_monitorgamma.x)); + vec3 cg = pow(u_gsubpix.rgb, vec3_splat(u_monitorgamma.x)); + vec3 cb = pow(u_bsubpix.rgb, vec3_splat(u_monitorgamma.x)); + + vec2 tl = v_texcoord0 * u_tex_size0.xy - vec2(0.5,0.5); + vec2 tli = floor(tl); + float subpix = fract(tl.x) * 3.0; + float rsubpix = u_tex_size0.x / u_quad_dims.x * 3.0; + + vec3 lcol, rcol; + lcol = vec3(intsmear_x(subpix+1.0, rsubpix, 3.0*u_subpixsize.x), + intsmear_x(subpix , rsubpix, 3.0*u_subpixsize.x), + intsmear_x(subpix-1.0, rsubpix, 3.0*u_subpixsize.x)); + rcol = vec3(intsmear_x(subpix-2.0, rsubpix, 3.0*u_subpixsize.x), + intsmear_x(subpix-3.0, rsubpix, 3.0*u_subpixsize.x), + intsmear_x(subpix-4.0, rsubpix, 3.0*u_subpixsize.x)); + + if (u_BGR.x > 0.5) { + lcol.rgb = lcol.bgr; + rcol.rgb = rcol.bgr; + } + + float tcol, bcol; + subpix = fract(tl.y); + rsubpix = u_tex_size0.y / u_quad_dims.y; + tcol = intsmear_y(subpix ,rsubpix, u_subpixsize.y); + bcol = intsmear_y(subpix-1.0,rsubpix, u_subpixsize.y); + + tl = (tli + vec2_splat(0.5)) / u_tex_size0.xy; + vec2 one = vec2_splat(1.0) / u_tex_size0.xy; + + vec3 ul = fetch_offset(tl, vec2(0,0) ) * lcol * vec3_splat(tcol); + vec3 br = fetch_offset(tl, one ) * rcol * vec3_splat(bcol); + vec3 bl = fetch_offset(tl, vec2(0,one.y)) * lcol * vec3_splat(bcol); + vec3 ur = fetch_offset(tl, vec2(one.x,0)) * rcol * vec3_splat(tcol); + + vec3 csum = ul + br + bl + ur; + vec3 col = mul(mtxFromCols(u_rsubpix.rgb, u_gsubpix.rgb, u_bsubpix.rgb), csum); + gl_FragColor = vec4(pow(col, vec3_splat(1.0/u_monitorgamma.x)), 1.0); } diff --git a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc index 0187b8c90d2..4c9e998d3ec 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/fs_persistence.sc @@ -9,8 +9,8 @@ uniform vec4 u_persistence; void main() { - vec4 screen = texture2D(s_screen , v_texcoord0); - vec4 motionblur = texture2D(s_motionblur, v_texcoord0); + vec4 screen = texture2D(s_screen , v_texcoord0); + vec4 motionblur = texture2D(s_motionblur, v_texcoord0); - gl_FragColor = mix(screen, motionblur, u_persistence.x); + gl_FragColor = mix(screen, motionblur, u_persistence.x); } diff --git a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_lcd-grid.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/lcd-grid/vs_persistence.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc index 3e58af492c6..090485da1bc 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass0.sc @@ -20,7 +20,7 @@ uniform vec4 DIFF_THRESH1; vec3 df3(vec3 c1, vec3 c2) { - return abs(c1 - c2); + return abs(c1 - c2); } bvec3 le3(vec3 A, vec3 B, vec3 param) diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc index 8fdd168a262..085f767358c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/fs_deposterize-pass1.sc @@ -20,7 +20,7 @@ uniform vec4 DIFF_THRESH2; vec3 df3(vec3 c1, vec3 c2) { - return abs(c1 - c2); + return abs(c1 - c2); } bvec3 le3(vec3 A, vec3 B, vec3 param) diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_blit.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_bob-and-ghost-deinterlace.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc index f46bf23b063..1ed054f1b9a 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass0.sc @@ -14,10 +14,14 @@ $output v_texcoord0, v_texcoord1, v_color0 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif vec2 ps = vec2(1.0 / u_tex_size0.xy); float dx = ps.x; diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc index 486edf97c5c..69a23cb477c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_deposterize-pass1.sc @@ -14,10 +14,14 @@ $output v_texcoord0, v_texcoord1, v_color0 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif vec2 ps = vec2(1.0 / u_tex_size0.xy); float dx = ps.x; diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_lut.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_resize_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_resize_blit.sc new file mode 100644 index 00000000000..0a9f2f178e1 --- /dev/null +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_resize_blit.sc @@ -0,0 +1,21 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "common.sh" + +uniform vec4 u_inv_view_dims; +uniform vec4 u_tex_bounds0; + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif + + v_texcoord0 = a_texcoord0 * (u_tex_bounds0.zw - u_tex_bounds0.xy) + u_tex_bounds0.xy; + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/misc/vs_saturation.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_gaussian.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc index f071beaaa26..77d392ad813 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_horizontal/vs_offset_sat.sc @@ -9,9 +9,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0 * vec2(0.16666666 * 0.9, 1.0 * 0.8) + vec2(0.1, 0.1); v_color0 = a_color0; -}
\ No newline at end of file +} diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_gaussian.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc index a9f6649c1e5..6d47076f992 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_left_vertical/vs_offset_sat.sc @@ -9,9 +9,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0 * vec2(1.0 * 0.8, 0.685185 * 0.9) + vec2(0.1, 0.1); v_color0 = a_color0; -}
\ No newline at end of file +} diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_gaussian.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc index a473bc4123c..403b880b5ec 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_horizontal/vs_offset_sat.sc @@ -9,9 +9,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0 * vec2(0.16666666 * 0.9, 1.0 * 0.8) + vec2(0.9 - 0.16666666 * 0.9, 0.1); v_color0 = a_color0; -}
\ No newline at end of file +} diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_gaussian.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc index 8af6a293d8e..7121ae6651c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/pillarbox_right_vertical/vs_offset_sat.sc @@ -9,9 +9,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { - gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0 * vec2(1.0 * 0.8, 0.685185 * 0.9) + vec2(0.1, 0.9 - 0.685185 * 0.9); v_color0 = a_color0; -}
\ No newline at end of file +} diff --git a/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc b/src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc index 9433c8359be..52e0fc2ae90 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/warp/vs_dilation-horizontal-fast.sc @@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_color0 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; @@ -45,7 +49,7 @@ void main() // D E F // H - v_texcoord1 = vec4(1.0 / u_tex_size0.xy, 0.0, 0.0); // F H + v_texcoord1 = vec4(1.0 / u_tex_size0.xy, 0.0, 0.0); // F H v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc index fdf14bd393b..fd9a2d72f94 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_custom-jinc2-sharper.sc @@ -18,11 +18,11 @@ uniform vec4 u_tex_size0; SAMPLER2D(s_p, 0); - /* - This is an approximation of Jinc(x)*Jinc(x*r1/r2) for x < 2.5, - where r1 and r2 are the first two zeros of jinc function. - For a jinc 2-lobe best approximation, use A=0.5 and B=0.825. - */ +/* + This is an approximation of Jinc(x)*Jinc(x*r1/r2) for x < 2.5, + where r1 and r2 are the first two zeros of jinc function. + For a jinc 2-lobe best approximation, use A=0.5 and B=0.825. +*/ // A=0.5, B=0.825 is the best jinc approximation for x<2.5. if B=1.0, it's a lanczos filter. // Increase A to get more blur. Decrease it to get a sharper picture. @@ -47,12 +47,12 @@ float d(vec2 pt1, vec2 pt2) vec4 min4(vec4 a, vec4 b, vec4 c, vec4 d) { - return min(a, min(b, min(c, d))); + return min(a, min(b, min(c, d))); } vec4 max4(vec4 a, vec4 b, vec4 c, vec4 d) { - return max(a, max(b, max(c, d))); + return max(a, max(b, max(c, d))); } vec4 resampler(vec4 x) diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc index 9e5520740c2..fdb38420261 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/fs_super-2xbr-3d-pass0.sc @@ -95,23 +95,23 @@ float hv_wd(float i1, float i2, float i3, float i4, float e1, float e2, float e3 vec4 min4(vec4 a, vec4 b, vec4 c, vec4 d) { - return min(a, min(b, min(c, d))); + return min(a, min(b, min(c, d))); } vec4 max4(vec4 a, vec4 b, vec4 c, vec4 d) { - return max(a, max(b, max(c, d))); + return max(a, max(b, max(c, d))); } void main() { //Skip pixels on wrong grid vec2 fraction = fract(v_texcoord0 * u_tex_size0.xy / XBR_RES); - if (fraction.x < 0.5 || fraction.y < 0.5) - { - gl_FragColor = texture2D(s0, v_texcoord0); - return; - } + if (fraction.x < 0.5 || fraction.y < 0.5) + { + gl_FragColor = texture2D(s0, v_texcoord0); + return; + } vec2 tex = (floor(v_texcoord0 * u_tex_size0.xy / XBR_RES) + vec2(0.5, 0.5)) * XBR_RES / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_custom-jinc2-sharper.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass0.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass1.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc index 1c3ee6a8f23..335c9ef8b4c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-2xbr-3d-pass2.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass0.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc index c5bd41ee120..338cadbe4b7 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass1f.sc @@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass2.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc index c5bd41ee120..338cadbe4b7 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-4xbr-3d-pass3f.sc @@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc index 5827f1999b8..21e16b595e4 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass0.sc @@ -32,9 +32,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc index 60637684154..fc33723ec9d 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass1.sc @@ -32,9 +32,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc index 2cfe541e2b8..a8ec5539c0b 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-fast-pass2.sc @@ -32,9 +32,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc index d10c9c24665..8352137204e 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass0.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc index 5827f1999b8..21e16b595e4 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass1.sc @@ -32,9 +32,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc index 9ae87c8a7ea..8f2d3277665 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass2.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc index 9ae87c8a7ea..8f2d3277665 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/super-xbr/vs_super-xbr-pass3.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_color #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc index 3e97446a880..de23993d020 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv1-noblend.sc @@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_color0 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc index a3bb4330f45..7992b9eee51 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-3d.sc @@ -9,10 +9,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco uniform vec4 XBR_RES; uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = XBR_RES.xx / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc index 38e92865308..48e9664b766 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-fast.sc @@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_color0 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc index cfc1a7cfc47..5bcf3e31f5a 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2-noblend.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc index ce6e411b75d..22e993426ed 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv2.sc @@ -7,10 +7,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc index 114f1669ad1..5957004443c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3-noblend.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc index 3d72da14478..a5ee8cee547 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/vs_xbr-lv3.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc index c09b7b66d1c..35cc742cff1 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-sharp.sc @@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc index 2be09e52908..3a9b0e56b1c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2-gamma.sc @@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc index 2ec42c6585d..c08e3988e24 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v2.sc @@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc index f40310aa1b9..8c2b0aec4cd 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4-gamma.sc @@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc index e363aba2eb4..d7328857ffd 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4.sc @@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc index 8f9c58be4c1..48ebe4f0a54 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v4b.sc @@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc index f40310aa1b9..8c2b0aec4cd 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid-v5-gamma.sc @@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc index c09b7b66d1c..35cc742cff1 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-hybrid/vs_2xbr-hybrid.sc @@ -43,10 +43,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; vec2 ps = 1.0 / u_tex_size0.xy; diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc index 59ffb0a026a..15490257390 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-a-pass0.sc @@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc index 5c20062823a..f63eb7b2391 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass0.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc index fbb10ec9ea5..db8c513319b 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-accuracy-pass1.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_color0 #include "common.sh" uniform vec4 u_tex_size1; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc index afdcf872331..0c317f16cc7 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-b-pass0.sc @@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc index ba0da15a70d..fbcf72fd706 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-c-pass0.sc @@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc index bfd5e4a6414..e75cc78ac8c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-d-pass0.sc @@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc index b85cca1828d..56cebbd6540 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-noblend-pass1.sc @@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_color0 #include "common.sh" uniform vec4 u_tex_size1; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc index 11042eab09a..c35e62e81ac 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv2-multipass/vs_xbr-lv2-pass1.sc @@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_color0 #include "common.sh" uniform vec4 u_tex_size1; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc index 4331c2353f6..229f2f93936 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/fs_xbr-lv3-pass0.sc @@ -120,7 +120,7 @@ vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, v LEFT = UP = LEFT3 = UP3 = 0.0; \ PX0 = vec2(0.0, PX); \ LIN0 = vec4(0.0, 0.0, 0.0, 0.0); \ - } \ + } diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc index 80dd11d7ad9..8ae8f8df41c 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass0.sc @@ -34,10 +34,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc index 7932ba25f15..439005d2941 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-lv3-multipass/vs_xbr-lv3-pass1.sc @@ -32,10 +32,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_color0 uniform vec4 u_tex_size1; uniform vec4 u_target_dims; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A3 B3 C3 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc index c37c512a7f6..bdd9f5b31db 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/fs_xbr-mlv4-pass4.sc @@ -110,7 +110,7 @@ vec3 color_mix(vec3 c, vec3 color, vec3 E) ax.x = round(info); \ iq.x = dot(ax, bin) - 2.0; \ iq.y = dot(ay, bin) - 2.0; \ - PIXEL = texture2D(ORIG_texture, v_texcoord0 + iq.x * v_texcoord1.xy + iq.y * v_texcoord1.zw).xyz; \ + PIXEL = texture2D(ORIG_texture, v_texcoord0 + iq.x * v_texcoord1.xy + iq.y * v_texcoord1.zw).xyz; void main() diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc index 1edfd8632ad..24f3b396cc2 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass1.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_color0 #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A3 B3 C3 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc index 92cf6b60b87..1d67bb87ebe 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass2.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4, v_texco #include "common.sh" uniform vec4 u_tex_size0; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A1 B1 C1 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc index a6926a41f8b..2c85859340b 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass3.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_color0 #include "common.sh" uniform vec4 u_tex_size1; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A3 B3 C3 diff --git a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc index 29fec2f1759..5e62a75a12e 100644 --- a/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc +++ b/src/osd/modules/render/bgfx/shaders/chains/xbr/xbr-mlv4-multipass/vs_xbr-mlv4-pass4.sc @@ -33,10 +33,14 @@ $output v_texcoord0, v_texcoord1, v_color0 #include "common.sh" uniform vec4 u_tex_size1; +uniform vec4 u_inv_view_dims; void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; // A3 B3 C3 diff --git a/src/osd/modules/render/bgfx/shaders/vs_gui.sc b/src/osd/modules/render/bgfx/shaders/vs_gui.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/vs_gui.sc +++ b/src/osd/modules/render/bgfx/shaders/vs_gui.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/shaders/vs_screen.sc b/src/osd/modules/render/bgfx/shaders/vs_screen.sc index 405ef8feb3b..df2b37f203c 100644 --- a/src/osd/modules/render/bgfx/shaders/vs_screen.sc +++ b/src/osd/modules/render/bgfx/shaders/vs_screen.sc @@ -6,9 +6,14 @@ $output v_texcoord0, v_color0 #include "common.sh" +uniform vec4 u_inv_view_dims; + void main() { gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); +#if BGFX_SHADER_LANGUAGE_HLSL && BGFX_SHADER_LANGUAGE_HLSL <= 300 + gl_Position.xy += u_inv_view_dims.xy * gl_Position.w; +#endif v_texcoord0 = a_texcoord0; v_color0 = a_color0; } diff --git a/src/osd/modules/render/bgfx/slider.cpp b/src/osd/modules/render/bgfx/slider.cpp index 452c934fd37..dcd64c0c865 100644 --- a/src/osd/modules/render/bgfx/slider.cpp +++ b/src/osd/modules/render/bgfx/slider.cpp @@ -11,8 +11,10 @@ #include "strformat.h" -bgfx_slider::bgfx_slider(running_machine &machine, std::string name, float min, float def, float max, float step, slider_type type, screen_type screen, std::string format, std::string description, std::vector<std::string>& strings) - : m_name(name) +#include <utility> + +bgfx_slider::bgfx_slider(running_machine &machine, std::string &&name, float min, float def, float max, float step, slider_type type, screen_type screen, std::string format, std::string description, std::vector<std::string>& strings) + : m_name(std::move(name)) , m_step(step) , m_type(type) , m_screen_type(screen) diff --git a/src/osd/modules/render/bgfx/slider.h b/src/osd/modules/render/bgfx/slider.h index d7815765c34..89a713da4b3 100644 --- a/src/osd/modules/render/bgfx/slider.h +++ b/src/osd/modules/render/bgfx/slider.h @@ -6,14 +6,15 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_SLIDER_H +#define MAME_RENDER_BGFX_SLIDER_H -#ifndef __DRAWBGFX_SLIDER__ -#define __DRAWBGFX_SLIDER__ +#pragma once #include <bgfx/bgfx.h> #include <cmath> +#include <cstdint> #include <memory> #include <string> #include <vector> @@ -46,16 +47,19 @@ public: SLIDER_SCREEN_TYPE_ANY = SLIDER_SCREEN_TYPE_RASTER | SLIDER_SCREEN_TYPE_VECTOR | SLIDER_SCREEN_TYPE_LCD }; - bgfx_slider(running_machine& machine, std::string name, float min, float def, float max, float step, slider_type type, screen_type screen, std::string format, std::string description, std::vector<std::string>& strings); + bgfx_slider(running_machine& machine, std::string &&name, float min, float def, float max, float step, slider_type type, screen_type screen, std::string format, std::string description, std::vector<std::string>& strings); virtual ~bgfx_slider(); int32_t update(std::string *str, int32_t newval); // Getters - std::string name() const { return m_name; } + const 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); } + float min_value() const { return m_min; } + float default_value() const { return m_default; } + float max_value() const { return m_max; } slider_state *core_slider() const { return m_slider_state.get(); } size_t size() const { return get_size_for_type(m_type); } static size_t get_size_for_type(slider_type type); @@ -82,4 +86,4 @@ protected: running_machine&m_machine; }; -#endif // __DRAWBGFX_SLIDER__ +#endif // MAME_RENDER_BGFX_SLIDER_H diff --git a/src/osd/modules/render/bgfx/sliderreader.cpp b/src/osd/modules/render/bgfx/sliderreader.cpp index 208bc241559..96ff2511c96 100644 --- a/src/osd/modules/render/bgfx/sliderreader.cpp +++ b/src/osd/modules/render/bgfx/sliderreader.cpp @@ -33,7 +33,7 @@ const slider_reader::string_to_enum slider_reader::SCREEN_NAMES[slider_reader::S { "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, chain_manager& chains, uint32_t screen_index) +std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, uint32_t screen_index) { std::vector<bgfx_slider*> sliders; @@ -55,7 +55,7 @@ std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, std const Value& string_array = value["strings"]; for (uint32_t 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())) + if (!READER_CHECK(string_array[i].IsString(), "%sSlider '%s': strings[%u]: must be a string\n", prefix, name, i)) { return sliders; } @@ -82,18 +82,22 @@ std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, std break; } - std::string prefixed_desc = "Window " + std::to_string(chains.window_index()) + ", Screen " + std::to_string(screen_index) + ", " + description; + std::string prefixed_desc = util::string_format("Window %1$u, Screen %2$u, %3$s", chains.window_index(), screen_index, description); if (slider_count > 1) { + if (!READER_CHECK(value["min"].IsArray(), "%1$sSlider '%2$s': value 'min' must be an array", prefix, name)) + return sliders; + if (!READER_CHECK(value["default"].IsArray(), "%1$sSlider '%2$s': value 'default' must be an array", prefix, name)) + return sliders; + if (!READER_CHECK(value["max"].IsArray(), "%1$sSlider '%2$s': value 'max' must be an array", prefix, name)) + return sliders; + float min[3]; float defaults[3]; float 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); + get_values(value, util::string_format("%1$sSlider '%2$s': 'min': ", prefix, name), "min", min, slider_count); + get_values(value, util::string_format("%1$sSlider '%2$s': 'default': ", prefix, name), "default", defaults, slider_count); + get_values(value, util::string_format("%1$sSlider '%2$s': 'max': ", prefix, name), "max", max, slider_count); for (int index = 0; index < slider_count; index++) { std::string desc; @@ -113,51 +117,50 @@ std::vector<bgfx_slider*> slider_reader::read_from_value(const Value& value, std desc = prefixed_desc + "Invalid"; break; } - sliders.push_back(new bgfx_slider(chains.machine(), full_name, min[index], defaults[index], max[index], step, type, screen_type, format, desc, strings)); + sliders.push_back(new bgfx_slider(chains.machine(), std::move(full_name), min[index], defaults[index], max[index], step, type, screen_type, format, desc, strings)); } } else { - float min = get_float(value, "min", 0.0f); - float def = get_float(value, "default", 0.0f); - float max = get_float(value, "max", 1.0f); + const float min = get_float(value, "min", 0.0f); + const float def = get_float(value, "default", 0.0f); + const float max = get_float(value, "max", 1.0f); sliders.push_back(new bgfx_slider(chains.machine(), name + "0", min, def, max, step, type, screen_type, format, prefixed_desc, strings)); } return sliders; } -bool slider_reader::get_values(const Value& value, std::string prefix, std::string name, float* values, const int count) +bool slider_reader::get_values(const Value& value, const std::string &prefix, const std::string &name, float* values, const int count) { - const char* name_str = name.c_str(); - const Value& value_array = value[name_str]; + const Value& value_array = value[name.c_str()]; for (uint32_t i = 0; i < value_array.Size() && i < count; i++) { - if (!READER_CHECK(value_array[i].IsNumber(), (prefix + "Entry " + std::to_string(i) + " must be a number\n").c_str())) return false; + if (!READER_CHECK(value_array[i].IsNumber(), "%sEntry %u must be a number\n", prefix, i)) return false; values[i] = value_array[i].GetFloat(); } return true; } -bool slider_reader::validate_parameters(const Value& value, std::string prefix) +bool slider_reader::validate_parameters(const Value& value, const 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("min"), (prefix + "Must have a number or array value 'min'\n").c_str())) return false; - if (!READER_CHECK(value["min"].IsNumber() || value["min"].IsArray(), (prefix + "Value 'min' must be a number or an array the size of the corresponding slider type\n").c_str())) return false; - if (!READER_CHECK(value.HasMember("default"), (prefix + "Must have a number or array value 'default'\n").c_str())) return false; - if (!READER_CHECK(value["default"].IsNumber() || value["default"].IsArray(), (prefix + "Value 'default' must be a number or an array the size of the corresponding slider type\n").c_str())) return false; - if (!READER_CHECK(value.HasMember("max"), (prefix + "Must have a number or array value 'max'\n").c_str())) return false; - if (!READER_CHECK(value["max"].IsNumber() || value["max"].IsArray(), (prefix + "Value 'max' must be a number or an array the size of the corresponding slider type\n").c_str())) return false; - if (!READER_CHECK(value.HasMember("step"), (prefix + "Must have a number value 'step'\n").c_str())) return false; - if (!READER_CHECK(value["step"].IsNumber(), (prefix + "Value 'step' must be a number (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("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; + if (!READER_CHECK(value.HasMember("name"), "%1$sMust have string value 'name'", prefix)) return false; + if (!READER_CHECK(value["name"].IsString(), "%1$sValue 'name' must be a string", prefix)) return false; + if (!READER_CHECK(value.HasMember("min"), "%1$sMust have a number or array value 'min'", prefix)) return false; + if (!READER_CHECK(value["min"].IsNumber() || value["min"].IsArray(), "%1$sValue 'min' must be a number or an array the size of the corresponding slider type", prefix)) return false; + if (!READER_CHECK(value.HasMember("default"), "%1$sMust have a number or array value 'default'", prefix)) return false; + if (!READER_CHECK(value["default"].IsNumber() || value["default"].IsArray(), "%1$sValue 'default' must be a number or an array the size of the corresponding slider type", prefix)) return false; + if (!READER_CHECK(value.HasMember("max"), "%1$sMust have a number or array value 'max'", prefix)) return false; + if (!READER_CHECK(value["max"].IsNumber() || value["max"].IsArray(), "%1$sValue 'max' must be a number or an array the size of the corresponding slider type", prefix)) return false; + if (!READER_CHECK(value.HasMember("step"), "%1$sMust have a number value 'step'", prefix)) return false; + if (!READER_CHECK(value["step"].IsNumber(), "%1$sValue 'step' must be a number (how much does this slider increment by internally?)", prefix)) return false; + if (!READER_CHECK(value.HasMember("type"), "%1$sMust have string value 'type'", prefix)) return false; + if (!READER_CHECK(value["type"].IsString(), "%1$sValue 'type' must be a string (what type of slider is this? [int_enum, int, float])", prefix)) return false; + if (!READER_CHECK(value.HasMember("screen"), "%1$sMust have string value 'screen'", prefix)) return false; + if (!READER_CHECK(value["screen"].IsString(), "%1$sValue 'screen' must be a string (what type of output device does this slider apply to? [none, raster, vector, crt, lcd, non_vector, any])", prefix)) return false; + if (!READER_CHECK(value.HasMember("format"), "%1$sMust have string value 'format'", prefix)) return false; + if (!READER_CHECK(value["format"].IsString(), "%1$sValue 'scale' must be a string (how would we display it in a printf?)", prefix)) return false; + if (!READER_CHECK(value.HasMember("text"), "%1$sMust have string value 'text'", prefix)) return false; + if (!READER_CHECK(value["text"].IsString(), "%1$sValue 'text' must be a string (how would you explain it?)", prefix)) return false; + if (!READER_CHECK(!value.HasMember("strings") || value["strings"].IsArray(), "%1$sValue 'strings' must be an array", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/sliderreader.h b/src/osd/modules/render/bgfx/sliderreader.h index 95c6872e171..dc905472cc8 100644 --- a/src/osd/modules/render/bgfx/sliderreader.h +++ b/src/osd/modules/render/bgfx/sliderreader.h @@ -6,26 +6,26 @@ // //============================================================ +#ifndef MAME_RENDER_BGFX_SLIDERREADER_H +#define MAME_RENDER_BGFX_SLIDERREADER_H + #pragma once -#ifndef __DRAWBGFX_SLIDER_READER__ -#define __DRAWBGFX_SLIDER_READER__ +#include "statereader.h" #include <vector> -#include "statereader.h" - class bgfx_slider; class chain_manager; class slider_reader : public state_reader { public: - static std::vector<bgfx_slider*> read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index); + static std::vector<bgfx_slider*> read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, uint32_t screen_index); private: - static bool get_values(const Value& value, std::string prefix, std::string name, float* values, const int count); - static bool validate_parameters(const Value& value, std::string prefix); + static bool get_values(const Value& value, const std::string &prefix, const std::string &name, float* values, const int count); + static bool validate_parameters(const Value& value, const std::string &prefix); static const int TYPE_COUNT = 5; static const string_to_enum TYPE_NAMES[TYPE_COUNT]; @@ -33,4 +33,4 @@ private: static const string_to_enum SCREEN_NAMES[SCREEN_COUNT]; }; -#endif // __DRAWBGFX_SLIDER_READER__ +#endif // MAME_RENDER_BGFX_SLIDERREADER_H diff --git a/src/osd/modules/render/bgfx/slideruniform.cpp b/src/osd/modules/render/bgfx/slideruniform.cpp index 7a63b1e6901..bc116f51ff1 100644 --- a/src/osd/modules/render/bgfx/slideruniform.cpp +++ b/src/osd/modules/render/bgfx/slideruniform.cpp @@ -13,13 +13,12 @@ #include "slider.h" -bgfx_slider_uniform::bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> sliders) +#include <utility> + +bgfx_slider_uniform::bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> &&sliders) : bgfx_entry_uniform(uniform) + , m_sliders(std::move(sliders)) { - for (bgfx_slider* slider : sliders) - { - m_sliders.push_back(slider); - } } void bgfx_slider_uniform::bind() diff --git a/src/osd/modules/render/bgfx/slideruniform.h b/src/osd/modules/render/bgfx/slideruniform.h index a2fa990dd1f..a08d2fb503d 100644 --- a/src/osd/modules/render/bgfx/slideruniform.h +++ b/src/osd/modules/render/bgfx/slideruniform.h @@ -9,10 +9,10 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_SLIDERUNIFORM_H +#define MAME_RENDER_BGFX_SLIDERUNIFORM_H -#ifndef __DRAWBGFX_SLIDER_UNIFORM__ -#define __DRAWBGFX_SLIDER_UNIFORM__ +#pragma once #include "entryuniform.h" @@ -23,7 +23,7 @@ class bgfx_slider; class bgfx_slider_uniform : public bgfx_entry_uniform { public: - bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> sliders); + bgfx_slider_uniform(bgfx_uniform* uniform, std::vector<bgfx_slider*> &&sliders); virtual void bind() override; @@ -31,4 +31,4 @@ private: std::vector<bgfx_slider*> m_sliders; }; -#endif // __DRAWBGFX_SLIDER_UNIFORM__ +#endif // MAME_RENDER_BGFX_SLIDERUNIFORM_H diff --git a/src/osd/modules/render/bgfx/slideruniformreader.cpp b/src/osd/modules/render/bgfx/slideruniformreader.cpp index 314cff0b78b..3fdeb0b21e6 100644 --- a/src/osd/modules/render/bgfx/slideruniformreader.cpp +++ b/src/osd/modules/render/bgfx/slideruniformreader.cpp @@ -8,13 +8,13 @@ #include "slideruniformreader.h" -#include <vector> - -#include "slideruniform.h" #include "entryuniform.h" #include "slider.h" +#include "slideruniform.h" + +#include <vector> -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) +bgfx_entry_uniform* slider_uniform_reader::read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_slider*>& sliders) { if (!validate_parameters(value, prefix)) { @@ -35,12 +35,12 @@ bgfx_entry_uniform* slider_uniform_reader::read_from_value(const Value& value, s slider_list.push_back(sliders[name + "2"]); } - return new bgfx_slider_uniform(uniform, slider_list); + return new bgfx_slider_uniform(uniform, std::move(slider_list)); } -bool slider_uniform_reader::validate_parameters(const Value& value, std::string prefix) +bool slider_uniform_reader::validate_parameters(const Value& value, const 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; + if (!READER_CHECK(value.HasMember("slider"), "%sMust have string value 'slider' (what slider are we getting the value of?)\n", prefix)) return false; + if (!READER_CHECK(value["slider"].IsString(), "%sValue 'slider' must be a string\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/slideruniformreader.h b/src/osd/modules/render/bgfx/slideruniformreader.h index 0db387270b0..f39e7fc2fd8 100644 --- a/src/osd/modules/render/bgfx/slideruniformreader.h +++ b/src/osd/modules/render/bgfx/slideruniformreader.h @@ -6,27 +6,27 @@ // //================================================================ +#ifndef MAME_RENDER_BGFX_SLIDERUNIFORMREADER_H +#define MAME_RENDER_BGFX_SLIDERUNIFORMREADER_H + #pragma once -#ifndef __DRAWBGFX_SLIDER_UNIFORM_READER__ -#define __DRAWBGFX_SLIDER_UNIFORM_READER__ +#include "entryuniform.h" +#include "statereader.h" #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); + static bgfx_entry_uniform* read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform, std::map<std::string, bgfx_slider*>& sliders); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); }; -#endif // __DRAWBGFX_SLIDER_UNIFORM_READER__ +#endif // MAME_RENDER_BGFX_SLIDERUNIFORMREADER_H diff --git a/src/osd/modules/render/bgfx/statereader.cpp b/src/osd/modules/render/bgfx/statereader.cpp index acaeddd35b5..277e6815185 100644 --- a/src/osd/modules/render/bgfx/statereader.cpp +++ b/src/osd/modules/render/bgfx/statereader.cpp @@ -13,17 +13,20 @@ #include <cmath> -bool state_reader::READER_CHECK(bool condition, const char* format, ...) + +bool state_reader::V_READER_CHECK(bool condition, const util::format_argument_pack<char> &args) { 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); - } + osd_printf_error("Error: %s\n", util::string_format(args)); + + return condition; +} + +bool state_reader::V_READER_WARN(bool condition, const util::format_argument_pack<char> &args) +{ + if (!condition) + osd_printf_warning("Warning: %s\n", util::string_format(args)); + return condition; } @@ -117,7 +120,7 @@ float state_reader::get_float(const Value& value, const std::string name, const { if (value.HasMember(name.c_str())) { - return (float)value[name.c_str()].GetDouble(); + return float(value[name.c_str()].GetDouble()); } return default_value; } @@ -128,7 +131,7 @@ void state_reader::get_float(const Value& value, const std::string name, float* { if (count == 1) { - *out = (float) value[name.c_str()].GetDouble(); + *out = float(value[name.c_str()].GetDouble()); return; } else @@ -146,7 +149,7 @@ void state_reader::get_vec_values(const Value& value_array, float* data, const u { for (unsigned int i = 0; i < count && i < value_array.Size(); i++) { - data[i] = (float) value_array[i].GetDouble(); + data[i] = float(value_array[i].GetDouble()); } } diff --git a/src/osd/modules/render/bgfx/statereader.h b/src/osd/modules/render/bgfx/statereader.h index 43596bf4e94..69a795d9f04 100644 --- a/src/osd/modules/render/bgfx/statereader.h +++ b/src/osd/modules/render/bgfx/statereader.h @@ -7,16 +7,19 @@ // //================================================================ +#ifndef MAME_RENDER_BGFX_STATEREADER_H +#define MAME_RENDER_BGFX_STATEREADER_H + #pragma once -#ifndef DRAWBGFX_STATE_READER -#define DRAWBGFX_STATE_READER +#include "util/strformat.h" #include <rapidjson/document.h> #include <cstdint> #include <string> + using namespace rapidjson; class state_reader @@ -44,10 +47,22 @@ protected: 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, ...); + template <typename Format, typename... Params> + static bool READER_CHECK(bool condition, Format &&fmt, Params &&... args) + { + return V_READER_CHECK(condition, util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...)); + } + + template <typename Format, typename... Params> + static bool READER_WARN(bool condition, Format &&fmt, Params &&... args) + { + return V_READER_WARN(condition, util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...)); + } private: + static bool V_READER_CHECK(bool condition, const util::format_argument_pack<char> &args); + static bool V_READER_WARN(bool condition, const util::format_argument_pack<char> &args); static void get_vec_values(const Value& value_array, float* data, const unsigned int count); }; -#endif // DRAWBGFX_STATE_READER +#endif // MAME_RENDER_BGFX_STATEREADER_H diff --git a/src/osd/modules/render/bgfx/suppressor.cpp b/src/osd/modules/render/bgfx/suppressor.cpp index 83dd403adf7..8ffb4be6d66 100644 --- a/src/osd/modules/render/bgfx/suppressor.cpp +++ b/src/osd/modules/render/bgfx/suppressor.cpp @@ -13,13 +13,13 @@ #include <cstring> -bgfx_suppressor::bgfx_suppressor(std::vector<bgfx_slider*> sliders, uint32_t condition, combine_mode combine, void* value) - : m_sliders(sliders) +bgfx_suppressor::bgfx_suppressor(std::vector<bgfx_slider*> &&sliders, uint32_t condition, combine_mode combine, void* value) + : m_sliders(std::move(sliders)) , m_condition(condition) , m_combine(combine) , m_value(nullptr) { - uint32_t size = sliders[0]->size(); + uint32_t size = m_sliders[0]->size(); m_value = new uint8_t[size]; memcpy(m_value, value, size); } diff --git a/src/osd/modules/render/bgfx/suppressor.h b/src/osd/modules/render/bgfx/suppressor.h index 343a621b72d..00276fbb398 100644 --- a/src/osd/modules/render/bgfx/suppressor.h +++ b/src/osd/modules/render/bgfx/suppressor.h @@ -7,10 +7,10 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_SUPPRESSOR_H +#define MAME_RENDER_BGFX_SUPPRESSOR_H -#ifndef __DRAWBGFX_SUPPRESSOR__ -#define __DRAWBGFX_SUPPRESSOR__ +#pragma once #include <bgfx/bgfx.h> @@ -34,7 +34,7 @@ public: COMBINE_OR }; - bgfx_suppressor(std::vector<bgfx_slider*> sliders, uint32_t condition, combine_mode combine, void* value); + bgfx_suppressor(std::vector<bgfx_slider*> &&sliders, uint32_t condition, combine_mode combine, void* value); ~bgfx_suppressor(); // Getters @@ -48,4 +48,4 @@ private: uint8_t* m_value; }; -#endif // __DRAWBGFX_SUPPRESSOR__ +#endif // MAME_RENDER_BGFX_SUPPRESSOR_H diff --git a/src/osd/modules/render/bgfx/suppressorreader.cpp b/src/osd/modules/render/bgfx/suppressorreader.cpp index d7eb2b21fb8..353b79ad9bf 100644 --- a/src/osd/modules/render/bgfx/suppressorreader.cpp +++ b/src/osd/modules/render/bgfx/suppressorreader.cpp @@ -21,7 +21,7 @@ const suppressor_reader::string_to_enum suppressor_reader::COMBINE_NAMES[suppres { "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) +bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, const std::string &prefix, std::map<std::string, bgfx_slider*>& sliders) { if (!validate_parameters(value, prefix)) { @@ -58,7 +58,7 @@ bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, std::str 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; + if (!READER_CHECK(slider_count == value["value"].GetArray().Size(), "%sExpected %d values, got %u\n", prefix, slider_count, value["value"].GetArray().Size())) return nullptr; for (int index = 1; index < slider_count; index++) { check_sliders.push_back(sliders[name + std::to_string(index)]); @@ -69,26 +69,25 @@ bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, std::str values[0] = get_int(value, "value", 0); } - return new bgfx_suppressor(check_sliders, condition, mode, values); + return new bgfx_suppressor(std::move(check_sliders), condition, mode, values); } -bool suppressor_reader::validate_parameters(const Value& value, std::string prefix) +bool suppressor_reader::validate_parameters(const Value& value, const std::string &prefix) { - if (!READER_CHECK(value["type"].IsString(), (prefix + "Value 'type' must be a string\n").c_str())) return false; - 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; + if (!READER_CHECK(value["type"].IsString(), "%sValue 'type' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name'\n", prefix)) return false; + if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("value"), "%sMust have numeric or array value 'value'\n", prefix)) return false; + if (!READER_CHECK(value["value"].IsNumber() || value["value"].IsArray(), "%sValue 'value' must be a number or array the size of the corresponding slider type\n", prefix)) 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]; + const Value& value_array = value[name.c_str()]; for (uint32_t 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; + if (!READER_CHECK(value_array[i].IsInt(), "%svalue[%u] must be an integer\n", prefix, i)) 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 index cf7d641997c..23855134c51 100644 --- a/src/osd/modules/render/bgfx/suppressorreader.h +++ b/src/osd/modules/render/bgfx/suppressorreader.h @@ -6,10 +6,10 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_SUPPRESSORREADER_H +#define MAME_RENDER_BGFX_SUPPRESSORREADER_H -#ifndef __DRAWBGFX_SUPPRESSOR_READER__ -#define __DRAWBGFX_SUPPRESSOR_READER__ +#pragma once #include "statereader.h" @@ -22,11 +22,11 @@ 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); + static bgfx_suppressor* read_from_value(const Value& value, const 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 bool validate_parameters(const Value& value, const std::string &prefix); static const int CONDITION_COUNT = 2; static const string_to_enum CONDITION_NAMES[CONDITION_COUNT]; @@ -34,4 +34,4 @@ private: static const string_to_enum COMBINE_NAMES[COMBINE_COUNT]; }; -#endif // __DRAWBGFX_SUPPRESSOR_READER__ +#endif // MAME_RENDER_BGFX_SUPPRESSORREADER_H diff --git a/src/osd/modules/render/bgfx/target.cpp b/src/osd/modules/render/bgfx/target.cpp index f900f4f99fb..dd9169cb6cd 100644 --- a/src/osd/modules/render/bgfx/target.cpp +++ b/src/osd/modules/render/bgfx/target.cpp @@ -10,13 +10,16 @@ #include "target.h" -bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen) +bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint16_t xprescale, uint16_t yprescale, + uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen) : m_name(name) , m_format(format) , m_targets(nullptr) , m_textures(nullptr) , m_width(width) , m_height(height) + , m_xprescale(xprescale) + , m_yprescale(yprescale) , m_double_buffer(double_buffer) , m_style(style) , m_filter(filter) @@ -39,10 +42,10 @@ bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uin m_targets = new bgfx::FrameBufferHandle[m_page_count]; for (int page = 0; page < m_page_count; page++) { - m_textures[page] = bgfx::createTexture2D(m_width, m_height, false, 1, format, wrap_mode | filter_mode | BGFX_TEXTURE_RT); + m_textures[page] = bgfx::createTexture2D(m_width * xprescale, m_height * yprescale, false, 1, format, wrap_mode | filter_mode | BGFX_TEXTURE_RT); assert(m_textures[page].idx != 0xffff); - m_textures[m_page_count + page] = bgfx::createTexture2D(m_width, m_height, false, 1, bgfx::TextureFormat::D32F, depth_flags | BGFX_TEXTURE_RT); + m_textures[m_page_count + page] = bgfx::createTexture2D(m_width * xprescale, m_height * yprescale, false, 1, bgfx::TextureFormat::D32F, depth_flags | BGFX_TEXTURE_RT); assert(m_textures[m_page_count + page].idx != 0xffff); bgfx::TextureHandle handles[2] = { m_textures[page], m_textures[m_page_count + page] }; @@ -62,6 +65,8 @@ bgfx_target::bgfx_target(void *handle, uint16_t width, uint16_t height) , m_textures(nullptr) , m_width(width) , m_height(height) + , m_xprescale(1) + , m_yprescale(1) , m_double_buffer(false) , m_style(TARGET_STYLE_CUSTOM) , m_filter(false) diff --git a/src/osd/modules/render/bgfx/target.h b/src/osd/modules/render/bgfx/target.h index c00fc669337..5b979373971 100644 --- a/src/osd/modules/render/bgfx/target.h +++ b/src/osd/modules/render/bgfx/target.h @@ -27,7 +27,8 @@ enum class bgfx_target : public bgfx_texture_handle_provider { public: - bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen); + bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint16_t xprescale, uint16_t yprescale, + uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen); bgfx_target(void *handle, uint16_t width, uint16_t height); virtual ~bgfx_target(); @@ -42,13 +43,16 @@ public: bool filter() const { return m_filter; } uint16_t scale() const { return m_scale; } uint32_t screen_index() const { return m_screen; } + uint16_t raw_width() const { return m_width; } + uint16_t raw_height() const { return m_height; } // bgfx_texture_handle_provider virtual bgfx::TextureHandle texture() const override; virtual bool is_target() const override { return true; } - virtual uint16_t width() const override { return m_width; } - virtual uint16_t height() const override { return m_height; } - virtual uint16_t rowpixels() const override { return m_width; } + virtual uint16_t width() const override { return m_width * m_xprescale; } + virtual uint16_t width_margin() const override { return 0; } + virtual uint16_t height() const override { return m_height * m_yprescale; } + virtual uint16_t rowpixels() const override { return m_width * m_xprescale; } virtual int width_div_factor() const override { return 1; } virtual int width_mul_factor() const override { return 1; } @@ -62,6 +66,8 @@ private: uint16_t m_width; uint16_t m_height; + uint16_t m_xprescale; + uint16_t m_yprescale; bool m_double_buffer; uint32_t m_style; diff --git a/src/osd/modules/render/bgfx/targetmanager.cpp b/src/osd/modules/render/bgfx/targetmanager.cpp index dfd5b2adbd1..eae09c48008 100644 --- a/src/osd/modules/render/bgfx/targetmanager.cpp +++ b/src/osd/modules/render/bgfx/targetmanager.cpp @@ -9,15 +9,15 @@ // //============================================================ -#include <bgfx/bgfx.h> +#include "targetmanager.h" -#include <vector> +#include "bgfxutil.h" +#include "target.h" #include "modules/lib/osdobj_common.h" -#include "targetmanager.h" +#include <utility> -#include "target.h" const int32_t target_manager::MAX_SCREENS = 100; @@ -29,100 +29,106 @@ target_manager::target_manager(texture_manager& textures) target_manager::~target_manager() { - std::vector<bgfx_target*> to_delete; - for (std::pair<std::string, bgfx_target*> target : m_targets) - { - if (target.second != nullptr) - { - to_delete.push_back(target.second); - } - } - m_targets.clear(); - - for (uint32_t i = 0; i < to_delete.size(); i++) - { - delete to_delete[i]; - } + for (auto iter = m_targets.begin(); iter != m_targets.end(); iter = m_targets.erase(iter)) + m_textures.remove_provider(iter->first); } -bgfx_target* target_manager::create_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen) +bgfx_target* target_manager::create_target( + std::string &&name, + bgfx::TextureFormat::Enum format, + uint16_t width, + uint16_t height, + uint16_t xprescale, + uint16_t yprescale, + uint32_t style, + bool double_buffer, + bool filter, + uint16_t scale, + uint32_t screen) { - std::string full_name = name + std::to_string(screen); + const std::string full_name = name + std::to_string(screen); auto iter = m_targets.find(full_name); if (iter != m_targets.end()) - destroy_target(name, screen); + { + iter->second.reset(); + m_textures.remove_provider(full_name); + } - bgfx_target *target = new bgfx_target(name, format, width, height, style, double_buffer, filter, scale, screen); - m_targets[full_name] = target; - m_textures.add_provider(full_name, target); + auto target = std::make_unique<bgfx_target>(std::move(name), format, width, height, xprescale, yprescale, style, double_buffer, filter, scale, screen); + if (iter != m_targets.end()) + iter->second = std::move(target); + else + iter = m_targets.emplace(full_name, std::move(target)).first; + m_textures.add_provider(full_name, *iter->second); - return target; + return iter->second.get(); } -void target_manager::destroy_target(std::string name, uint32_t screen) +void target_manager::destroy_target(const std::string &name, uint32_t screen) { - std::string full_name = (screen < 0) ? name : (name + std::to_string(screen)); - if (m_targets.find(full_name) != m_targets.end()) + const std::string full_name = (screen < 0) ? name : (name + std::to_string(screen)); + const auto found = m_targets.find(full_name); + if (found != m_targets.end()) { - delete m_targets[full_name]; - m_targets.erase(full_name); + m_targets.erase(found); m_textures.remove_provider(full_name); } } bgfx_target* target_manager::create_backbuffer(void *handle, uint16_t width, uint16_t height) { - auto* target = new bgfx_target(handle, width, height); - m_targets["backbuffer"] = target; - return target; + auto target = std::make_unique<bgfx_target>(handle, width, height); + return (m_targets["backbuffer"] = std::move(target)).get(); } -bgfx_target* target_manager::target(uint32_t screen, std::string name) +bgfx_target* target_manager::target(uint32_t screen, const std::string &name) { - std::string full_name = name + std::to_string(screen); - if (m_targets.find(full_name) == m_targets.end()) + const std::string full_name = name + std::to_string(screen); + const auto found = m_targets.find(full_name); + if (found != m_targets.end()) + { + return found->second.get(); + } + else { osd_printf_verbose("Warning: Attempting to retrieve a nonexistent target '%s' for screen %d\n", name, screen); + return nullptr; } - return m_targets[full_name]; } -bool target_manager::update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style) +bool target_manager::update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style, uint16_t user_prescale, uint16_t max_prescale_size) { - if (style == TARGET_STYLE_CUSTOM) return false; + if (style == TARGET_STYLE_CUSTOM) + return false; - std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims; + std::vector<osd_dim> &sizes = (style == TARGET_STYLE_GUEST) ? m_guest_dims : m_native_dims; // Ensure that there's an entry to fill while (sizes.size() <= screen) { - sizes.emplace_back(osd_dim(0, 0)); + sizes.emplace_back(0, 0); } if (width != sizes[screen].width() || height != sizes[screen].height()) { sizes[screen] = osd_dim(width, height); - rebuild_targets(screen, style); + rebuild_targets(screen, style, user_prescale, max_prescale_size); return true; } return false; } -void target_manager::rebuild_targets(uint32_t screen, uint32_t style) +void target_manager::rebuild_targets(uint32_t screen, uint32_t style, uint16_t user_prescale, uint16_t max_prescale_size) { if (style == TARGET_STYLE_CUSTOM) return; std::vector<bgfx_target*> to_resize; - for (std::pair<std::string, bgfx_target*> target_pair : m_targets) + for (const auto &[name, target] : m_targets) { - bgfx_target* target = target_pair.second; - if (target == nullptr || target->style() != style || target->screen_index() != screen) - { - continue; - } - to_resize.push_back(target); + if (target && (target->style() == style) && (target->screen_index() == screen)) + to_resize.push_back(target.get()); } std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims; @@ -135,13 +141,15 @@ void target_manager::rebuild_targets(uint32_t screen, uint32_t style) const uint16_t scale = target->scale(); const uint16_t width(sizes[screen].width()); const uint16_t height(sizes[screen].height()); + uint16_t xprescale = user_prescale; + uint16_t yprescale = user_prescale; + bgfx_util::find_prescale_factor(width, height, max_prescale_size, xprescale, yprescale); - destroy_target(name, screen); - create_target(name, format, width, height, style, double_buffered, filter, scale, screen); + create_target(std::move(name), format, width, height, xprescale, yprescale, style, double_buffered, filter, scale, screen); } } -void target_manager::update_screen_count(uint32_t count) +void target_manager::update_screen_count(uint32_t count, uint16_t user_prescale, uint16_t max_prescale_size) { // Ensure that there's an entry to fill while (count > m_native_dims.size()) @@ -157,26 +165,26 @@ void target_manager::update_screen_count(uint32_t count) { for (uint32_t screen = old_count; screen < m_screen_count; screen++) { - create_target_if_nonexistent(screen, "output", false, false, TARGET_STYLE_NATIVE); + create_output_if_nonexistent(screen, user_prescale, max_prescale_size); } } } } -void target_manager::create_target_if_nonexistent(uint32_t screen, std::string name, bool double_buffered, bool filter, uint32_t style) +void target_manager::create_output_if_nonexistent(uint32_t screen, uint16_t user_prescale, uint16_t max_prescale_size) { - if (style == TARGET_STYLE_CUSTOM) return; - - if (m_targets.find(name + std::to_string(screen)) != m_targets.end()) + if (m_targets.find("output" + std::to_string(screen)) != m_targets.end()) { return; } - std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims; - uint16_t width(sizes[screen].width()); - uint16_t height(sizes[screen].height()); + uint16_t width(m_native_dims[screen].width()); + uint16_t height(m_native_dims[screen].height()); + uint16_t xprescale = user_prescale; + uint16_t yprescale = user_prescale; + bgfx_util::find_prescale_factor(width, height, max_prescale_size, xprescale, yprescale); - create_target(name, bgfx::TextureFormat::BGRA8, width, height, style, double_buffered, filter, 1, screen); + create_target("output", bgfx::TextureFormat::BGRA8, width, height, xprescale, yprescale, TARGET_STYLE_NATIVE, false, false, 1, screen); } uint16_t target_manager::width(uint32_t style, uint32_t screen) diff --git a/src/osd/modules/render/bgfx/targetmanager.h b/src/osd/modules/render/bgfx/targetmanager.h index fa44e2c1bd6..38bba4c5db5 100644 --- a/src/osd/modules/render/bgfx/targetmanager.h +++ b/src/osd/modules/render/bgfx/targetmanager.h @@ -9,44 +9,49 @@ // //============================================================ +#ifndef MAME_RENDER_BGFX_TARGETMANAGER_H +#define MAME_RENDER_BGFX_TARGETMANAGER_H + #pragma once -#ifndef __DRAWBGFX_TARGET_MANAGER__ -#define __DRAWBGFX_TARGET_MANAGER__ +#include "texturemanager.h" -#include <map> -#include <string> +#include "modules/osdhelper.h" #include <bgfx/bgfx.h> -#include "modules/osdhelper.h" +#include <map> +#include <memory> +#include <string> +#include <vector> -#include "texturemanager.h" class bgfx_target; -class target_manager { +class target_manager +{ public: target_manager(texture_manager& textures); ~target_manager(); - bgfx_target* create_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen); - void destroy_target(std::string name, uint32_t screen = -1); + bgfx_target* create_target(std::string &&name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint16_t xprescale, uint16_t yprescale, + uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen); + void destroy_target(const std::string &name, uint32_t screen = -1); bgfx_target* create_backbuffer(void *handle, uint16_t width, uint16_t height); - bool update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style); - void update_screen_count(uint32_t count); + bool update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style, uint16_t user_prescale, uint16_t max_prescale_size); + void update_screen_count(uint32_t count, uint16_t user_prescale, uint16_t max_prescale_size); // Getters - bgfx_target* target(uint32_t screen, std::string name); + bgfx_target* target(uint32_t screen, const std::string &name); uint16_t width(uint32_t style, uint32_t screen); uint16_t height(uint32_t style, uint32_t screen); private: - void rebuild_targets(uint32_t screen, uint32_t style); - void create_target_if_nonexistent(uint32_t screen, std::string name, bool double_buffered, bool filter, uint32_t style); + void rebuild_targets(uint32_t screen, uint32_t style, uint16_t user_prescale, uint16_t max_prescale_size); + void create_output_if_nonexistent(uint32_t screen, uint16_t user_prescale, uint16_t max_prescale_size); - std::map<std::string, bgfx_target*> m_targets; + std::map<std::string, std::unique_ptr<bgfx_target> > m_targets; texture_manager& m_textures; std::vector<osd_dim> m_guest_dims; @@ -56,4 +61,4 @@ private: static const int32_t MAX_SCREENS; }; -#endif // __DRAWBGFX_TARGET_MANAGER__ +#endif // MAME_RENDER_BGFX_TARGETMANAGER_H diff --git a/src/osd/modules/render/bgfx/targetreader.cpp b/src/osd/modules/render/bgfx/targetreader.cpp index e66a147d7ba..12386428822 100644 --- a/src/osd/modules/render/bgfx/targetreader.cpp +++ b/src/osd/modules/render/bgfx/targetreader.cpp @@ -8,11 +8,12 @@ #include "targetreader.h" -#include <modules/lib/osdobj_common.h> - +#include "bgfxutil.h" #include "chainmanager.h" #include "target.h" +#include "modules/lib/osdobj_common.h" + #include <cmath> const target_reader::string_to_enum target_reader::STYLE_NAMES[target_reader::STYLE_COUNT] = { @@ -21,7 +22,13 @@ const target_reader::string_to_enum target_reader::STYLE_NAMES[target_reader::ST { "custom", TARGET_STYLE_CUSTOM } }; -bgfx_target* target_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index) +bgfx_target* target_reader::read_from_value( + const Value& value, + const std::string &prefix, + chain_manager& chains, + uint32_t screen_index, + uint16_t user_prescale, + uint16_t max_prescale_size) { if (!validate_parameters(value, prefix)) { @@ -37,40 +44,61 @@ bgfx_target* target_reader::read_from_value(const Value& value, std::string pref { scale = int(floor(value["scale"].GetDouble() + 0.5)); } + bool use_user_prescale = get_bool(value, "user_prescale", false); uint16_t width = 0; uint16_t height = 0; + uint16_t xprescale = 1; + uint16_t yprescale = 1; switch (mode) { case TARGET_STYLE_GUEST: + { width = chains.targets().width(TARGET_STYLE_GUEST, screen_index); height = chains.targets().height(TARGET_STYLE_GUEST, screen_index); + + if (use_user_prescale) + { + xprescale = user_prescale; + yprescale = user_prescale; + bgfx_util::find_prescale_factor(width, height, max_prescale_size, xprescale, yprescale); + } break; + } case TARGET_STYLE_NATIVE: width = chains.targets().width(TARGET_STYLE_NATIVE, screen_index); height = chains.targets().height(TARGET_STYLE_NATIVE, screen_index); + + if (use_user_prescale) + { + xprescale = user_prescale; + yprescale = user_prescale; + bgfx_util::find_prescale_factor(width, height, max_prescale_size, xprescale, yprescale); + } break; case TARGET_STYLE_CUSTOM: - if (!READER_CHECK(value.HasMember("width"), (prefix + "Target '" + target_name + "': Must have numeric value 'width'\n").c_str())) return nullptr; - if (!READER_CHECK(value["width"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'width' must be a number\n").c_str())) return nullptr; - if (!READER_CHECK(value.HasMember("height"), (prefix + "Target '" + target_name + "': Must have numeric value 'height'\n").c_str())) return nullptr; - if (!READER_CHECK(value["height"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'height' must be a number\n").c_str())) return nullptr; + READER_WARN(!value.HasMember("user_prescale"), "%sTarget '%s': user_prescale parameter is not used for custom-type render targets.\n", prefix, target_name); + if (!READER_CHECK(value.HasMember("width"), "%sTarget '%s': Must have numeric value 'width'\n", prefix, target_name)) return nullptr; + if (!READER_CHECK(value["width"].IsNumber(), "%sTarget '%s': Value 'width' must be a number\n", prefix, target_name)) return nullptr; + if (!READER_CHECK(value.HasMember("height"), "%sTarget '%s': Must have numeric value 'height'\n", prefix, target_name)) return nullptr; + if (!READER_CHECK(value["height"].IsNumber(), "%sTarget '%s': Value 'height' must be a number\n", prefix, target_name)) return nullptr; width = uint16_t(value["width"].GetDouble()); height = uint16_t(value["height"].GetDouble()); break; } - return chains.targets().create_target(target_name, bgfx::TextureFormat::BGRA8, width, height, mode, double_buffer, bilinear, scale, screen_index); + return chains.targets().create_target(std::move(target_name), bgfx::TextureFormat::BGRA8, width, height, xprescale, yprescale, mode, double_buffer, bilinear, scale, screen_index); } -bool target_reader::validate_parameters(const Value& value, std::string prefix) +bool target_reader::validate_parameters(const Value& value, const 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("scale") || value["scale"].IsNumber(), (prefix + "Value 'scale' must be a numeric value\n").c_str())) return false; + if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name'\n", prefix)) return false; + if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("mode"), "%sMust have string enum 'mode'\n", prefix)) return false; + if (!READER_CHECK(value["mode"].IsString(), "%sValue 'mode' must be a string (what screens does this apply to?)\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("bilinear") || value["bilinear"].IsBool(), "%sValue 'bilinear' must be a boolean\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("doublebuffer") || value["doublebuffer"].IsBool(), "%sValue 'doublebuffer' must be a boolean\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("user_prescale") || value["user_prescale"].IsBool(), "%sValue 'user_prescale' must be a boolean\n", prefix)) return false; + if (!READER_CHECK(!value.HasMember("scale") || value["scale"].IsNumber(), "%sValue 'scale' must be a numeric value\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/targetreader.h b/src/osd/modules/render/bgfx/targetreader.h index 7edf5e456fa..2db81311359 100644 --- a/src/osd/modules/render/bgfx/targetreader.h +++ b/src/osd/modules/render/bgfx/targetreader.h @@ -6,28 +6,28 @@ // //============================================================ +#ifndef MAME_RENDER_BGFX_TARGETREADER_H +#define MAME_RENDER_BGFX_TARGETREADER_H + #pragma once -#ifndef __DRAWBGFX_TARGET_READER__ -#define __DRAWBGFX_TARGET_READER__ +#include "statereader.h" #include <string> -#include "statereader.h" - class bgfx_target; class chain_manager; class target_reader : public state_reader { public: - static bgfx_target* read_from_value(const Value& value, std::string prefix, chain_manager& chains, uint32_t screen_index); + static bgfx_target* read_from_value(const Value& value, const std::string &prefix, chain_manager& chains, uint32_t screen_index, uint16_t user_prescale, uint16_t max_prescale_size); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); static const int STYLE_COUNT = 3; static const string_to_enum STYLE_NAMES[STYLE_COUNT]; }; -#endif // __DRAWBGFX_TARGET_READER__ +#endif // MAME_RENDER_BGFX_TARGETREADER_H diff --git a/src/osd/modules/render/bgfx/texture.cpp b/src/osd/modules/render/bgfx/texture.cpp index a504c625415..2ffa97c0b6f 100644 --- a/src/osd/modules/render/bgfx/texture.cpp +++ b/src/osd/modules/render/bgfx/texture.cpp @@ -10,10 +10,11 @@ #include "texture.h" -bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t flags, void* data) +bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t width_margin, uint16_t height, uint32_t flags, void* data) : m_name(name) , m_format(format) , m_width(width) + , m_width_margin(width_margin) , m_height(height) , m_rowpixels(width) , m_width_div_factor(1) @@ -35,10 +36,11 @@ bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, u } } -bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, const bgfx::Memory* data, uint32_t flags, uint16_t pitch, uint16_t rowpixels, int width_div_factor, int width_mul_factor) +bgfx_texture::bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t width_margin, uint16_t height, const bgfx::Memory* data, uint32_t flags, uint16_t pitch, uint16_t rowpixels, int width_div_factor, int width_mul_factor) : m_name(name) , m_format(format) , m_width(width) + , m_width_margin(width_margin) , m_height(height) , m_rowpixels(rowpixels ? rowpixels : width) , m_width_div_factor(width_div_factor) @@ -56,7 +58,8 @@ bgfx_texture::~bgfx_texture() bgfx::destroy(m_texture); } -void bgfx_texture::update(const bgfx::Memory *data, uint16_t pitch) +void bgfx_texture::update(const bgfx::Memory *data, uint16_t pitch, uint16_t width_margin) { + m_width_margin = width_margin; bgfx::updateTexture2D(m_texture, 0, 0, 0, 0, (m_rowpixels * m_width_mul_factor) / m_width_div_factor, m_height, data, pitch); } diff --git a/src/osd/modules/render/bgfx/texture.h b/src/osd/modules/render/bgfx/texture.h index 75fedcd3129..ced0604dfcf 100644 --- a/src/osd/modules/render/bgfx/texture.h +++ b/src/osd/modules/render/bgfx/texture.h @@ -20,8 +20,8 @@ class bgfx_texture : public bgfx_texture_handle_provider { public: - 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_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP, uint16_t pitch = UINT16_MAX, uint16_t rowpixels = 0, int width_div_factor = 1, int width_mul_factor = 1); + bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t width_margin, uint16_t height, uint32_t flags, void* data); + bgfx_texture(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t width_margin, uint16_t height, const bgfx::Memory* data, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP, uint16_t pitch = UINT16_MAX, uint16_t rowpixels = 0, int width_div_factor = 1, int width_mul_factor = 1); virtual ~bgfx_texture(); // Getters @@ -32,17 +32,19 @@ public: virtual bgfx::TextureHandle texture() const override { return m_texture; } virtual bool is_target() const override { return false; } virtual uint16_t width() const override { return m_width; } + virtual uint16_t width_margin() const override { return m_width_margin; } virtual uint16_t height() const override { return m_height; } virtual uint16_t rowpixels() const override { return m_rowpixels; } virtual int width_div_factor() const override { return m_width_div_factor; } virtual int width_mul_factor() const override { return m_width_mul_factor; } - void update(const bgfx::Memory *data, uint16_t pitch = UINT16_MAX); + void update(const bgfx::Memory *data, uint16_t pitch = UINT16_MAX, uint16_t width_margin = 0); protected: std::string m_name; bgfx::TextureFormat::Enum m_format; uint16_t m_width; + uint16_t m_width_margin; uint16_t m_height; uint16_t m_rowpixels; int m_width_div_factor; diff --git a/src/osd/modules/render/bgfx/texturehandleprovider.h b/src/osd/modules/render/bgfx/texturehandleprovider.h index 14fb2fe892c..35e4e12dc43 100644 --- a/src/osd/modules/render/bgfx/texturehandleprovider.h +++ b/src/osd/modules/render/bgfx/texturehandleprovider.h @@ -7,26 +7,27 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_TEXTUREHANDLEPROVIDER_H +#define MAME_RENDER_BGFX_TEXTUREHANDLEPROVIDER_H -#ifndef __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__ -#define __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__ +#pragma once #include <bgfx/bgfx.h> class bgfx_texture_handle_provider { public: - virtual ~bgfx_texture_handle_provider() { } + virtual ~bgfx_texture_handle_provider() = default; // Getters virtual bgfx::TextureHandle texture() const = 0; virtual bool is_target() const = 0; virtual uint16_t width() const = 0; + virtual uint16_t width_margin() const = 0; virtual uint16_t height() const = 0; virtual uint16_t rowpixels() const = 0; virtual int width_div_factor() const = 0; virtual int width_mul_factor() const = 0; }; -#endif // __DRAWBGFX_TEXTURE_HANDLE_PROVIDER__ +#endif // MAME_RENDER_BGFX_TEXTUREHANDLEPROVIDER_H diff --git a/src/osd/modules/render/bgfx/texturemanager.cpp b/src/osd/modules/render/bgfx/texturemanager.cpp index 82225f87eb0..b9acd5748e8 100644 --- a/src/osd/modules/render/bgfx/texturemanager.cpp +++ b/src/osd/modules/render/bgfx/texturemanager.cpp @@ -11,23 +11,24 @@ #include "texturemanager.h" -#include "texture.h" #include "bgfxutil.h" +#include "texture.h" + +#include "modules/render/copyutil.h" +#include "osdcore.h" + #include "emucore.h" #include "fileio.h" #include "rendutil.h" -#include "osdcore.h" -#include "modules/render/copyutil.h" + + +texture_manager::texture_manager() +{ + // out-of-line so header works with forward declarations +} texture_manager::~texture_manager() { - for (std::pair<std::string, bgfx_texture_handle_provider*> texture : m_textures) - { - if (texture.second != nullptr && !(texture.second)->is_target()) - { - delete texture.second; - } - } m_textures.clear(); for (std::pair<uint64_t, sequenced_handle> mame_texture : m_mame_textures) @@ -37,27 +38,45 @@ texture_manager::~texture_manager() m_mame_textures.clear(); } -void texture_manager::add_provider(std::string name, bgfx_texture_handle_provider* provider) +void texture_manager::add_provider(const std::string &name, std::unique_ptr<bgfx_texture_handle_provider> &&provider) { - auto iter = m_textures.find(name); + const auto iter = m_textures.find(name); if (iter != m_textures.end()) - { - iter->second = provider; - } + iter->second = std::make_pair(provider.get(), std::move(provider)); else - { - m_textures[name] = provider; - } + m_textures.emplace(name, std::make_pair(provider.get(), std::move(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) +void texture_manager::add_provider(const std::string &name, bgfx_texture_handle_provider &provider) { - auto* texture = new bgfx_texture(name, format, width, height, flags, data); - m_textures[name] = texture; - return texture; + const auto iter = m_textures.find(name); + if (iter != m_textures.end()) + iter->second = std::make_pair(&provider, nullptr); + else + m_textures.emplace(name, std::make_pair(&provider, nullptr)); +} + +bgfx_texture* texture_manager::create_texture( + const std::string &name, + bgfx::TextureFormat::Enum format, + uint32_t width, + uint32_t width_margin, + uint32_t height, + void* data, + uint32_t flags) +{ + auto texture = std::make_unique<bgfx_texture>(name, format, width, width_margin, height, flags, data); + bgfx_texture &result = *texture; + m_textures[name] = std::make_pair(texture.get(), std::move(texture)); + return &result; } -bgfx_texture* texture_manager::create_png_texture(std::string path, std::string file_name, std::string texture_name, uint32_t flags, uint32_t screen) +bgfx_texture* texture_manager::create_png_texture( + const std::string &path, + const std::string &file_name, + std::string texture_name, + uint32_t flags, + uint32_t screen) { bitmap_argb32 bitmap; emu_file file(path, OPEN_FLAG_READ); @@ -69,40 +88,45 @@ bgfx_texture* texture_manager::create_png_texture(std::string path, std::string if (bitmap.width() == 0 || bitmap.height() == 0) { - osd_printf_error("Unable to load PNG '%s' from path '%s'\n", file_name.c_str(), path.c_str()); + osd_printf_error("Unable to load PNG '%s' from path '%s'\n", file_name, path); return nullptr; } - auto *data = new uint8_t[bitmap.width() * bitmap.height() * 4]; - auto *data32 = reinterpret_cast<uint32_t *>(data); - const uint32_t width = bitmap.width(); const uint32_t height = bitmap.height(); + auto data32 = std::make_unique<uint32_t []>(width * height); + const uint32_t rowpixels = bitmap.rowpixels(); auto* base = reinterpret_cast<uint32_t *>(bitmap.raw_pixptr(0)); for (int y = 0; y < height; y++) { - copy_util::copyline_argb32_to_bgra(data32 + y * width, base + y * rowpixels, width, nullptr); + copy_util::copyline_argb32_to_bgra(&data32[y * width], base + y * rowpixels, width, nullptr); } if (screen >= 0) { texture_name += std::to_string(screen); } - bgfx_texture* texture = create_texture(texture_name, bgfx::TextureFormat::BGRA8, width, height, data, flags); - - delete [] data; - - return texture; + return create_texture(texture_name, bgfx::TextureFormat::BGRA8, width, 0, height, data32.get(), flags); } -bgfx::TextureHandle texture_manager::create_or_update_mame_texture(uint32_t format, int width, int height - , int rowpixels, const rgb_t *palette, void *base, uint32_t seqid, uint32_t flags, uint64_t key, uint64_t old_key) +bgfx::TextureHandle texture_manager::create_or_update_mame_texture( + uint32_t format, + int width, + int width_margin, + int height, + int rowpixels, + const rgb_t *palette, + void *base, + uint32_t seqid, + uint32_t flags, + uint64_t key, + uint64_t old_key) { bgfx::TextureHandle handle = BGFX_INVALID_HANDLE; if (old_key != ~0ULL) { - auto iter = m_mame_textures.find(old_key); + const auto iter = m_mame_textures.find(old_key); if (iter != m_mame_textures.end()) { handle = iter->second.handle; @@ -126,8 +150,8 @@ bgfx::TextureHandle texture_manager::create_or_update_mame_texture(uint32_t form uint16_t pitch = width; int width_div_factor = 1; int width_mul_factor = 1; - const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, height, palette, base, pitch, width_div_factor, width_mul_factor); - bgfx::updateTexture2D(handle, 0, 0, 0, 0, (uint16_t)((rowpixels * width_mul_factor) / width_div_factor), (uint16_t)height, mem, pitch); + const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, width_margin, height, palette, base, pitch, width_div_factor, width_mul_factor); + bgfx::updateTexture2D(handle, 0, 0, 0, 0, uint16_t((rowpixels * width_mul_factor) / width_div_factor), uint16_t(height), mem, pitch); return handle; } } @@ -156,8 +180,8 @@ bgfx::TextureHandle texture_manager::create_or_update_mame_texture(uint32_t form uint16_t pitch = width; int width_div_factor = 1; int width_mul_factor = 1; - const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, height, palette, base, pitch, width_div_factor, width_mul_factor); - bgfx::updateTexture2D(handle, 0, 0, 0, 0, (uint16_t)((rowpixels * width_mul_factor) / width_div_factor), (uint16_t)height, mem, pitch); + const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, width_margin, height, palette, base, pitch, width_div_factor, width_mul_factor); + bgfx::updateTexture2D(handle, 0, 0, 0, 0, uint16_t((rowpixels * width_mul_factor) / width_div_factor), uint16_t(height), mem, pitch); return handle; } } @@ -169,47 +193,36 @@ bgfx::TextureHandle texture_manager::create_or_update_mame_texture(uint32_t form uint16_t pitch = width; int width_div_factor = 1; int width_mul_factor = 1; - const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, height, palette, base, pitch, width_div_factor, width_mul_factor); - const uint16_t adjusted_width = (uint16_t)((rowpixels * width_mul_factor) / width_div_factor); + const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, format, rowpixels, width_margin, height, palette, base, pitch, width_div_factor, width_mul_factor); + const uint16_t adjusted_width = uint16_t((rowpixels * width_mul_factor) / width_div_factor); handle = bgfx::createTexture2D(adjusted_width, height, false, 1, dst_format, flags, nullptr); - bgfx::updateTexture2D(handle, 0, 0, 0, 0, adjusted_width, (uint16_t)height, mem, pitch); + bgfx::updateTexture2D(handle, 0, 0, 0, 0, adjusted_width, uint16_t(height), mem, pitch); m_mame_textures[key] = { handle, seqid, width, height }; return handle; } -bgfx::TextureHandle texture_manager::handle(std::string name) +bgfx::TextureHandle texture_manager::handle(const std::string &name) { bgfx::TextureHandle handle = BGFX_INVALID_HANDLE; - auto iter = m_textures.find(name); + const auto iter = m_textures.find(name); if (iter != m_textures.end()) - { - handle = (iter->second)->texture(); - } + handle = iter->second.first->texture(); assert(handle.idx != bgfx::kInvalidHandle); return handle; } -bgfx_texture_handle_provider* texture_manager::provider(std::string name) +bgfx_texture_handle_provider* texture_manager::provider(const std::string &name) { - auto iter = m_textures.find(name); + const auto iter = m_textures.find(name); if (iter != m_textures.end()) - { - return iter->second; - } - - return nullptr; + return iter->second.first; + else + return nullptr; } -void texture_manager::remove_provider(std::string name, bool delete_provider) +void texture_manager::remove_provider(const std::string &name) { - if (provider(name) != nullptr) - { - if (delete_provider) - { - delete m_textures[name]; - } - m_textures.erase(name); - } + m_textures.erase(name); } diff --git a/src/osd/modules/render/bgfx/texturemanager.h b/src/osd/modules/render/bgfx/texturemanager.h index db71f07c0fa..8ed5d410f75 100644 --- a/src/osd/modules/render/bgfx/texturemanager.h +++ b/src/osd/modules/render/bgfx/texturemanager.h @@ -9,40 +9,45 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_TEXTUREMANAGER_H +#define MAME_RENDER_BGFX_TEXTUREMANAGER_H -#ifndef DRAWBGFX_TEXTURE_MANAGER -#define DRAWBGFX_TEXTURE_MANAGER +#pragma once #include "bitmap.h" #include <cstdint> #include <map> +#include <memory> #include <string> +#include <utility> #include <bgfx/bgfx.h> + class bgfx_texture_handle_provider; class bgfx_texture; -class texture_manager { +class texture_manager +{ public: - texture_manager() { } + texture_manager(); ~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_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP); - bgfx_texture* create_png_texture(std::string path, std::string file_name, std::string texture_name, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP, uint32_t screen = -1); - void add_provider(std::string name, bgfx_texture_handle_provider* texture); - void remove_provider(std::string name, bool delete_provider = false); - bgfx::TextureHandle create_or_update_mame_texture(uint32_t format, int width, int height - , int rowpixels, const rgb_t *palette, void *base, uint32_t seqid, uint32_t flags, uint64_t key, uint64_t old_key); + bgfx_texture* create_texture(const std::string &name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t width_margin, uint32_t height, void* data = nullptr, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP); + bgfx_texture* create_png_texture(const std::string &path, const std::string &file_name, std::string texture_name, uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP, uint32_t screen = -1); + void add_provider(const std::string &name, std::unique_ptr<bgfx_texture_handle_provider> &&texture); + void add_provider(const std::string &name, bgfx_texture_handle_provider &texture); + void remove_provider(const std::string &name); + bgfx::TextureHandle create_or_update_mame_texture(uint32_t format, int width, int width_margin, int height, + int rowpixels, const rgb_t *palette, void *base, uint32_t seqid, uint32_t flags, uint64_t key, uint64_t old_key); // Getters - bgfx::TextureHandle handle(std::string name); - bgfx_texture_handle_provider* provider(std::string name); + bgfx::TextureHandle handle(const std::string &name); + bgfx_texture_handle_provider* provider(const std::string &name); private: - bgfx_texture* create_texture(std::string name); + bgfx_texture* create_texture(const std::string &name); struct sequenced_handle { @@ -52,8 +57,8 @@ private: int height; }; - std::map<std::string, bgfx_texture_handle_provider*> m_textures; + std::map<std::string, std::pair<bgfx_texture_handle_provider *, std::unique_ptr<bgfx_texture_handle_provider> > > m_textures; std::map<uint64_t, sequenced_handle> m_mame_textures; }; -#endif // DRAWBGFX_TEXTURE_MANAGER +#endif // MAME_RENDER_BGFX_TEXTUREMANAGER_H diff --git a/src/osd/modules/render/bgfx/timeparameter.cpp b/src/osd/modules/render/bgfx/timeparameter.cpp index cbcd56c8e6e..bc01bb33b61 100644 --- a/src/osd/modules/render/bgfx/timeparameter.cpp +++ b/src/osd/modules/render/bgfx/timeparameter.cpp @@ -8,8 +8,10 @@ #include "timeparameter.h" -bgfx_time_parameter::bgfx_time_parameter(std::string name, parameter_type type, double limit) - : bgfx_parameter(name, type) +#include <utility> + +bgfx_time_parameter::bgfx_time_parameter(std::string &&name, parameter_type type, double limit) + : bgfx_parameter(std::move(name), type) , m_current_time(0) , m_limit(limit) { diff --git a/src/osd/modules/render/bgfx/timeparameter.h b/src/osd/modules/render/bgfx/timeparameter.h index ad01f8f7e60..ff7005041ff 100644 --- a/src/osd/modules/render/bgfx/timeparameter.h +++ b/src/osd/modules/render/bgfx/timeparameter.h @@ -6,22 +6,19 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_TIMEPARAMETER_H +#define MAME_RENDER_BGFX_TIMEPARAMETER_H -#ifndef __DRAWBGFX_TIME_PARAMETER__ -#define __DRAWBGFX_TIME_PARAMETER__ +#pragma once -#include <bgfx/bgfx.h> +#include "parameter.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() { } + bgfx_time_parameter(std::string &&name, parameter_type type, double limit); virtual float value() override; virtual void tick(double delta) override; @@ -31,4 +28,4 @@ private: double m_limit; }; -#endif // __DRAWBGFX_TIME_PARAMETER__ +#endif // MAME_RENDER_BGFX_TIMEPARAMETER_H diff --git a/src/osd/modules/render/bgfx/uniform.cpp b/src/osd/modules/render/bgfx/uniform.cpp index 36f68b7a9c7..238a6a4315d 100644 --- a/src/osd/modules/render/bgfx/uniform.cpp +++ b/src/osd/modules/render/bgfx/uniform.cpp @@ -7,10 +7,12 @@ //============================================================ #include "uniform.h" + #include <cstring> +#include <utility> -bgfx_uniform::bgfx_uniform(std::string name, bgfx::UniformType::Enum type) - : m_name(name) +bgfx_uniform::bgfx_uniform(std::string &&name, bgfx::UniformType::Enum type) + : m_name(std::move(name)) , m_type(type) { m_handle = BGFX_INVALID_HANDLE; diff --git a/src/osd/modules/render/bgfx/uniform.h b/src/osd/modules/render/bgfx/uniform.h index f7873f400a9..6a9999ca19f 100644 --- a/src/osd/modules/render/bgfx/uniform.h +++ b/src/osd/modules/render/bgfx/uniform.h @@ -6,10 +6,10 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_UNIFORM_H +#define MAME_RENDER_BGFX_UNIFORM_H -#ifndef __DRAWBGFX_UNIFORM__ -#define __DRAWBGFX_UNIFORM__ +#pragma once #include <bgfx/bgfx.h> @@ -18,7 +18,7 @@ class bgfx_uniform { public: - bgfx_uniform(std::string name, bgfx::UniformType::Enum type); + bgfx_uniform(std::string &&name, bgfx::UniformType::Enum type); virtual ~bgfx_uniform(); virtual void upload(); @@ -26,7 +26,7 @@ public: void create(); // Getters - std::string name() { return m_name; } + const std::string &name() { return m_name; } bgfx::UniformType::Enum type() const { return m_type; } bgfx::UniformHandle handle() const { return m_handle; } @@ -47,4 +47,4 @@ protected: size_t m_data_size; }; -#endif // __DRAWBGFX_UNIFORM__ +#endif // MAME_RENDER_BGFX_UNIFORM_H diff --git a/src/osd/modules/render/bgfx/uniformreader.cpp b/src/osd/modules/render/bgfx/uniformreader.cpp index f2bf1114ec6..d1eab8098c7 100644 --- a/src/osd/modules/render/bgfx/uniformreader.cpp +++ b/src/osd/modules/render/bgfx/uniformreader.cpp @@ -10,6 +10,9 @@ #include "uniform.h" +#include <cstdlib> + + const uniform_reader::string_to_enum uniform_reader::TYPE_NAMES[uniform_reader::TYPE_COUNT] = { { "int", bgfx::UniformType::Sampler }, { "vec4", bgfx::UniformType::Vec4 }, @@ -17,7 +20,7 @@ const uniform_reader::string_to_enum uniform_reader::TYPE_NAMES[uniform_reader:: { "mat4", bgfx::UniformType::Mat4 } }; -bgfx_uniform* uniform_reader::read_from_value(const Value& value, std::string prefix) +std::unique_ptr<bgfx_uniform> uniform_reader::read_from_value(const Value& value, const std::string &prefix) { if (!validate_parameters(value, prefix)) { @@ -31,33 +34,28 @@ bgfx_uniform* uniform_reader::read_from_value(const Value& value, std::string pr const Value& value_array = value["values"]; const size_t array_size = value_array.Size() * sizeof(float); - const size_t alloc_size = (type_size > array_size) ? type_size : array_size; - auto* data = reinterpret_cast<float*>(new char[alloc_size]); + auto* data = reinterpret_cast<float*>(std::malloc(std::max(type_size, array_size))); unsigned int index = 0; for (; index < type_size / 4 && index < value_array.Size(); index++) - { - data[index] = (float)value_array[index].GetDouble(); - } + data[index] = float(value_array[index].GetDouble()); for (; index < type_size / 4; index++) - { data[index] = 0.0f; - } - auto* uniform = new bgfx_uniform(name, type); - uniform->set((void*)data, type_size); - delete [] data; + auto uniform = std::make_unique<bgfx_uniform>(name, type); + uniform->set(data, type_size); + std::free(data); return uniform; } -bool uniform_reader::validate_parameters(const Value& value, std::string prefix) +bool uniform_reader::validate_parameters(const Value& value, const 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; + if (!READER_CHECK(value.HasMember("name"), "%sMust have string value 'name' (what is this uniform called in the shader code?)\n", prefix)) return false; + if (!READER_CHECK(value["name"].IsString(), "%sValue 'name' must be a string\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("type"), "%sMust have string value 'type' [int, vec4, mat3, mat4]\n", prefix)) return false; + if (!READER_CHECK(value.HasMember("values"), "%sMust have array value 'values' (what are the uniform's default values?)\n", prefix)) return false; + if (!READER_CHECK(value["values"].IsArray(), "%sValue 'values' must be an array\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/uniformreader.h b/src/osd/modules/render/bgfx/uniformreader.h index ce1b1e9ccbe..ebb3a485d63 100644 --- a/src/osd/modules/render/bgfx/uniformreader.h +++ b/src/osd/modules/render/bgfx/uniformreader.h @@ -6,27 +6,29 @@ // //============================================================ +#ifndef MAME_RENDER_BGFX_UNIFORMREADER_H +#define MAME_RENDER_BGFX_UNIFORMREADER_H + #pragma once -#ifndef __DRAWBGFX_UNIFORM_READER__ -#define __DRAWBGFX_UNIFORM_READER__ +#include "statereader.h" -#include <bgfx/bgfx.h> +#include <memory> +#include <string> -#include "statereader.h" class bgfx_uniform; class uniform_reader : public state_reader { public: - static bgfx_uniform* read_from_value(const Value& value, std::string prefix); + static std::unique_ptr<bgfx_uniform> read_from_value(const Value& value, const std::string &prefix); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); static const int TYPE_COUNT = 4; static const string_to_enum TYPE_NAMES[TYPE_COUNT]; }; -#endif // __DRAWBGFX_UNIFORM_READER__ +#endif // MAME_RENDER_BGFX_UNIFORMREADER_H diff --git a/src/osd/modules/render/bgfx/valueuniform.cpp b/src/osd/modules/render/bgfx/valueuniform.cpp index 8a018ac492a..e36ee3cbca8 100644 --- a/src/osd/modules/render/bgfx/valueuniform.cpp +++ b/src/osd/modules/render/bgfx/valueuniform.cpp @@ -10,13 +10,17 @@ //============================================================ #include "valueuniform.h" -#include <cstring> -bgfx_value_uniform::bgfx_value_uniform(bgfx_uniform* uniform, float* values, const int count) +#include <algorithm> +#include <cassert> + + +bgfx_value_uniform::bgfx_value_uniform(bgfx_uniform* uniform, const float* values, const int count) : bgfx_entry_uniform(uniform) , m_count(count) { - memcpy(m_values, values, sizeof(float) * count); + assert(count <= std::size(m_values)); + std::copy_n(values, count, m_values); } void bgfx_value_uniform::bind() diff --git a/src/osd/modules/render/bgfx/valueuniform.h b/src/osd/modules/render/bgfx/valueuniform.h index 40d207aa0bb..aa8139650a3 100644 --- a/src/osd/modules/render/bgfx/valueuniform.h +++ b/src/osd/modules/render/bgfx/valueuniform.h @@ -9,17 +9,17 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_VALUEUNIFORM_H +#define MAME_RENDER_BGFX_VALUEUNIFORM_H -#ifndef __DRAWBGFX_VALUE_UNIFORM__ -#define __DRAWBGFX_VALUE_UNIFORM__ +#pragma once #include "entryuniform.h" class bgfx_value_uniform : public bgfx_entry_uniform { public: - bgfx_value_uniform(bgfx_uniform* uniform, float* values, const int count); + bgfx_value_uniform(bgfx_uniform* uniform, const float* values, const int count); virtual void bind() override; @@ -28,4 +28,4 @@ private: const int m_count; }; -#endif // __DRAWBGFX_VALUE_UNIFORM__ +#endif // MAME_RENDER_BGFX_VALUEUNIFORM_H diff --git a/src/osd/modules/render/bgfx/valueuniformreader.cpp b/src/osd/modules/render/bgfx/valueuniformreader.cpp index e71f1c86329..137a6d24719 100644 --- a/src/osd/modules/render/bgfx/valueuniformreader.cpp +++ b/src/osd/modules/render/bgfx/valueuniformreader.cpp @@ -11,7 +11,7 @@ #include "entryuniform.h" #include "valueuniform.h" -bgfx_entry_uniform* value_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_uniform* uniform) +bgfx_entry_uniform* value_uniform_reader::read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform) { if (!validate_parameters(value, prefix)) { @@ -36,9 +36,9 @@ bgfx_entry_uniform* value_uniform_reader::read_from_value(const Value& value, st return new bgfx_value_uniform(uniform, values, count); } -bool value_uniform_reader::validate_parameters(const Value& value, std::string prefix) +bool value_uniform_reader::validate_parameters(const Value& value, const 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; + if (!READER_CHECK(value.HasMember("value"), "%sMust have string value 'value' (what value is being assigned?)\n", prefix)) return false; + if (!READER_CHECK(value["value"].IsArray() || value["value"].IsNumber(), "%sValue 'value' must be numeric or an array\n", prefix)) return false; return true; } diff --git a/src/osd/modules/render/bgfx/valueuniformreader.h b/src/osd/modules/render/bgfx/valueuniformreader.h index 0b6fead1cca..ea544266a84 100644 --- a/src/osd/modules/render/bgfx/valueuniformreader.h +++ b/src/osd/modules/render/bgfx/valueuniformreader.h @@ -6,15 +6,14 @@ // //================================================================ +#ifndef MAME_RENDER_BGFX_VALUEUNIFORMREADER_H +#define MAME_RENDER_BGFX_VALUEUNIFORMREADER_H + #pragma once -#ifndef __DRAWBGFX_VALUE_UNIFORM_READER__ -#define __DRAWBGFX_VALUE_UNIFORM_READER__ +#include "statereader.h" #include <string> -#include <map> - -#include "statereader.h" class bgfx_entry_uniform; class bgfx_uniform; @@ -22,10 +21,10 @@ 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); + static bgfx_entry_uniform* read_from_value(const Value& value, const std::string &prefix, bgfx_uniform* uniform); private: - static bool validate_parameters(const Value& value, std::string prefix); + static bool validate_parameters(const Value& value, const std::string &prefix); }; -#endif // __DRAWBGFX_VALUE_UNIFORM_READER__ +#endif // MAME_RENDER_BGFX_VALUEUNIFORMREADER_H diff --git a/src/osd/modules/render/bgfx/view.cpp b/src/osd/modules/render/bgfx/view.cpp index 6935e19bca7..3a731fc71f8 100644 --- a/src/osd/modules/render/bgfx/view.cpp +++ b/src/osd/modules/render/bgfx/view.cpp @@ -13,9 +13,7 @@ #include "target.h" void bgfx_view::update() { - std::shared_ptr<osd_window> win = m_renderer->assert_window(); - - const uint32_t window_index = win->index(); + const uint32_t window_index = m_renderer->window().index(); const uint32_t width = m_renderer->get_window_width(window_index); const uint32_t height = m_renderer->get_window_height(window_index); diff --git a/src/osd/modules/render/bgfx/view.h b/src/osd/modules/render/bgfx/view.h index a1793f89d0b..b257eb12ea4 100644 --- a/src/osd/modules/render/bgfx/view.h +++ b/src/osd/modules/render/bgfx/view.h @@ -4,12 +4,14 @@ #pragma once #include "window.h" + #include <climits> class renderer_bgfx; class bgfx_target; -class bgfx_view { +class bgfx_view +{ public: bgfx_view(renderer_bgfx *renderer, uint32_t index, bgfx_target *backbuffer, std::vector<uint32_t> &seen_views) : m_renderer(renderer) @@ -21,7 +23,7 @@ public: , m_view_height(0) , m_z_near(0.0f) , m_z_far(100.0f) - , m_clear_color(0) + , m_clear_color(0x000000ff) , m_clear_depth(1.0f) , m_clear_stencil(0) , m_do_clear_color(true) diff --git a/src/osd/modules/render/bgfx/windowparameter.h b/src/osd/modules/render/bgfx/windowparameter.h index 0ba4224de40..45df9060c71 100644 --- a/src/osd/modules/render/bgfx/windowparameter.h +++ b/src/osd/modules/render/bgfx/windowparameter.h @@ -6,22 +6,20 @@ // //============================================================ -#pragma once +#ifndef MAME_RENDER_BGFX_WINDOWPARAMETER_H +#define MAME_RENDER_BGFX_WINDOWPARAMETER_H -#ifndef __DRAWBGFX_WINDOW_PARAMETER__ -#define __DRAWBGFX_WINDOW_PARAMETER__ +#pragma once -#include <bgfx/bgfx.h> +#include "parameter.h" #include <string> - -#include "parameter.h" +#include <utility> 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() { } + bgfx_window_parameter(std::string &&name, parameter_type type, uint32_t index) : bgfx_parameter(std::move(name), type), m_index(index) { } virtual float value() override { return float(m_index); } virtual void tick(double delta) override { } @@ -30,4 +28,4 @@ private: uint32_t m_index; }; -#endif // __DRAWBGFX_WINDOW_PARAMETER__ +#endif // MAME_RENDER_BGFX_WINDOWPARAMETER_H diff --git a/src/osd/modules/render/bgfxutil.cpp b/src/osd/modules/render/bgfxutil.cpp index e864cb98fb4..3d555bb60ad 100644 --- a/src/osd/modules/render/bgfxutil.cpp +++ b/src/osd/modules/render/bgfxutil.cpp @@ -14,10 +14,11 @@ #include "render.h" -const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::TextureFormat::Enum &dst_format, uint32_t src_format, int rowpixels, int height, const rgb_t *palette, void *base, uint16_t &out_pitch, int &width_div_factor, int &width_mul_factor) +const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::TextureFormat::Enum &dst_format, uint32_t src_format, int rowpixels, int width_margin, int height, const rgb_t *palette, void *base, uint16_t &out_pitch, int &width_div_factor, int &width_mul_factor) { bgfx::TextureInfo info; const bgfx::Memory *data = nullptr; + uint8_t *adjusted_base = (uint8_t *)base; switch (src_format) { @@ -28,7 +29,11 @@ const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::Text out_pitch = rowpixels * 2; bgfx::calcTextureSize(info, rowpixels / width_div_factor, height, 1, false, false, 1, dst_format); - data = bgfx::copy(base, info.storageSize); + if (width_margin) + { + adjusted_base -= width_margin * 2; + } + data = bgfx::copy(adjusted_base, info.storageSize); break; case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16): dst_format = bgfx::TextureFormat::R8; @@ -37,7 +42,11 @@ const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::Text out_pitch = rowpixels * 2; bgfx::calcTextureSize(info, rowpixels * width_mul_factor, height, 1, false, false, 1, dst_format); - data = bgfx::copy(base, info.storageSize); + if (width_margin) + { + adjusted_base -= width_margin * 2; + } + data = bgfx::copy(adjusted_base, info.storageSize); break; case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32): case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32): @@ -47,7 +56,11 @@ const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(bgfx::Text out_pitch = rowpixels * 4; bgfx::calcTextureSize(info, rowpixels, height, 1, false, false, 1, dst_format); - data = bgfx::copy(base, info.storageSize); + if (width_margin) + { + adjusted_base -= width_margin * 4; + } + data = bgfx::copy(adjusted_base, info.storageSize); break; } @@ -96,6 +109,7 @@ uint64_t bgfx_util::get_blend_state(uint32_t blend) case BLENDMODE_ALPHA: return BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA); case BLENDMODE_RGB_MULTIPLY: + //return BGFX_STATE_BLEND_FUNC_SEPARATE(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_INV_SRC_COLOR, BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ZERO); return BGFX_STATE_BLEND_FUNC_SEPARATE(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO, BGFX_STATE_BLEND_DST_ALPHA, BGFX_STATE_BLEND_ZERO); case BLENDMODE_ADD: return BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE); @@ -104,3 +118,15 @@ uint64_t bgfx_util::get_blend_state(uint32_t blend) } return 0L; } + +void bgfx_util::find_prescale_factor(uint16_t width, uint16_t height, uint16_t max_prescale_size, uint16_t &xprescale, uint16_t &yprescale) +{ + while (xprescale > 1 && width * xprescale > max_prescale_size) + { + xprescale--; + } + while (yprescale > 1 && height * yprescale > max_prescale_size) + { + yprescale--; + } +} diff --git a/src/osd/modules/render/bgfxutil.h b/src/osd/modules/render/bgfxutil.h index db07e7fba77..aa108a6fb3b 100644 --- a/src/osd/modules/render/bgfxutil.h +++ b/src/osd/modules/render/bgfxutil.h @@ -15,9 +15,10 @@ class bgfx_util { public: - static const bgfx::Memory* mame_texture_data_to_bgfx_texture_data(bgfx::TextureFormat::Enum &dst_format, uint32_t format, int rowpixels, int height, const rgb_t *palette, void *base, uint16_t &out_pitch, int &width_div_factor, int &width_mul_factor); + static const bgfx::Memory* mame_texture_data_to_bgfx_texture_data(bgfx::TextureFormat::Enum &dst_format, uint32_t format, int rowpixels, int width_margin, int height, const rgb_t *palette, void *base, uint16_t &out_pitch, int &width_div_factor, int &width_mul_factor); static const bgfx::Memory* mame_texture_data_to_bgra32(uint32_t src_format, int width, int height, int rowpixels, const rgb_t *palette, void *base); static uint64_t get_blend_state(uint32_t blend); + static void find_prescale_factor(uint16_t width, uint16_t height, uint16_t max_prescale_size, uint16_t &xprescale, uint16_t &yprescale); }; #endif // RENDER_BGFX_UTIL diff --git a/src/osd/modules/render/binpacker.h b/src/osd/modules/render/binpacker.h index 1fb84596eec..52efe4abb85 100644 --- a/src/osd/modules/render/binpacker.h +++ b/src/osd/modules/render/binpacker.h @@ -29,7 +29,7 @@ public: class packable_rectangle { public: - packable_rectangle() : m_hash(0), m_width(-1), m_height(-1) { } + packable_rectangle() = default; packable_rectangle(uint32_t hash, uint32_t format, int width, int height, int rowpixels, const rgb_t *palette, void *base) : m_hash(hash) , m_format(format) @@ -50,19 +50,19 @@ public: void* base() const { return m_base; } private: - uint32_t m_hash; - uint32_t m_format; - int m_width; - int m_height; - int m_rowpixels; - const rgb_t* m_palette; - void* m_base; + uint32_t m_hash = 0; + uint32_t m_format = 0; + int m_width = -1; + int m_height = -1; + int m_rowpixels = 0; + const rgb_t* m_palette = nullptr; + void* m_base = nullptr; }; class packed_rectangle { public: - packed_rectangle() : m_hash(0), m_format(0), m_width(-1), m_height(-1), m_x(-1), m_y(-1), m_rowpixels(0), m_palette(nullptr), m_base(nullptr) { } + packed_rectangle() = default; packed_rectangle(const packed_rectangle& rect) : m_hash(rect.m_hash) , m_format(rect.m_format) @@ -99,15 +99,15 @@ public: void* base() const { return m_base; } private: - uint32_t m_hash; - uint32_t m_format; - int m_width; - int m_height; - int m_x; - int m_y; - int m_rowpixels; - const rgb_t* m_palette; - void* m_base; + uint32_t m_hash = 0; + uint32_t m_format = 0; + int m_width = -1; + int m_height = -1; + int m_x = -1; + int m_y = -1; + int m_rowpixels = 0; + const rgb_t* m_palette = nullptr; + void* m_base = nullptr; }; bool pack(const std::vector<packable_rectangle>& rects, std::vector<std::vector<packed_rectangle>>& packs, int pack_size); diff --git a/src/osd/modules/render/blit13.h b/src/osd/modules/render/blit13.ipp index 1ac485bab8d..1ac485bab8d 100644 --- a/src/osd/modules/render/blit13.h +++ b/src/osd/modules/render/blit13.ipp diff --git a/src/osd/modules/render/d3d/d3dcomm.h b/src/osd/modules/render/d3d/d3dcomm.h index c7dc58c6340..846d9dac791 100644 --- a/src/osd/modules/render/d3d/d3dcomm.h +++ b/src/osd/modules/render/d3d/d3dcomm.h @@ -6,8 +6,22 @@ // //============================================================ -#ifndef __WIN_D3DCOMM__ -#define __WIN_D3DCOMM__ +#ifndef MAME_RENDER_D3D_D3DCOMM_H +#define MAME_RENDER_D3D_D3DCOMM_H + +#pragma once + +// lib/util +#include "bitmap.h" + +#include <windows.h> +#include <d3d9.h> +#include <wrl/client.h> + +#include <cstring> +#include <memory> +#include <vector> + //============================================================ // CONSTANTS @@ -60,10 +74,7 @@ public: class d3d_texture_manager { public: - d3d_texture_manager(): m_renderer(nullptr), m_yuv_format(), m_texture_caps(0), m_texture_max_aspect(0), m_texture_max_width(0), m_texture_max_height(0), m_default_texture(nullptr) - { } - - d3d_texture_manager(renderer_d3d9 *d3d); + d3d_texture_manager(renderer_d3d9 &d3d, IDirect3D9 *d3dobj); void update_textures(); @@ -82,12 +93,12 @@ public: texture_info * get_default_texture() const { return m_default_texture; } - renderer_d3d9 * get_d3d() const { return m_renderer; } + renderer_d3d9 & get_d3d() const { return m_renderer; } - std::vector<std::unique_ptr<texture_info>> m_texture_list; // list of active textures + std::vector<std::unique_ptr<texture_info> > m_texture_list; // list of active textures private: - renderer_d3d9 * m_renderer; + renderer_d3d9 & m_renderer; D3DFORMAT m_yuv_format; // format to use for YUV textures DWORD m_texture_caps; // textureCaps field @@ -104,7 +115,7 @@ private: class texture_info { public: - texture_info(d3d_texture_manager *manager, const render_texinfo *texsource, int prescale, uint32_t flags); + texture_info(d3d_texture_manager &manager, const render_texinfo *texsource, int prescale, uint32_t flags); ~texture_info(); render_texinfo & get_texinfo() { return m_texinfo; } @@ -125,15 +136,16 @@ public: int get_cur_frame() const { return m_cur_frame; } - IDirect3DTexture9 * get_tex() const { return m_d3dtex; } - IDirect3DSurface9 * get_surface() const { return m_d3dsurface; } - IDirect3DTexture9 * get_finaltex() const { return m_d3dfinaltex; } + IDirect3DTexture9 * get_finaltex() const { return m_d3dfinaltex.Get(); } vec2f & get_uvstart() { return m_start; } vec2f & get_uvstop() { return m_stop; } vec2f & get_rawdims() { return m_rawdims; } private: + using IDirect3DTexture9Ptr = Microsoft::WRL::ComPtr<IDirect3DTexture9>; + using IDirect3DSurface9Ptr = Microsoft::WRL::ComPtr<IDirect3DSurface9>; + void prescale(); void compute_size(int texwidth, int texheight); void compute_size_subroutine(int texwidth, int texheight, int* p_width, int* p_height); @@ -145,23 +157,23 @@ private: inline void copyline_yuy16_to_uyvy(uint16_t *dst, const uint16_t *src, int width, const rgb_t *palette); inline void copyline_yuy16_to_argb(uint32_t *dst, const uint16_t *src, int width, const rgb_t *palette); - d3d_texture_manager * m_texture_manager; // texture manager pointer + d3d_texture_manager & m_texture_manager; // texture manager pointer - renderer_d3d9 * m_renderer; // renderer pointer + renderer_d3d9 & m_renderer; // renderer pointer - uint32_t m_hash; // hash value for the texture - uint32_t m_flags; // rendering flags + const uint32_t m_hash; // hash value for the texture + const uint32_t m_flags; // rendering flags render_texinfo m_texinfo; // copy of the texture info + const int m_type; // what type of texture are we? vec2f m_start; // beggining UV coordinates vec2f m_stop; // ending UV coordinates vec2f m_rawdims; // raw dims of the texture - int m_type; // what type of texture are we? int m_xprescale, m_yprescale; // X/Y prescale factor int m_xborderpix, m_yborderpix; // X/Y border pixels int m_cur_frame; // what is our current frame? - IDirect3DTexture9 * m_d3dtex; // Direct3D texture pointer - IDirect3DSurface9 * m_d3dsurface; // Direct3D offscreen plain surface pointer - IDirect3DTexture9 * m_d3dfinaltex; // Direct3D final (post-scaled) texture + IDirect3DTexture9Ptr m_d3dtex; // Direct3D texture pointer + IDirect3DSurface9Ptr m_d3dsurface; // Direct3D offscreen plain surface pointer + IDirect3DTexture9Ptr m_d3dfinaltex; // Direct3D final (post-scaled) texture }; /* poly_info holds information about a single polygon/d3d primitive */ @@ -170,7 +182,7 @@ class poly_info public: void init(D3DPRIMITIVETYPE type, uint32_t count, uint32_t numverts, uint32_t flags, texture_info *texture, uint32_t modmode, - float prim_width, float prim_height) + float prim_width, float prim_height, uint32_t tint) { m_type = type; m_count = count; @@ -180,6 +192,7 @@ public: m_modmode = modmode; m_prim_width = prim_width; m_prim_height = prim_height; + m_tint = tint; } D3DPRIMITIVETYPE type() const { return m_type; } @@ -193,6 +206,8 @@ public: float prim_width() const { return m_prim_width; } float prim_height() const { return m_prim_height; } + DWORD tint() const { return m_tint; } + private: D3DPRIMITIVETYPE m_type; // type of primitive uint32_t m_count; // total number of primitives @@ -204,6 +219,8 @@ private: float m_prim_width; // used by quads float m_prim_height; // used by quads + + uint32_t m_tint; // color tint for primitive }; /* vertex describes a single vertex */ @@ -222,24 +239,14 @@ class d3d_render_target { public: // construction/destruction - d3d_render_target(): target_width(0), target_height(0), width(0), height(0), screen_index(0), bloom_count(0) + d3d_render_target() + : target_width(0) + , target_height(0) + , width(0) + , height(0) + , screen_index(0) + , bloom_count(0) { - for (int index = 0; index < MAX_BLOOM_COUNT; index++) - { - bloom_texture[index] = nullptr; - bloom_surface[index] = nullptr; - } - - for (int index = 0; index < 2; index++) - { - source_texture[index] = nullptr; - source_surface[index] = nullptr; - target_texture[index] = nullptr; - target_surface[index] = nullptr; - } - - cache_texture = nullptr; - cache_surface = nullptr; } ~d3d_render_target(); @@ -257,20 +264,20 @@ public: int screen_index; - IDirect3DSurface9 *target_surface[2]; - IDirect3DTexture9 *target_texture[2]; - IDirect3DSurface9 *source_surface[2]; - IDirect3DTexture9 *source_texture[2]; + Microsoft::WRL::ComPtr<IDirect3DSurface9> target_surface[2]; + Microsoft::WRL::ComPtr<IDirect3DTexture9> target_texture[2]; + Microsoft::WRL::ComPtr<IDirect3DSurface9> source_surface[2]; + Microsoft::WRL::ComPtr<IDirect3DTexture9> source_texture[2]; - IDirect3DSurface9 *cache_surface; - IDirect3DTexture9 *cache_texture; + Microsoft::WRL::ComPtr<IDirect3DSurface9> cache_surface; + Microsoft::WRL::ComPtr<IDirect3DTexture9> cache_texture; - IDirect3DSurface9 *bloom_surface[MAX_BLOOM_COUNT]; - IDirect3DTexture9 *bloom_texture[MAX_BLOOM_COUNT]; + Microsoft::WRL::ComPtr<IDirect3DSurface9> bloom_surface[MAX_BLOOM_COUNT]; + Microsoft::WRL::ComPtr<IDirect3DTexture9> bloom_texture[MAX_BLOOM_COUNT]; float bloom_dims[MAX_BLOOM_COUNT][2]; int bloom_count; }; -#endif +#endif // MAME_RENDER_D3D_D3DCOMM_H diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 22a6b5af508..c0753f314f7 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -8,15 +8,18 @@ // MAME headers #include "emu.h" + #include "drivenum.h" +#include "emuopts.h" +#include "fileio.h" +#include "main.h" #include "render.h" #include "rendlay.h" #include "rendutil.h" -#include "emuopts.h" -#include "fileio.h" +#include "screen.h" + #include "aviio.h" #include "png.h" -#include "screen.h" // MAMEOS headers #include "winmain.h" @@ -50,8 +53,6 @@ class movie_recorder public: movie_recorder(running_machine& machine, renderer_d3d9 *d3d, int width, int height) : m_initialized(false), m_d3d(d3d), m_width(width), m_height(height) - , m_sys_texture(nullptr), m_sys_surface(nullptr) - , m_vid_texture(nullptr), m_vid_surface(nullptr) { HRESULT result; @@ -82,17 +83,6 @@ public: ~movie_recorder() { - if (m_sys_texture != nullptr) - m_sys_texture->Release(); - - if (m_sys_surface != nullptr) - m_sys_surface->Release(); - - if (m_vid_texture != nullptr) - m_vid_texture->Release(); - - if (m_vid_surface != nullptr) - m_vid_surface->Release(); } void record(const char *name) @@ -109,7 +99,7 @@ public: return; // copy the frame from video memory, where it is not accessible, to system memory - HRESULT result = m_d3d->get_device()->GetRenderTargetData(m_vid_surface, m_sys_surface); + HRESULT result = m_d3d->get_device()->GetRenderTargetData(m_vid_surface.Get(), m_sys_surface.Get()); if (FAILED(result)) return; @@ -144,7 +134,7 @@ public: m_avi_writer->audio_frame(buffer, samples_this_frame); } - IDirect3DSurface9 * target_surface() { return m_vid_surface; } + IDirect3DSurface9 * target_surface() { return m_vid_surface.Get(); } private: bool m_initialized; @@ -156,10 +146,10 @@ private: bitmap_rgb32 m_frame; int m_width; int m_height; - IDirect3DTexture9 * m_sys_texture; // texture in system memory - IDirect3DSurface9 * m_sys_surface; // surface in system memory - IDirect3DTexture9 * m_vid_texture; // texture in video memory - IDirect3DSurface9 * m_vid_surface; // surface in video memory + Microsoft::WRL::ComPtr<IDirect3DTexture9> m_sys_texture; // texture in system memory + Microsoft::WRL::ComPtr<IDirect3DSurface9> m_sys_surface; // surface in system memory + Microsoft::WRL::ComPtr<IDirect3DTexture9> m_vid_texture; // texture in video memory + Microsoft::WRL::ComPtr<IDirect3DSurface9> m_vid_surface; // surface in video memory }; @@ -168,51 +158,32 @@ private: //============================================================ shaders::shaders() : - d3dintf(nullptr), machine(nullptr), d3d(nullptr), post_fx_enable(false), oversampling_enable(false), num_screens(0), - curr_screen(0), + num_targets(0), + curr_target(0), acc_t(0), delta_t(0), shadow_texture(nullptr), lut_texture(nullptr), ui_lut_texture(nullptr), options(nullptr), - black_surface(nullptr), - black_texture(nullptr), recording_movie(false), render_snap(false), - snap_copy_target(nullptr), - snap_copy_texture(nullptr), - snap_target(nullptr), - snap_texture(nullptr), snap_width(0), snap_height(0), initialized(false), - backbuffer(nullptr), curr_effect(nullptr), - default_effect(nullptr), - prescale_effect(nullptr), - post_effect(nullptr), - distortion_effect(nullptr), - scanline_effect(nullptr), - focus_effect(nullptr), - phosphor_effect(nullptr), - deconverge_effect(nullptr), - color_effect(nullptr), - ntsc_effect(nullptr), - bloom_effect(nullptr), - downsample_effect(nullptr), - vector_effect(nullptr), - chroma_effect(nullptr), + diffuse_texture(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr), d3dx_create_effect_from_file_ptr(nullptr) { + std::fill(std::begin(target_to_screen), std::end(target_to_screen), 0); } @@ -222,12 +193,7 @@ shaders::shaders() : shaders::~shaders() { - for (slider* slider : internal_sliders) - { - delete slider; - } - - if (options != nullptr) + if (options && (&last_options != options)) { delete options; options = nullptr; @@ -244,11 +210,9 @@ void shaders::save_snapshot() if (!enabled()) return; - auto win = d3d->assert_window(); - int width = snap_width; int height = snap_height; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(width, height); } @@ -289,8 +253,7 @@ void shaders::record_movie() return; } - auto win = d3d->assert_window(); - osd_dim wdim = win->get_size(); + osd_dim wdim = d3d->window().get_size(); recorder = std::make_unique<movie_recorder>(*machine, d3d, wdim.width(), wdim.height()); recorder->record(downcast<windows_options &>(machine->options()).d3d_hlsl_write()); @@ -323,11 +286,9 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) if (!enabled()) return; - auto win = d3d->assert_window(); - int width = snap_width; int height = snap_height; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(width, height); } @@ -337,7 +298,7 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) return; // copy the texture - HRESULT result = d3d->get_device()->GetRenderTargetData(surface, snap_copy_target); + HRESULT result = d3d->get_device()->GetRenderTargetData(surface, snap_copy_target.Get()); if (FAILED(result)) return; @@ -378,29 +339,10 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during texture UnlockRect call\n", result); - if (snap_texture != nullptr) - { - snap_texture->Release(); - snap_texture = nullptr; - } - - if (snap_target != nullptr) - { - snap_target->Release(); - snap_target = nullptr; - } - - if (snap_copy_texture != nullptr) - { - snap_copy_texture->Release(); - snap_copy_texture = nullptr; - } - - if (snap_copy_target != nullptr) - { - snap_copy_target->Release(); - snap_copy_target = nullptr; - } + snap_texture.Reset(); + snap_target.Reset(); + snap_copy_texture.Reset(); + snap_copy_target.Reset(); } @@ -440,25 +382,33 @@ void shaders::set_texture(texture_info *texture) return; } - // set initial texture to use - texture_info *default_texture = d3d->get_default_texture(); - default_effect->set_texture("Diffuse", (texture == nullptr) ? default_texture->get_finaltex() : texture->get_finaltex()); - if (options->yiq_enable) + if (texture) { - ntsc_effect->set_texture("Diffuse", (texture == nullptr) ? default_texture->get_finaltex() : texture->get_finaltex()); + diffuse_texture = texture; } else { - color_effect->set_texture("Diffuse", (texture == nullptr) ? default_texture->get_finaltex() : texture->get_finaltex()); + diffuse_texture = d3d->get_default_texture(); } } //============================================================ +// shaders::set_filter - indicates if screens should be +// filtered on upscaling +//============================================================ + +void shaders::set_filter(bool filter_screens) +{ + this->filter_screens = filter_screens; +} + + +//============================================================ // shaders::init //============================================================ -bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer) +bool shaders::init(IDirect3D9 *d3dobj, running_machine *machine, renderer_d3d9 *renderer) { osd_printf_verbose("Direct3D: Initialize HLSL\n"); @@ -490,14 +440,10 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r return false; } - d3dintf->post_fx_available = true; - - this->d3dintf = d3dintf; + this->d3dobj = d3dobj; this->machine = machine; this->d3d = renderer; - enumerate_screens(); - auto &winoptions = downcast<windows_options &>(machine->options()); post_fx_enable = winoptions.d3d_hlsl_enable(); @@ -505,19 +451,18 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r snap_width = winoptions.d3d_snap_width(); snap_height = winoptions.d3d_snap_height(); - this->options = new hlsl_options; - this->options->params_init = false; - - // copy last options if initialized if (last_options.params_init) { + // copy last options if initialized osd_printf_verbose("Direct3D: First restore options\n"); options = &last_options; } - - // read options if not initialized - if (!options->params_init) + else { + // read options if not initialized + options = new hlsl_options; + options->params_init = false; + strncpy(options->shadow_mask_texture, winoptions.screen_shadow_mask_texture(), sizeof(options->shadow_mask_texture)); options->shadow_mask_tile_mode = winoptions.screen_shadow_mask_tile_mode(); options->shadow_mask_alpha = winoptions.screen_shadow_mask_alpha(); @@ -599,6 +544,7 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r osd_printf_verbose("Direct3D: First store options\n"); last_options = *options; + delete options; options = &last_options; } @@ -613,11 +559,70 @@ bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r //============================================================ +// shaders::begin_frame +// +// Enumerates the total number of screen textures present. +// +// Additionally, ensures the presence of necessary post- +// processing geometry. +// +//============================================================ + +void shaders::begin_frame(render_primitive_list *primlist) +{ + init_fsfx_quad(); + + std::fill(std::begin(target_to_screen), std::end(target_to_screen), 0); + std::fill(std::begin(targets_per_screen), std::end(targets_per_screen), 0); + EQUIVALENT_ARRAY(target_to_screen, render_container *) containers; + + // Maximum potential runtime O(max_num_targets^2) + num_targets = 0; + num_screens = 0; + curr_target = 0; + for (render_primitive &prim : *primlist) + { + if (PRIMFLAG_GET_SCREENTEX(prim.flags)) + { + int screen_index = 0; + for (; screen_index < num_screens && containers[screen_index] != prim.container; screen_index++); + containers[screen_index] = prim.container; + target_to_screen[num_targets] = screen_index; + targets_per_screen[screen_index]++; + if (screen_index >= num_screens) + num_screens++; + num_targets++; + } + } + + diffuse_texture = d3d->get_default_texture(); +} + + +//============================================================ +// shaders::end_frame +// +// Closes out any still-active effects at the end of +// rendering. +// +//============================================================ + +void shaders::end_frame() +{ + if (curr_effect->is_active()) + { + curr_effect->end(); + } +} + + +//============================================================ // shaders::init_fsfx_quad // // Called always at the start of each frame so that the two // triangles used for the post-processing effects are always -// at the beginning of the vertex buffer +// at the beginning of the vertex buffer. +// //============================================================ void shaders::init_fsfx_quad() @@ -714,7 +719,7 @@ int shaders::create_resources() return 1; } black_texture->GetSurfaceLevel(0, &black_surface); - result = d3d->get_device()->SetRenderTarget(0, black_surface); + result = d3d->get_device()->SetRenderTarget(0, black_surface.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); @@ -722,7 +727,7 @@ int shaders::create_resources() if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result); - result = d3d->get_device()->SetRenderTarget(0, backbuffer); + result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); @@ -747,7 +752,7 @@ int shaders::create_resources() texture.seqid = 0; // now create it (no prescale, no wrap) - auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); shadow_texture = tex.get(); d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } @@ -770,7 +775,7 @@ int shaders::create_resources() texture.seqid = 0; // now create it (no prescale, no wrap) - auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); lut_texture = tex.get(); d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } @@ -793,74 +798,66 @@ int shaders::create_resources() texture.seqid = 0; // now create it (no prescale, no wrap) - auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); ui_lut_texture = tex.get(); d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } const char *fx_dir = downcast<windows_options &>(machine->options()).screen_post_fx_dir(); - default_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir); - post_effect = new effect(this, d3d->get_device(), "post.fx", fx_dir); - distortion_effect = new effect(this, d3d->get_device(), "distortion.fx", fx_dir); - prescale_effect = new effect(this, d3d->get_device(), "prescale.fx", fx_dir); - phosphor_effect = new effect(this, d3d->get_device(), "phosphor.fx", fx_dir); - focus_effect = new effect(this, d3d->get_device(), "focus.fx", fx_dir); - scanline_effect = new effect(this, d3d->get_device(), "scanline.fx", fx_dir); - deconverge_effect = new effect(this, d3d->get_device(), "deconverge.fx", fx_dir); - color_effect = new effect(this, d3d->get_device(), "color.fx", fx_dir); - ntsc_effect = new effect(this, d3d->get_device(), "ntsc.fx", fx_dir); - bloom_effect = new effect(this, d3d->get_device(), "bloom.fx", fx_dir); - downsample_effect = new effect(this, d3d->get_device(), "downsample.fx", fx_dir); - vector_effect = new effect(this, d3d->get_device(), "vector.fx", fx_dir); - chroma_effect = new effect(this, d3d->get_device(), "chroma.fx", fx_dir); - - if (!default_effect->is_valid() || - !post_effect->is_valid() || - !distortion_effect->is_valid() || - !prescale_effect->is_valid() || - !phosphor_effect->is_valid() || - !focus_effect->is_valid() || - !scanline_effect->is_valid() || - !deconverge_effect->is_valid() || - !color_effect->is_valid() || - !ntsc_effect->is_valid() || - !bloom_effect->is_valid() || - !downsample_effect->is_valid() || - !vector_effect->is_valid() || - !chroma_effect->is_valid()) - { - return 1; - } - - std::array<effect*, 15> effects = { - default_effect, - post_effect, - distortion_effect, - prescale_effect, - phosphor_effect, - focus_effect, - scanline_effect, - deconverge_effect, - color_effect, - ntsc_effect, - color_effect, - bloom_effect, - downsample_effect, - vector_effect, - chroma_effect - }; - - for (int i = 0; i < effects.size(); i++) - { - effects[i]->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); - effects[i]->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS); - effects[i]->add_uniform("TargetScale", uniform::UT_FLOAT, uniform::CU_TARGET_SCALE); - effects[i]->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); - effects[i]->add_uniform("ScreenCount", uniform::UT_INT, uniform::CU_SCREEN_COUNT); - effects[i]->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS); - effects[i]->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY); - effects[i]->add_uniform("VectorScreen", uniform::UT_BOOL, uniform::CU_VECTOR_SCREEN); + default_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir); + ui_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir); + ui_wrap_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir); + vector_buffer_effect = std::make_unique<effect>(this, d3d->get_device(), "primary.fx", fx_dir); + post_effect = std::make_unique<effect>(this, d3d->get_device(), "post.fx", fx_dir); + distortion_effect = std::make_unique<effect>(this, d3d->get_device(), "distortion.fx", fx_dir); + prescale_effect = std::make_unique<effect>(this, d3d->get_device(), "prescale.fx", fx_dir); + prescale_point_effect = std::make_unique<effect>(this, d3d->get_device(), "prescale.fx", fx_dir); + phosphor_effect = std::make_unique<effect>(this, d3d->get_device(), "phosphor.fx", fx_dir); + focus_effect = std::make_unique<effect>(this, d3d->get_device(), "focus.fx", fx_dir); + scanline_effect = std::make_unique<effect>(this, d3d->get_device(), "scanline.fx", fx_dir); + deconverge_effect = std::make_unique<effect>(this, d3d->get_device(), "deconverge.fx", fx_dir); + color_effect = std::make_unique<effect>(this, d3d->get_device(), "color.fx", fx_dir); + ntsc_effect = std::make_unique<effect>(this, d3d->get_device(), "ntsc.fx", fx_dir); + bloom_effect = std::make_unique<effect>(this, d3d->get_device(), "bloom.fx", fx_dir); + downsample_effect = std::make_unique<effect>(this, d3d->get_device(), "downsample.fx", fx_dir); + vector_effect = std::make_unique<effect>(this, d3d->get_device(), "vector.fx", fx_dir); + chroma_effect = std::make_unique<effect>(this, d3d->get_device(), "chroma.fx", fx_dir); + + std::array<effect*, 18> effects = { + default_effect.get(), + ui_effect.get(), + ui_wrap_effect.get(), + vector_buffer_effect.get(), + post_effect.get(), + distortion_effect.get(), + prescale_effect.get(), + prescale_point_effect.get(), + phosphor_effect.get(), + focus_effect.get(), + scanline_effect.get(), + deconverge_effect.get(), + color_effect.get(), + ntsc_effect.get(), + bloom_effect.get(), + downsample_effect.get(), + vector_effect.get(), + chroma_effect.get() }; + + for (effect *eff : effects) + { + if (!eff->is_valid()) + return 1; + } + + for (effect *eff : effects) + { + eff->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS); + eff->add_uniform("TargetScale", uniform::UT_FLOAT, uniform::CU_TARGET_SCALE); + eff->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); + eff->add_uniform("ScreenCount", uniform::UT_INT, uniform::CU_SCREEN_COUNT); + eff->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY); + eff->add_uniform("VectorScreen", uniform::UT_BOOL, uniform::CU_VECTOR_SCREEN); } ntsc_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); @@ -873,6 +870,7 @@ int shaders::create_resources() ntsc_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ); ntsc_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ); ntsc_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME); + ntsc_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); color_effect->add_uniform("RedRatios", uniform::UT_VEC3, uniform::CU_COLOR_RED_RATIOS); color_effect->add_uniform("GrnRatios", uniform::UT_VEC3, uniform::CU_COLOR_GRN_RATIOS); @@ -880,6 +878,8 @@ int shaders::create_resources() color_effect->add_uniform("Offset", uniform::UT_VEC3, uniform::CU_COLOR_OFFSET); color_effect->add_uniform("Scale", uniform::UT_VEC3, uniform::CU_COLOR_SCALE); color_effect->add_uniform("Saturation", uniform::UT_FLOAT, uniform::CU_COLOR_SATURATION); + color_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); + color_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE); deconverge_effect->add_uniform("ConvergeX", uniform::UT_VEC3, uniform::CU_CONVERGE_LINEAR_X); deconverge_effect->add_uniform("ConvergeY", uniform::UT_VEC3, uniform::CU_CONVERGE_LINEAR_Y); @@ -892,6 +892,8 @@ int shaders::create_resources() scanline_effect->add_uniform("ScanlineVariation", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_VARIATION); scanline_effect->add_uniform("ScanlineBrightScale", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_BRIGHT_SCALE); scanline_effect->add_uniform("ScanlineBrightOffset", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_BRIGHT_OFFSET); + scanline_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS); + scanline_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); focus_effect->add_uniform("Defocus", uniform::UT_VEC2, uniform::CU_FOCUS_SIZE); @@ -904,9 +906,15 @@ int shaders::create_resources() post_effect->add_uniform("Floor", uniform::UT_VEC3, uniform::CU_POST_FLOOR); post_effect->add_uniform("ChomaMode", uniform::UT_INT, uniform::CU_CHROMA_MODE); post_effect->add_uniform("ConversionGain", uniform::UT_VEC3, uniform::CU_CHROMA_CONVERSION_GAIN); + post_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS); + post_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); phosphor_effect->add_uniform("Phosphor", uniform::UT_VEC3, uniform::CU_PHOSPHOR_LIFE); + bloom_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); + + downsample_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS); + chroma_effect->add_uniform("YGain", uniform::UT_VEC3, uniform::CU_CHROMA_Y_GAIN); chroma_effect->add_uniform("ChromaA", uniform::UT_VEC2, uniform::CU_CHROMA_A); chroma_effect->add_uniform("ChromaB", uniform::UT_VEC2, uniform::CU_CHROMA_B); @@ -919,9 +927,19 @@ int shaders::create_resources() distortion_effect->add_uniform("RoundCornerAmount", uniform::UT_FLOAT, uniform::CU_POST_ROUND_CORNER); distortion_effect->add_uniform("SmoothBorderAmount", uniform::UT_FLOAT, uniform::CU_POST_SMOOTH_BORDER); distortion_effect->add_uniform("ReflectionAmount", uniform::UT_FLOAT, uniform::CU_POST_REFLECTION); + distortion_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS); + + prescale_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); + + prescale_point_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); - default_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE); - default_effect->add_uniform("UiLutEnable", uniform::UT_BOOL, uniform::CU_UI_LUT_ENABLE); + ui_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE); + ui_effect->add_uniform("UiLutEnable", uniform::UT_BOOL, uniform::CU_UI_LUT_ENABLE); + + ui_wrap_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE); + ui_wrap_effect->add_uniform("UiLutEnable", uniform::UT_BOOL, uniform::CU_UI_LUT_ENABLE); + + vector_buffer_effect->add_uniform("LutEnable", uniform::UT_BOOL, uniform::CU_LUT_ENABLE); return 0; } @@ -933,24 +951,24 @@ int shaders::create_resources() void shaders::begin_draw() { - double t; - if (!enabled()) - { return; - } - curr_screen = 0; - curr_effect = default_effect; + curr_target = 0; + // Update for delta_time - t = machine->time().as_double(); + const double t = machine->time().as_double(); delta_t = t - acc_t; acc_t = t; default_effect->set_technique("ScreenTechnique"); + ui_effect->set_technique("UiTechnique"); + ui_wrap_effect->set_technique("UiWrapTechnique"); + vector_buffer_effect->set_technique("VectorBufferTechnique"); post_effect->set_technique("DefaultTechnique"); distortion_effect->set_technique("DefaultTechnique"); prescale_effect->set_technique("DefaultTechnique"); + prescale_point_effect->set_technique("PointTechnique"); phosphor_effect->set_technique("DefaultTechnique"); focus_effect->set_technique("DefaultTechnique"); scanline_effect->set_technique("DefaultTechnique"); @@ -963,11 +981,31 @@ void shaders::begin_draw() vector_effect->set_technique("DefaultTechnique"); chroma_effect->set_technique("DefaultTechnique"); - HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer); + HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get()); if (FAILED(result)) { osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); } + + set_curr_effect(default_effect.get()); +} + + +//============================================================ +// shaders::set_curr_effect +//============================================================ + +void shaders::set_curr_effect(effect *curr_effect) +{ + if (this->curr_effect == curr_effect) + { + return; + } + if (this->curr_effect && this->curr_effect->is_active()) + { + this->curr_effect->end(); + } + this->curr_effect = curr_effect; } @@ -994,7 +1032,7 @@ void shaders::blit( if (clear_dst) { - result = d3d->get_device()->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 0, 0); + result = d3d->get_device()->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0xff,0,0,0), 0, 0); if (FAILED(result)) { osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result); @@ -1002,24 +1040,17 @@ void shaders::blit( } } - UINT num_passes = 0; - curr_effect->begin(&num_passes, 0); - - for (UINT pass = 0; pass < num_passes; pass++) + if (!curr_effect->is_active()) { - curr_effect->begin_pass(pass); - - // add the primitives - result = d3d->get_device()->DrawPrimitive(prim_type, prim_index, prim_count); - if (FAILED(result)) - { - osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result); - } - - curr_effect->end_pass(); + curr_effect->begin(0); } - curr_effect->end(); + // add the primitives + result = d3d->get_device()->DrawPrimitive(prim_type, prim_index, prim_count); + if (FAILED(result)) + { + osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result); + } } //============================================================ @@ -1056,14 +1087,15 @@ int shaders::ntsc_pass(d3d_render_target *rt, int source_index, poly_info *poly, // initial "Diffuse" texture is set in shaders::set_texture() - curr_effect = ntsc_effect; + set_curr_effect(ntsc_effect.get()); + curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); curr_effect->update_uniforms(); curr_effect->set_float("SignalOffset", signal_offset); next_index = rt->next_index(next_index); - blit(rt->source_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->source_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); - color_effect->set_texture("Diffuse", rt->source_texture[next_index]); + color_effect->set_texture("Diffuse", rt->source_texture[next_index].Get()); return next_index; } @@ -1112,13 +1144,23 @@ int shaders::color_convolution_pass(d3d_render_target *rt, int source_index, pol { int next_index = source_index; - curr_effect = color_effect; - curr_effect->update_uniforms(); + set_curr_effect(color_effect.get()); - // initial "Diffuse" texture is set in shaders::set_texture() or the result of shaders::ntsc_pass() + // initial "Diffuse" texture is set in shaders::ntsc_pass() if NTSC processing is enabled + if (!options->yiq_enable) + { + curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); + } + + curr_effect->update_uniforms(); + uint32_t tint = (uint32_t)poly->tint(); + float prim_tint[3] = { ((tint >> 16) & 0xff) / 255.0f, ((tint >> 8) & 0xff) / 255.0f, (tint & 0xff) / 255.0f }; + curr_effect->set_vector("PrimTint", 3, prim_tint); + curr_effect->set_texture("LutTexture", !lut_texture ? nullptr : lut_texture->get_finaltex()); + curr_effect->set_bool("UiLutEnable", false); next_index = rt->next_index(next_index); - blit(rt->source_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->source_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1127,12 +1169,12 @@ int shaders::prescale_pass(d3d_render_target *rt, int source_index, poly_info *p { int next_index = source_index; - curr_effect = prescale_effect; + set_curr_effect(filter_screens ? prescale_effect.get() : prescale_point_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->source_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->source_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1150,12 +1192,12 @@ int shaders::deconverge_pass(d3d_render_target *rt, int source_index, poly_info return next_index; } - curr_effect = deconverge_effect; + set_curr_effect(deconverge_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1165,12 +1207,11 @@ int shaders::scanline_pass(d3d_render_target *rt, int source_index, poly_info *p int next_index = source_index; // skip scanline if alpha is 0 - if (options->scanline_alpha == 0.0f) - return next_index; + //if (options->scanline_alpha == 0.0f) + //return next_index; - auto win = d3d->assert_window(); screen_device_enumerator screen_iterator(machine->root_device()); - screen_device *screen = screen_iterator.byindex(curr_screen); + screen_device *screen = screen_iterator.byindex(target_to_screen[curr_target]); render_container &screen_container = screen->container(); float xscale = 1.0f / screen_container.xscale(); float yscale = 1.0f / screen_container.yscale(); @@ -1179,16 +1220,16 @@ int shaders::scanline_pass(d3d_render_target *rt, int source_index, poly_info *p float screen_scale[] = { xscale, yscale }; float screen_offset[] = { xoffset, yoffset }; - curr_effect = scanline_effect; + set_curr_effect(scanline_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); curr_effect->set_vector("ScreenScale", 2, screen_scale); curr_effect->set_vector("ScreenOffset", 2, screen_offset); curr_effect->set_float("ScanlineOffset", curr_texture->get_cur_frame() == 0 ? 0.0f : options->scanline_jitter); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1202,12 +1243,12 @@ int shaders::defocus_pass(d3d_render_target *rt, int source_index, poly_info *po return next_index; } - curr_effect = focus_effect; + set_curr_effect(focus_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1223,23 +1264,23 @@ int shaders::phosphor_pass(d3d_render_target *rt, int source_index, poly_info *p } // Shader needs time between last update - curr_effect = phosphor_effect; + set_curr_effect(phosphor_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); - curr_effect->set_texture("LastPass", rt->cache_texture); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); + curr_effect->set_texture("LastPass", rt->cache_texture.Get()); curr_effect->set_bool("Passthrough", false); curr_effect->set_float("DeltaTime", delta_time()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); // Pass along our phosphor'd screen curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); - curr_effect->set_texture("LastPass", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); + curr_effect->set_texture("LastPass", rt->target_texture[next_index].Get()); curr_effect->set_bool("Passthrough", true); - blit(rt->cache_surface, false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->cache_surface.Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1248,10 +1289,8 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly, { int next_index = source_index; - auto win = d3d->assert_window(); - screen_device_enumerator screen_iterator(machine->root_device()); - screen_device *screen = screen_iterator.byindex(curr_screen); + screen_device *screen = screen_iterator.byindex(target_to_screen[curr_target]); render_container &screen_container = screen->container(); float xscale = 1.0f / screen_container.xscale(); @@ -1270,11 +1309,11 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly, float(back_color_rgb.g()) / 255.0f, float(back_color_rgb.b()) / 255.0f }; - curr_effect = post_effect; + set_curr_effect(post_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("ShadowTexture", shadow_texture == nullptr ? nullptr : shadow_texture->get_finaltex()); + curr_effect->set_texture("ShadowTexture", !shadow_texture ? nullptr : shadow_texture->get_finaltex()); curr_effect->set_int("ShadowTileMode", options->shadow_mask_tile_mode); - curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]); + curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get()); curr_effect->set_vector("BackColor", 3, back_color); curr_effect->set_vector("ScreenScale", 2, screen_scale); curr_effect->set_vector("ScreenOffset", 2, screen_offset); @@ -1283,7 +1322,7 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly, curr_effect->set_bool("PrepareBloom", prepare_bloom); next_index = rt->next_index(next_index); - blit(prepare_bloom ? rt->source_surface[next_index] : rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(prepare_bloom ? rt->source_surface[next_index].Get() : rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1292,11 +1331,11 @@ int shaders::chroma_pass(d3d_render_target *rt, int source_index, poly_info *pol { int next_index = source_index; - curr_effect = chroma_effect; + set_curr_effect(chroma_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1310,18 +1349,19 @@ int shaders::downsample_pass(d3d_render_target *rt, int source_index, poly_info return next_index; } - curr_effect = downsample_effect; - curr_effect->update_uniforms(); + set_curr_effect(downsample_effect.get()); for (int bloom_index = 0; bloom_index < rt->bloom_count; bloom_index++) { + curr_effect->update_uniforms(); curr_effect->set_vector("TargetDims", 2, rt->bloom_dims[bloom_index]); curr_effect->set_texture("DiffuseTexture", bloom_index == 0 - ? rt->source_texture[next_index] - : rt->bloom_texture[bloom_index - 1]); + ? rt->source_texture[next_index].Get() + : rt->bloom_texture[bloom_index - 1].Get()); - blit(rt->bloom_surface[bloom_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->bloom_surface[bloom_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); + downsample_effect->end(); } return next_index; @@ -1337,7 +1377,7 @@ int shaders::bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly return next_index; } - curr_effect = bloom_effect; + set_curr_effect(bloom_effect.get()); curr_effect->update_uniforms(); curr_effect->set_float("Level0Weight", options->bloom_level0_weight); @@ -1354,22 +1394,22 @@ int shaders::bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly curr_effect->set_float("BloomScale", options->bloom_scale); curr_effect->set_vector("BloomOverdrive", 3, options->bloom_overdrive); - curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]); + curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get()); char name[14] = "BloomTexture*"; for (int index = 1; index < rt->bloom_count; index++) { name[12] = 'A' + index - 1; - curr_effect->set_texture(name, rt->bloom_texture[index - 1]); + curr_effect->set_texture(name, rt->bloom_texture[index - 1].Get()); } for (int index = rt->bloom_count; index < MAX_BLOOM_COUNT; index++) { name[12] = 'A' + index - 1; - curr_effect->set_texture(name, black_texture); + curr_effect->set_texture(name, black_texture.Get()); } next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1390,12 +1430,12 @@ int shaders::distortion_pass(d3d_render_target *rt, int source_index, poly_info return next_index; } - curr_effect = distortion_effect; + set_curr_effect(distortion_effect.get()); curr_effect->update_uniforms(); - curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]); + curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index].Get()); next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), false, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1404,14 +1444,14 @@ int shaders::vector_pass(d3d_render_target *rt, int source_index, poly_info *pol { int next_index = source_index; - curr_effect = vector_effect; + set_curr_effect(vector_effect.get()); curr_effect->update_uniforms(); curr_effect->set_float("LengthRatio", options->vector_length_ratio); curr_effect->set_float("LengthScale", options->vector_length_scale); curr_effect->set_float("BeamSmooth", options->vector_beam_smooth); // we need to clear the vector render target here - blit(rt->target_surface[next_index], true, poly->type(), vertnum, poly->count()); + blit(rt->target_surface[next_index].Get(), true, poly->type(), vertnum, poly->count()); return next_index; } @@ -1420,17 +1460,17 @@ int shaders::vector_buffer_pass(d3d_render_target *rt, int source_index, poly_in { int next_index = source_index; - curr_effect = default_effect; + set_curr_effect(vector_buffer_effect.get()); + curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); curr_effect->update_uniforms(); - curr_effect->set_technique("VectorBufferTechnique"); - - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); - curr_effect->set_texture("LutTexture", lut_texture == nullptr ? nullptr : lut_texture->get_finaltex()); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); + curr_effect->set_texture("LutTexture", !lut_texture ? nullptr : lut_texture->get_finaltex()); + curr_effect->set_bool("UiLutEnable", false); // we need to clear the vector render target here next_index = rt->next_index(next_index); - blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2); + blit(rt->target_surface[next_index].Get(), true, D3DPT_TRIANGLELIST, 0, 2); return next_index; } @@ -1441,14 +1481,16 @@ int shaders::screen_pass(d3d_render_target *rt, int source_index, poly_info *pol d3d->set_blendmode(PRIMFLAG_GET_BLENDMODE(poly->flags())); - curr_effect = default_effect; + set_curr_effect(default_effect.get()); + curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); curr_effect->update_uniforms(); - curr_effect->set_technique("ScreenTechnique"); - curr_effect->set_texture("Diffuse", rt->target_texture[next_index]); - curr_effect->set_texture("LutTexture", lut_texture == nullptr ? nullptr : lut_texture->get_finaltex()); + curr_effect->set_texture("Diffuse", rt->target_texture[next_index].Get()); + curr_effect->set_texture("LutTexture", nullptr); + curr_effect->set_bool("LutEnable", false); + curr_effect->set_bool("UiLutEnable", false); - blit(backbuffer, false, poly->type(), vertnum, poly->count()); + blit(backbuffer.Get(), false, poly->type(), vertnum, poly->count()); if (recording_movie) { @@ -1460,9 +1502,9 @@ int shaders::screen_pass(d3d_render_target *rt, int source_index, poly_info *pol if (render_snap) { // we need to clear the snap render target here - blit(snap_target, true, poly->type(), vertnum, poly->count()); + blit(snap_target.Get(), true, poly->type(), vertnum, poly->count()); - render_snapshot(snap_target); + render_snapshot(snap_target.Get()); render_snap = false; } @@ -1474,11 +1516,11 @@ void shaders::ui_pass(poly_info *poly, int vertnum) { d3d->set_blendmode(PRIMFLAG_GET_BLENDMODE(poly->flags())); - curr_effect = default_effect; + set_curr_effect(PRIMFLAG_GET_TEXWRAP(poly->flags()) ? ui_wrap_effect.get() : ui_effect.get()); + curr_effect->set_texture("Diffuse", diffuse_texture->get_finaltex()); curr_effect->update_uniforms(); - curr_effect->set_technique("UiTechnique"); - curr_effect->set_texture("LutTexture", lut_texture == nullptr ? nullptr : ui_lut_texture->get_finaltex()); + curr_effect->set_texture("LutTexture", !lut_texture ? nullptr : ui_lut_texture->get_finaltex()); blit(nullptr, false, poly->type(), vertnum, poly->count()); } @@ -1498,8 +1540,6 @@ void shaders::render_quad(poly_info *poly, int vertnum) curr_texture = poly->texture(); curr_poly = poly; - auto win = d3d->assert_window(); - if (PRIMFLAG_GET_SCREENTEX(poly->flags())) { if (curr_texture == nullptr) @@ -1508,9 +1548,9 @@ void shaders::render_quad(poly_info *poly, int vertnum) return; } - curr_screen = curr_screen < num_screens ? curr_screen : 0; + curr_target = curr_target < num_targets ? curr_target : 0; - curr_render_target = find_render_target(curr_texture->get_width(), curr_texture->get_height(), curr_screen); + curr_render_target = find_render_target(curr_texture->get_width(), curr_texture->get_height(), curr_target); d3d_render_target *rt = curr_render_target; if (rt == nullptr) @@ -1530,12 +1570,16 @@ void shaders::render_quad(poly_info *poly, int vertnum) //next_index = phosphor_pass(rt, next_index, poly, vertnum); // create bloom textures - int old_index = next_index; - next_index = post_pass(rt, next_index, poly, vertnum, true); - next_index = downsample_pass(rt, next_index, poly, vertnum); + bool bloom_enabled = (options->bloom_scale > 0.0f); + if (bloom_enabled) + { + int old_index = next_index; + next_index = post_pass(rt, next_index, poly, vertnum, true); + next_index = downsample_pass(rt, next_index, poly, vertnum); + next_index = old_index; + } - // apply bloom textures - next_index = old_index; + // apply bloom textures (if enabled) and other post effects next_index = post_pass(rt, next_index, poly, vertnum, false); next_index = bloom_pass(rt, next_index, poly, vertnum); next_index = phosphor_pass(rt, next_index, poly, vertnum); @@ -1551,19 +1595,19 @@ void shaders::render_quad(poly_info *poly, int vertnum) curr_texture->increment_frame_count(); curr_texture->mask_frame_count(options->yiq_phase_count); - curr_screen++; + curr_target++; } else if (PRIMFLAG_GET_VECTOR(poly->flags())) { - curr_screen = curr_screen < num_screens ? curr_screen : 0; + curr_target = curr_target < num_targets ? curr_target : 0; int source_width = int(poly->prim_width() + 0.5f); int source_height = int(poly->prim_height() + 0.5f); - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(source_width, source_height); } - curr_render_target = find_render_target(source_width, source_height, curr_screen); + curr_render_target = find_render_target(source_width, source_height, curr_target); d3d_render_target *rt = curr_render_target; if (rt == nullptr) @@ -1576,25 +1620,25 @@ void shaders::render_quad(poly_info *poly, int vertnum) next_index = vector_pass(rt, next_index, poly, vertnum); - HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer); + HRESULT result = d3d->get_device()->SetRenderTarget(0, backbuffer.Get()); if (FAILED(result)) { osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); } - curr_screen++; + curr_target++; } else if (PRIMFLAG_GET_VECTORBUF(poly->flags())) { - curr_screen = curr_screen < num_screens ? curr_screen : 0; + curr_target = curr_target < num_targets ? curr_target : 0; int source_width = int(poly->prim_width() + 0.5f); int source_height = int(poly->prim_height() + 0.5f); - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(source_width, source_height); } - curr_render_target = find_render_target(source_width, source_height, curr_screen); + curr_render_target = find_render_target(source_width, source_height, curr_target); d3d_render_target *rt = curr_render_target; if (rt == nullptr) @@ -1629,7 +1673,7 @@ void shaders::render_quad(poly_info *poly, int vertnum) next_index = screen_pass(rt, next_index, poly, vertnum); d3d->set_wrap(PRIMFLAG_GET_TEXWRAP(curr_texture->get_flags()) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); - curr_screen++; + curr_target++; } else { @@ -1655,7 +1699,7 @@ void shaders::end_draw() return; } - backbuffer->Release(); + backbuffer->Release(); // TODO: where's the matching AddRef that requires this explicit Release? } @@ -1670,8 +1714,6 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, int width return nullptr; } - auto win = d3d->assert_window(); - int source_width = width; int source_height = height; int source_screen = screen; @@ -1679,7 +1721,7 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, int width int target_height = int(prim->get_full_quad_height() + 0.5f); target_width *= oversampling_enable ? 2 : 1; target_height *= oversampling_enable ? 2 : 1; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(target_width, target_height); } @@ -1710,8 +1752,6 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim, int screen return nullptr; } - auto win = d3d->assert_window(); - int source_width = int(prim->get_quad_width() + 0.5f); int source_height = int(prim->get_quad_height() + 0.5f); int source_screen = screen; @@ -1719,7 +1759,7 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim, int screen int target_height = int(prim->get_full_quad_height() + 0.5f); target_width *= oversampling_enable ? 2 : 1; target_height *= oversampling_enable ? 2 : 1; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(source_width, source_height); std::swap(target_width, target_height); @@ -1751,8 +1791,6 @@ bool shaders::create_vector_target(render_primitive *prim, int screen) return false; } - auto win = d3d->assert_window(); - int source_width = int(prim->get_quad_width() + 0.5f); int source_height = int(prim->get_quad_height() + 0.5f); int source_screen = screen; @@ -1760,7 +1798,7 @@ bool shaders::create_vector_target(render_primitive *prim, int screen) int target_height = int(prim->get_full_quad_height() + 0.5f); target_width *= oversampling_enable ? 2 : 1; target_height *= oversampling_enable ? 2 : 1; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { std::swap(source_width, source_height); std::swap(target_width, target_height); @@ -1796,16 +1834,6 @@ bool shaders::add_render_target(renderer_d3d9* d3d, render_primitive *prim, int //============================================================ -// shaders::enumerate_screens -//============================================================ -void shaders::enumerate_screens() -{ - screen_device_enumerator iter(machine->root_device()); - num_screens = iter.count(); -} - - -//============================================================ // shaders::create_texture_target //============================================================ @@ -1816,8 +1844,6 @@ bool shaders::create_texture_target(render_primitive *prim, int width, int heigh return false; } - auto win = d3d->assert_window(); - int source_width = width; int source_height = height; int source_screen = screen; @@ -1825,7 +1851,7 @@ bool shaders::create_texture_target(render_primitive *prim, int width, int heigh int target_height = int(prim->get_full_quad_height() + 0.5f); target_width *= oversampling_enable ? 2 : 1; target_height *= oversampling_enable ? 2 : 1; - if (win->swap_xy()) + if (d3d->window().swap_xy()) { // source texture is already swapped std::swap(target_width, target_height); @@ -1863,93 +1889,29 @@ void shaders::delete_resources() m_render_target_list.clear(); - if (downsample_effect != nullptr) - { - delete downsample_effect; - downsample_effect = nullptr; - } - if (bloom_effect != nullptr) - { - delete bloom_effect; - bloom_effect = nullptr; - } - if (vector_effect != nullptr) - { - delete vector_effect; - vector_effect = nullptr; - } - if (default_effect != nullptr) - { - delete default_effect; - default_effect = nullptr; - } - if (post_effect != nullptr) - { - delete post_effect; - post_effect = nullptr; - } - if (distortion_effect != nullptr) - { - delete distortion_effect; - distortion_effect = nullptr; - } - if (prescale_effect != nullptr) - { - delete prescale_effect; - prescale_effect = nullptr; - } - if (phosphor_effect != nullptr) - { - delete phosphor_effect; - phosphor_effect = nullptr; - } - if (focus_effect != nullptr) - { - delete focus_effect; - focus_effect = nullptr; - } - if (scanline_effect != nullptr) - { - delete scanline_effect; - scanline_effect = nullptr; - } - if (deconverge_effect != nullptr) - { - delete deconverge_effect; - deconverge_effect = nullptr; - } - if (color_effect != nullptr) - { - delete color_effect; - color_effect = nullptr; - } - if (ntsc_effect != nullptr) - { - delete ntsc_effect; - ntsc_effect = nullptr; - } - if (chroma_effect != nullptr) - { - delete chroma_effect; - chroma_effect = nullptr; - } - - if (backbuffer != nullptr) - { - backbuffer->Release(); - backbuffer = nullptr; - } - - if (black_surface != nullptr) - { - black_surface->Release(); - black_surface = nullptr; - } - if (black_texture != nullptr) - { - black_texture->Release(); - black_texture = nullptr; - } + downsample_effect.reset(); + bloom_effect.reset(); + vector_effect.reset(); + default_effect.reset(); + ui_effect.reset(); + ui_wrap_effect.reset(); + vector_buffer_effect.reset(); + post_effect.reset(); + distortion_effect.reset(); + prescale_effect.reset(); + prescale_point_effect.reset(); + phosphor_effect.reset(); + focus_effect.reset(); + scanline_effect.reset(); + deconverge_effect.reset(); + color_effect.reset(); + ntsc_effect.reset(); + chroma_effect.reset(); + + backbuffer.Reset(); + + black_surface.Reset(); + black_texture.Reset(); shadow_bitmap.reset(); lut_bitmap.reset(); @@ -2060,7 +2022,7 @@ int32_t slider::update(std::string *str, int32_t newval) return 0; } -char shaders::last_system_name[16]; +char shaders::last_system_name[MAX_DRIVER_NAME_CHARS + 1]; hlsl_options shaders::last_options = { false }; @@ -2215,13 +2177,13 @@ slider_desc shaders::s_sliders[] = { "NTSC Frame Jitter Offset", 0, 0, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_JITTER, 0.01f, "%1.2f", {} }, { "NTSC A Value", -100, 50, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_A_VALUE, 0.01f, "%1.2f", {} }, { "NTSC B Value", -100, 50, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_B_VALUE, 0.01f, "%1.2f", {} }, - { "NTSC Incoming Phase Pixel Clock Scale",-300, 100, 300, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_P_VALUE, 0.01f, "%1.2f", {} }, - { "NTSC Outgoing Phase Offset", -300, 0, 300, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_O_VALUE, 0.01f, "%1.2f", {} }, - { "NTSC Color Carrier (Hz)", 0, 35795, 60000, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_CC_VALUE, 0.001f, "%1.4f", {} }, - { "NTSC Color Notch Filter Width", 0, 100, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_N_VALUE, 0.01f, "%1.4f", {} }, - { "NTSC Y Signal Bandwidth (Hz)", 0, 600, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_Y_VALUE, 0.01f, "%1.4f", {} }, - { "NTSC I Signal Bandwidth (Hz)", 0, 120, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_I_VALUE, 0.01f, "%1.4f", {} }, - { "NTSC Q Signal Bandwidth (Hz)", 0, 60, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_Q_VALUE, 0.01f, "%1.4f", {} }, + { "NTSC Incoming Phase Pixel Clock Scale",-300,100, 300, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_P_VALUE, 0.01f, "%1.2f", {} }, + { "NTSC Outgoing Phase Offset (radians)",-314, 0, 314, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_O_VALUE, 0.01f, "%1.2f", {} }, + { "NTSC Color Carrier (MHz)", 0, 31500,6*8800, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_CC_VALUE, 1/8800.f, "%1.5f", {} }, + { "NTSC Color Notch Filter Width (MHz)",0, 100, 600, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_N_VALUE, 0.01f, "%1.2f", {} }, + { "NTSC Y Signal Bandwidth (MHz)", 0, 600, 2100, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_Y_VALUE, 0.01f, "%1.2f", {} }, + { "NTSC I Signal Bandwidth (MHz)", 0, 120, 2100, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_I_VALUE, 0.01f, "%1.2f", {} }, + { "NTSC Q Signal Bandwidth (MHz)", 0, 60, 2100, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_Q_VALUE, 0.01f, "%1.2f", {} }, { "NTSC Scanline Duration (uSec)", 0, 5260, 10000, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_LCD_OR_RASTER, SLIDER_NTSC_SCAN_TIME, 0.01f, "%1.2f", {} }, { "3D LUT (Screen)", 0, 0, 1, 1, SLIDER_INT_ENUM, SLIDER_SCREEN_TYPE_ANY, SLIDER_LUT_ENABLE, 0, "%s", { "Off", "On" } }, { nullptr, 0, 0, 0, 0, 0, 0, -1, 0, nullptr, {} } @@ -2313,10 +2275,6 @@ void shaders::init_slider_list() m_sliders.clear(); m_core_sliders.clear(); - for (slider* slider : internal_sliders) - { - delete slider; - } internal_sliders.clear(); const screen_device *first_screen = screen_device_enumerator(machine->root_device()).first(); @@ -2349,28 +2307,27 @@ void shaders::init_slider_list() for (int j = 0; j < count; j++) { - auto* slider_arg = new slider(desc, get_slider_option(desc->id, j), &options->params_dirty); - internal_sliders.push_back(slider_arg); + slider &slider_arg = *internal_sliders.emplace_back(std::make_unique<slider>(desc, get_slider_option(desc->id, j), &options->params_dirty)); std::string name = desc->name; switch (desc->slider_type) { case SLIDER_VEC2: { - std::string names[2] = { " X", " Y" }; - name = name + names[j]; + char const *const names[2] = { " X", " Y" }; + name += names[j]; break; } case SLIDER_COLOR: { - std::string names[3] = { " Red", " Green", " Blue" }; - name = name + names[j]; + char const *const names[3] = { " Red", " Green", " Blue" }; + name += names[j]; break; } default: break; } - std::unique_ptr<slider_state> core_slider = slider_alloc(std::move(name), desc->minval, desc->defval, desc->maxval, desc->step, slider_arg); + std::unique_ptr<slider_state> core_slider = slider_alloc(std::move(name), desc->minval, desc->defval, desc->maxval, desc->step, &slider_arg); ui::menu_item item(ui::menu_item_type::SLIDER, core_slider.get()); item.set_text(core_slider->description); @@ -2405,8 +2362,7 @@ void uniform::update() hlsl_options *options = shadersys->options; renderer_d3d9 *d3d = shadersys->d3d; - auto win = d3d->assert_window(); - const screen_device *first_screen = screen_device_enumerator(win->machine().root_device()).first(); + const screen_device *first_screen = screen_device_enumerator(d3d->window().machine().root_device()).first(); bool vector_screen = first_screen != nullptr && @@ -2422,7 +2378,7 @@ void uniform::update() } case CU_SCREEN_COUNT: { - int screen_count = win->target()->current_view().visible_screen_count(); + int screen_count = d3d->window().target()->current_view().visible_screen_count(); m_shader->set_int("ScreenCount", screen_count); break; } @@ -2485,7 +2441,7 @@ void uniform::update() case CU_SWAP_XY: { - m_shader->set_bool("SwapXY", win->swap_xy()); + m_shader->set_bool("SwapXY", d3d->window().swap_xy()); break; } case CU_VECTOR_SCREEN: @@ -2609,7 +2565,7 @@ void uniform::update() m_shader->set_float("SmoothBorderAmount", options->smooth_border); break; case CU_POST_SHADOW_ALPHA: - m_shader->set_float("ShadowAlpha", shadersys->shadow_texture == nullptr ? 0.0f : options->shadow_mask_alpha); + m_shader->set_float("ShadowAlpha", !shadersys->shadow_texture ? 0.0f : options->shadow_mask_alpha); break; case CU_POST_SHADOW_COUNT: { @@ -2684,12 +2640,14 @@ void uniform::update() //============================================================ effect::effect(shaders *shadersys, IDirect3DDevice9 *dev, const char *name, const char *path) + : m_effect(nullptr) + , m_shaders(shadersys) + , m_num_passes(0) + , m_valid(false) + , m_active(false) { LPD3DXBUFFER buffer_errors = nullptr; - m_shaders = shadersys; - m_valid = false; - char name_cstr[1024]; sprintf(name_cstr, "%s\\%s", path, name); auto effect_name = osd::text::to_tstring(name_cstr); @@ -2716,6 +2674,12 @@ effect::effect(shaders *shadersys, IDirect3DDevice9 *dev, const char *name, cons effect::~effect() { m_effect->Release(); + + m_vecs.clear(); + m_floats.clear(); + m_ints.clear(); + m_bools.clear(); + m_textures.clear(); } void effect::add_uniform(const char *name, uniform::uniform_type type, int id) @@ -2729,24 +2693,19 @@ void effect::update_uniforms() (*uniform).update(); } -void effect::begin(UINT *passes, DWORD flags) +void effect::begin(DWORD flags) { - m_effect->Begin(passes, flags); + m_active = true; + m_num_passes = 0; + m_effect->Begin(&m_num_passes, flags); + m_effect->BeginPass(0); } void effect::end() { - m_effect->End(); -} - -void effect::begin_pass(UINT pass) -{ - m_effect->BeginPass(pass); -} - -void effect::end_pass() -{ + m_active = false; m_effect->EndPass(); + m_effect->End(); } void effect::set_technique(const char *name) @@ -2756,48 +2715,97 @@ void effect::set_technique(const char *name) void effect::set_vector(D3DXHANDLE param, int count, float *vector) { - static D3DXVECTOR4 out_vector; - if (count > 0) - { - out_vector.x = vector[0]; - } - if (count > 1) - { - out_vector.y = vector[1]; - } - if (count > 2) + count = std::min(count, 4); + + auto iter = m_vecs.find(param); + if (iter != m_vecs.end()) { - out_vector.z = vector[2]; + D3DXVECTOR4 &data = iter->second; + if (!memcmp((float *)data, vector, sizeof(float) * count)) + { + return; + } + memcpy(data, vector, sizeof(float) * count); + m_effect->SetVector(param, &iter->second); } - if (count > 3) + else { - out_vector.w = vector[3]; + D3DXVECTOR4 vec; + memcpy((float *)vec, vector, sizeof(float) * count); + m_effect->SetVector(param, &vec); + m_vecs[param] = vec; } - m_effect->SetVector(param, &out_vector); } void effect::set_float(D3DXHANDLE param, float value) { + auto iter = m_floats.find(param); + if (iter != m_floats.end()) + { + if (iter->second == value) + { + return; + } + iter->second = value; + } + else + { + m_floats[param] = value; + } m_effect->SetFloat(param, value); } void effect::set_int(D3DXHANDLE param, int value) { + auto iter = m_ints.find(param); + if (iter != m_ints.end()) + { + if (iter->second == value) + { + return; + } + iter->second = value; + } + else + { + m_ints[param] = value; + } m_effect->SetInt(param, value); } void effect::set_bool(D3DXHANDLE param, bool value) { + auto iter = m_bools.find(param); + if (iter != m_bools.end()) + { + if (iter->second == value) + { + return; + } + iter->second = value; + } + else + { + m_bools[param] = value; + } m_effect->SetBool(param, value); } -void effect::set_matrix(D3DXHANDLE param, D3DXMATRIX *matrix) -{ - m_effect->SetMatrix(param, matrix); -} - void effect::set_texture(D3DXHANDLE param, IDirect3DTexture9 *tex) { + auto iter = m_textures.find(param); + if (iter != m_textures.end()) + { + if (iter->second == (void *)tex) + { + return; + } + iter->second = (void *)tex; + } + else + { + m_textures[param] = (void *)tex; + } m_effect->SetTexture(param, tex); } diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h index f72197cb7b1..6820f3dd316 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.h +++ b/src/osd/modules/render/d3d/d3dhlsl.h @@ -2,18 +2,23 @@ // copyright-holders:Aaron Giles //============================================================ // -// drawd3d.c - Win32 Direct3D HLSL-specific header +// drawd3d.h - Win32 Direct3D HLSL-specific header // //============================================================ #ifndef __WIN_D3DHLSL__ #define __WIN_D3DHLSL__ -#include <vector> #include "../frontend/mame/ui/menuitem.h" #include "../frontend/mame/ui/slider.h" #include "modules/lib/osdlib.h" +#include <wrl/client.h> + +#include <map> +#include <memory> +#include <vector> + //============================================================ // TYPE DEFINITIONS //============================================================ @@ -133,11 +138,8 @@ public: effect(shaders *shadersys, IDirect3DDevice9 *dev, const char *name, const char *path); ~effect(); - void begin(UINT *passes, DWORD flags); - void begin_pass(UINT pass); - + void begin(DWORD flags); void end(); - void end_pass(); void set_technique(const char *name); @@ -145,7 +147,6 @@ public: void set_float(D3DXHANDLE param, float value); void set_int(D3DXHANDLE param, int value); void set_bool(D3DXHANDLE param, bool value); - void set_matrix(D3DXHANDLE param, D3DXMATRIX *matrix); void set_texture(D3DXHANDLE param, IDirect3DTexture9 *tex); void add_uniform(const char *name, uniform::uniform_type type, int id); @@ -154,16 +155,26 @@ public: D3DXHANDLE get_parameter(D3DXHANDLE param, const char *name); shaders* get_shaders() { return m_shaders; } + uint32_t num_passes() { return m_num_passes; } bool is_valid() { return m_valid; } + bool is_active() { return m_active; } private: std::vector<std::unique_ptr<uniform>> m_uniform_list; ID3DXEffect *m_effect; shaders *m_shaders; + uint32_t m_num_passes; + + std::map<D3DXHANDLE, D3DXVECTOR4> m_vecs; + std::map<D3DXHANDLE, float> m_floats; + std::map<D3DXHANDLE, int> m_ints; + std::map<D3DXHANDLE, bool> m_bools; + std::map<D3DXHANDLE, void*> m_textures; bool m_valid; + bool m_active; }; class d3d_render_target; @@ -300,11 +311,14 @@ public: shaders(); ~shaders(); - bool init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer); + bool init(IDirect3D9 *d3dobj, running_machine *machine, renderer_d3d9 *renderer); - bool enabled() { return post_fx_enable && d3dintf->post_fx_available; } + bool enabled() { return post_fx_enable && d3d->post_fx_available(); } void toggle() { post_fx_enable = initialized && !post_fx_enable; } + void begin_frame(render_primitive_list *primlist); + void end_frame(); + void begin_draw(); void end_draw(); @@ -323,6 +337,7 @@ public: void init_fsfx_quad(); void set_texture(texture_info *info); + void set_filter(bool filter_screens); void remove_render_target(int source_width, int source_height, uint32_t screen_index); void remove_render_target(d3d_render_target *rt); @@ -336,8 +351,12 @@ public: void *get_slider_option(int id, int index = 0); private: + using IDirect3D9Ptr = Microsoft::WRL::ComPtr<IDirect3D9>; + using IDirect3DTexture9Ptr = Microsoft::WRL::ComPtr<IDirect3DTexture9>; + using IDirect3DSurface9Ptr = Microsoft::WRL::ComPtr<IDirect3DSurface9>; + + void set_curr_effect(effect *curr_effect); void blit(IDirect3DSurface9 *dst, bool clear_dst, D3DPRIMITIVETYPE prim_type, uint32_t prim_index, uint32_t prim_count); - void enumerate_screens(); void render_snapshot(IDirect3DSurface9 *surface); // Time since last call, only updates once per render of all screens @@ -364,7 +383,7 @@ private: int screen_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum); void ui_pass(poly_info *poly, int vertnum); - d3d_base * d3dintf; // D3D interface + IDirect3D9Ptr d3dobj; // D3D interface running_machine * machine; renderer_d3d9 * d3d; // D3D renderer @@ -372,7 +391,10 @@ private: bool post_fx_enable; // overall enable flag bool oversampling_enable; // oversampling enable flag int num_screens; // number of emulated physical screens - int curr_screen; // current screen for render target operations + int num_targets; // number of emulated screen targets (can be different from above; cf. artwork and Laserdisc games) + int curr_target; // current target index for render target operations + int targets_per_screen[256]; // screen target count per screen device/container index; estimated maximum count for array size + int target_to_screen[256]; // lookup from target index to screen device/container index; estimated maximum count for array size double acc_t; // accumulated machine time double delta_t; // data for delta_time bitmap_argb32 shadow_bitmap; // shadow mask bitmap for post-processing shader @@ -383,53 +405,59 @@ private: texture_info * ui_lut_texture; hlsl_options * options; // current options - IDirect3DSurface9 * black_surface; // black dummy surface - IDirect3DTexture9 * black_texture; // black dummy texture + IDirect3DSurface9Ptr black_surface; // black dummy surface + IDirect3DTexture9Ptr black_texture; // black dummy texture bool recording_movie; // ongoing movie recording std::unique_ptr<movie_recorder> recorder; // HLSL post-render movie recorder bool render_snap; // whether or not to take HLSL post-render snapshot - IDirect3DSurface9 * snap_copy_target; // snapshot destination surface in system memory - IDirect3DTexture9 * snap_copy_texture; // snapshot destination surface in system memory - IDirect3DSurface9 * snap_target; // snapshot upscaled surface - IDirect3DTexture9 * snap_texture; // snapshot upscaled texture + IDirect3DSurface9Ptr snap_copy_target; // snapshot destination surface in system memory + IDirect3DTexture9Ptr snap_copy_texture; // snapshot destination surface in system memory + IDirect3DSurface9Ptr snap_target; // snapshot upscaled surface + IDirect3DTexture9Ptr snap_texture; // snapshot upscaled texture int snap_width; // snapshot width int snap_height; // snapshot height bool initialized; // whether or not we're initialized // HLSL effects - IDirect3DSurface9 * backbuffer; // pointer to our device's backbuffer + IDirect3DSurface9Ptr backbuffer; // pointer to our device's backbuffer effect * curr_effect; // pointer to the currently active effect object - effect * default_effect; // pointer to the primary-effect object - effect * prescale_effect; // pointer to the prescale-effect object - effect * post_effect; // pointer to the post-effect object - effect * distortion_effect; // pointer to the distortion-effect object - effect * scanline_effect; - effect * focus_effect; // pointer to the focus-effect object - effect * phosphor_effect; // pointer to the phosphor-effect object - effect * deconverge_effect; // pointer to the deconvergence-effect object - effect * color_effect; // pointer to the color-effect object - effect * ntsc_effect; // pointer to the NTSC effect object - effect * bloom_effect; // pointer to the bloom composite effect - effect * downsample_effect; // pointer to the bloom downsample effect - effect * vector_effect; // pointer to the vector-effect object - effect * chroma_effect; - + std::unique_ptr<effect> default_effect; // pointer to the primary-effect object + std::unique_ptr<effect> ui_effect; // pointer to the UI-element effect object + std::unique_ptr<effect> ui_wrap_effect; // pointer to the UI-element effect object with texture wrapping + std::unique_ptr<effect> vector_buffer_effect; // pointer to the vector-buffering effect object + std::unique_ptr<effect> prescale_effect; // pointer to the prescale-effect object + std::unique_ptr<effect> prescale_point_effect; // pointer to the prescale-effect object with point filtering + std::unique_ptr<effect> post_effect; // pointer to the post-effect object + std::unique_ptr<effect> distortion_effect; // pointer to the distortion-effect object + std::unique_ptr<effect> scanline_effect; + std::unique_ptr<effect> focus_effect; // pointer to the focus-effect object + std::unique_ptr<effect> phosphor_effect; // pointer to the phosphor-effect object + std::unique_ptr<effect> deconverge_effect; // pointer to the deconvergence-effect object + std::unique_ptr<effect> color_effect; // pointer to the color-effect object + std::unique_ptr<effect> ntsc_effect; // pointer to the NTSC effect object + std::unique_ptr<effect> bloom_effect; // pointer to the bloom composite effect + std::unique_ptr<effect> downsample_effect; // pointer to the bloom downsample effect + std::unique_ptr<effect> vector_effect; // pointer to the vector-effect object + std::unique_ptr<effect> chroma_effect; + + texture_info * diffuse_texture; + bool filter_screens; texture_info * curr_texture; d3d_render_target * curr_render_target; poly_info * curr_poly; std::vector<std::unique_ptr<d3d_render_target>> m_render_target_list; - std::vector<slider*> internal_sliders; + std::vector<std::unique_ptr<slider> > internal_sliders; std::vector<ui::menu_item> m_sliders; - std::vector<std::unique_ptr<slider_state>> m_core_sliders; + std::vector<std::unique_ptr<slider_state> > m_core_sliders; static slider_desc s_sliders[]; static hlsl_options last_options; // last used options - static char last_system_name[16]; // last used system + static char last_system_name[MAX_DRIVER_NAME_CHARS + 1]; // last used system osd::dynamic_module::ptr d3dx9_dll; d3dx_create_effect_from_file_fn d3dx_create_effect_from_file_ptr; diff --git a/src/osd/modules/render/draw13.cpp b/src/osd/modules/render/draw13.cpp index af7c8559ca0..a36ee8a8f52 100644 --- a/src/osd/modules/render/draw13.cpp +++ b/src/osd/modules/render/draw13.cpp @@ -2,7 +2,7 @@ // copyright-holders: Couriersud, Olivier Galibert, R. Belmont //============================================================ // -// draw13.c - SDL 2.0 drawing implementation +// draw13.cpp - SDL 2.0 drawing implementation // // SDLMAME by Olivier Galibert and R. Belmont // @@ -10,24 +10,202 @@ // //============================================================ +#include "render_module.h" + +#include "modules/osdmodule.h" + +#if defined(OSD_SDL) + +// OSD headers +#include "sdlopts.h" +#include "window.h" + +// lib/util +#include "options.h" + +// emu +#include "emucore.h" +#include "render.h" + +// standard SDL headers +#include <SDL2/SDL.h> + // standard C headers +#include <algorithm> #include <cmath> #include <cstdio> +#include <iterator> +#include <list> -// MAME headers -#include "emu.h" -#include "options.h" -// OSD headers -#include "osdsdl.h" -#include "window.h" +namespace osd { + +namespace { + +struct quad_setup_data +{ + quad_setup_data() = default; + + void compute(const render_primitive &prim, const int prescale); + + int32_t dudx = 0, dvdx = 0, dudy = 0, dvdy = 0; + int32_t startu = 0, startv = 0; + int32_t rotwidth = 0, rotheight = 0; +}; + +//============================================================ +// Textures +//============================================================ + +class renderer_sdl2; +struct copy_info_t; + +/* texture_info holds information about a texture */ +class texture_info +{ +public: + texture_info(renderer_sdl2 *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const uint32_t flags); + ~texture_info(); + + void set_data(const render_texinfo &texsource, const uint32_t flags); + void render_quad(const render_primitive &prim, const int x, const int y); + bool matches(const render_primitive &prim, const quad_setup_data &setup); + + copy_info_t const *compute_size_type(); + + void *m_pixels; // pixels for the texture + int m_pitch; + + copy_info_t const *m_copyinfo; + quad_setup_data m_setup; + + osd_ticks_t m_last_access; + + int raw_width() const { return m_texinfo.width; } + int raw_height() const { return m_texinfo.height; } + + const render_texinfo &texinfo() const { return m_texinfo; } + render_texinfo &texinfo() { return m_texinfo; } + + HashT hash() const { return m_hash; } + uint32_t flags() const { return m_flags; } + +private: + bool is_pixels_owned() const; + + void set_coloralphamode(SDL_Texture *texture_id, const render_color *color); + + Uint32 m_sdl_access; + renderer_sdl2 * m_renderer; + render_texinfo m_texinfo; // copy of the texture info + HashT m_hash; // hash value for the texture (must be >= pointer size) + uint32_t m_flags; // rendering flags -#include "draw13.h" + SDL_Texture * m_texture_id; + bool m_is_rotated; + + int m_format; // texture format + SDL_BlendMode m_sdl_blendmode; +}; + +// inline functions and macros +#include "blit13.ipp" //============================================================ -// DEBUGGING +// TEXCOPY FUNCS //============================================================ +enum SDL_TEXFORMAT_E +{ + SDL_TEXFORMAT_ARGB32 = 0, + SDL_TEXFORMAT_RGB32, + SDL_TEXFORMAT_RGB32_PALETTED, + SDL_TEXFORMAT_YUY16, + SDL_TEXFORMAT_YUY16_PALETTED, + SDL_TEXFORMAT_PALETTE16, + SDL_TEXFORMAT_RGB15, + SDL_TEXFORMAT_RGB15_PALETTED, + SDL_TEXFORMAT_PALETTE16A, + SDL_TEXFORMAT_PALETTE16_ARGB1555, + SDL_TEXFORMAT_RGB15_ARGB1555, + SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555, + SDL_TEXFORMAT_LAST = SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555 +}; + +struct copy_info_t +{ + int src_fmt; + Uint32 dst_fmt; + const blit_base *blitter; + Uint32 bm_mask; + const char *srcname; + const char *dstname; + /* Statistics */ + mutable uint64_t pixel_count; + mutable int64_t time; + mutable int samples; + mutable int perf; + /* list */ + copy_info_t const *next; +}; + +/* renderer_sdl2 is the information about SDL for the current screen */ +class renderer_sdl2 : public osd_renderer +{ +public: + renderer_sdl2( + osd_window &window, + copy_info_t const *const (&blit_info)[SDL_TEXFORMAT_LAST + 1]); + + virtual ~renderer_sdl2() + { + destroy_all_textures(); + SDL_DestroyRenderer(m_sdl_renderer); + m_sdl_renderer = nullptr; + } + + virtual int create() override; + virtual int draw(const int update) override; + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; + virtual render_primitive_list *get_primitives() override; + + int RendererSupportsFormat(Uint32 format, Uint32 access, const char *sformat); + + SDL_Renderer *m_sdl_renderer; + copy_info_t const *const (&m_blit_info)[SDL_TEXFORMAT_LAST + 1]; + +private: + void render_quad(texture_info *texture, const render_primitive &prim, const int x, const int y); + + texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup); + texture_info *texture_update(const render_primitive &prim); + + void destroy_all_textures(); + + int32_t m_blittimer; + + std::list<texture_info> m_texlist; // list of active textures + + float m_last_hofs; + float m_last_vofs; + + int m_width; + int m_height; + + osd_dim m_blit_dim; + + struct + { + Uint32 format; + int status; + } fmt_support[30]; + + // Stats + int64_t m_last_blit_time; + int64_t m_last_blit_pixels; +}; + + //============================================================ // CONSTANTS //============================================================ @@ -60,9 +238,12 @@ static inline bool is_transparent(const float &a) // CONSTRUCTOR & DESTRUCTOR //============================================================ -renderer_sdl2::renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags) - : osd_renderer(window, FLAG_NEEDS_OPENGL | extra_flags) +renderer_sdl2::renderer_sdl2( + osd_window &window, + copy_info_t const *const (&blit_info)[SDL_TEXFORMAT_LAST + 1]) + : osd_renderer(window) , m_sdl_renderer(nullptr) + , m_blit_info(blit_info) , m_blittimer(0) , m_last_hofs(0) , m_last_vofs(0) @@ -77,112 +258,8 @@ renderer_sdl2::renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags fmt_support[i].format = 0; fmt_support[i].status = 0; } - - if (!s_blit_info_initialized) - { - /* On OSX, calling this from drawsdl2_init will - * prohibit fullscreen toggling. It is than not possible - * to toggle from fullscreen to window mode. - */ - expand_copy_info(s_blit_info_default); - s_blit_info_initialized = true; - } } - -//============================================================ -// STATIC VARIABLES -//============================================================ - -#define BM_ALL (UINT32_MAX) -//( SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD) - -#define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0} -#define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} -#define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} - -const copy_info_t renderer_sdl2::s_blit_info_default[] = -{ - /* no rotation */ - ENTRY(ARGB32, ARGB8888, argb32_argb32), - ENTRY_LR(ARGB32, RGB888, argb32_rgb32), - /* Entry primarily for directfb */ - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD), - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD), - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE), - - ENTRY(RGB32, ARGB8888, rgb32_argb32), - ENTRY(RGB32, RGB888, rgb32_rgb32), - - ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32), - ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32), - - ENTRY(YUY16, UYVY, yuv16_uyvy), - ENTRY(YUY16, YUY2, yuv16_yuy2), - ENTRY(YUY16, YVYU, yuv16_yvyu), - ENTRY(YUY16, ARGB8888, yuv16_argb32), - ENTRY(YUY16, RGB888, yuv16_argb32), - - ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy), - ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2), - ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu), - ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32), - ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32), - - ENTRY(PALETTE16, ARGB8888, pal16_argb32), - ENTRY(PALETTE16, RGB888, pal16_argb32), - - ENTRY(RGB15, RGB555, rgb15_rgb555), - ENTRY(RGB15, ARGB1555, rgb15_argb1555), - ENTRY(RGB15, ARGB8888, rgb15_argb32), - ENTRY(RGB15, RGB888, rgb15_argb32), - - ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32), - ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32), - - ENTRY(PALETTE16A, ARGB8888, pal16a_argb32), - ENTRY(PALETTE16A, RGB888, pal16a_rgb32), - - /* rotation */ - ENTRY(ARGB32, ARGB8888, rot_argb32_argb32), - ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32), - /* Entry primarily for directfb */ - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD), - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD), - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE), - - ENTRY(RGB32, ARGB8888, rot_rgb32_argb32), - ENTRY(RGB32, RGB888, rot_argb32_argb32), - - ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32), - ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32), - - ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot), - ENTRY(YUY16, RGB888, rot_yuv16_argb32rot), - - ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot), - ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot), - - ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32), - ENTRY(PALETTE16, RGB888, rot_pal16_argb32), - - ENTRY(RGB15, RGB555, rot_rgb15_argb1555), - ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555), - ENTRY(RGB15, ARGB8888, rot_rgb15_argb32), - ENTRY(RGB15, RGB888, rot_rgb15_argb32), - - ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32), - ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32), - - ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32), - ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32), - -{ -1 }, -}; - -copy_info_t* renderer_sdl2::s_blit_info[SDL_TEXFORMAT_LAST+1] = { nullptr }; -bool renderer_sdl2::s_blit_info_initialized = false; - //============================================================ // INLINES //============================================================ @@ -277,7 +354,7 @@ void renderer_sdl2::render_quad(texture_info *texture, const render_primitive &p if (texture) { - copy_info_t *copyinfo = texture->m_copyinfo; + copy_info_t const *copyinfo = texture->m_copyinfo; copyinfo->time -= osd_ticks(); texture->render_quad(prim, x, y); copyinfo->time += osd_ticks(); @@ -288,7 +365,7 @@ void renderer_sdl2::render_quad(texture_info *texture, const render_primitive &p copyinfo->time += (m_last_blit_time * (int64_t) (texture->raw_width() * texture->raw_height())) / (int64_t) m_last_blit_pixels; } copyinfo->samples++; - copyinfo->perf = ( texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / texture->m_copyinfo->time; + copyinfo->perf = (texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / std::max<int64_t>(texture->m_copyinfo->time, 1); } else { @@ -329,59 +406,6 @@ int renderer_sdl2::RendererSupportsFormat(Uint32 format, Uint32 access, const ch return 0; } -//============================================================ -// drawsdl_init -//============================================================ - -void renderer_sdl2::add_list(copy_info_t **head, const copy_info_t *element, Uint32 bm) -{ - copy_info_t *newci = new copy_info_t; - *newci = *element; - - newci->bm_mask = bm; - newci->next = *head; - *head = newci; -} - -void renderer_sdl2::expand_copy_info(const copy_info_t *list) -{ - for (const copy_info_t *bi = list; bi->src_fmt != -1; bi++) - { - if (bi->bm_mask == BM_ALL) - { - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_NONE); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_ADD); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_MOD); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_BLEND); - } - else - { - add_list(&s_blit_info[bi->src_fmt], bi, bi->bm_mask); - } - } -} - -// FIXME: machine only used to access options. -void renderer_sdl2::init(running_machine &machine) -{ - osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n"); - -#if USE_OPENGL - // Load the GL library now - else MT will fail - const char *stemp = downcast<sdl_options &>(machine.options()).gl_lib(); -#else - const char *stemp = nullptr; -#endif - if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) == 0) - stemp = nullptr; - - // No fatalerror here since not all video drivers support GL ! - if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==nullptr - osd_printf_warning("Warning: Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); - else - osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); -} - //============================================================ // sdl_info::create @@ -434,12 +458,10 @@ int renderer_sdl2::create() SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); } - auto win = assert_window(); - if (video_config.waitvsync) - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); else - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_ACCELERATED); if (!m_sdl_renderer) { @@ -483,18 +505,14 @@ int renderer_sdl2::xy_to_render_target(int x, int y, int *xt, int *yt) void renderer_sdl2::destroy_all_textures() { - auto win = assert_window(); - if (win == nullptr) - return; - - if(win->m_primlist) + if (window().m_primlist) { - win->m_primlist->acquire_lock(); - m_texlist.reset(); - win->m_primlist->release_lock(); + window().m_primlist->acquire_lock(); + m_texlist.clear(); + window().m_primlist->release_lock(); } else - m_texlist.reset(); + m_texlist.clear(); } //============================================================ @@ -507,13 +525,7 @@ int renderer_sdl2::draw(int update) float vofs, hofs; int blit_pixels = 0; - if (video_config.novideo) - { - return 0; - } - - auto win = assert_window(); - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) { @@ -560,10 +572,10 @@ int renderer_sdl2::draw(int update) m_last_hofs = hofs; m_last_vofs = vofs; - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // now draw - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { Uint8 sr, sg, sb, sa; @@ -593,7 +605,7 @@ int renderer_sdl2::draw(int update) } } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); m_last_blit_pixels = blit_pixels; m_last_blit_time = -osd_ticks(); @@ -612,22 +624,23 @@ int renderer_sdl2::draw(int update) // texture_compute_size and type //============================================================ -copy_info_t *texture_info::compute_size_type() +copy_info_t const *texture_info::compute_size_type() { - copy_info_t *result = nullptr; + copy_info_t const *result = nullptr; int maxperf = 0; - for (copy_info_t *bi = renderer_sdl2::s_blit_info[m_format]; bi != nullptr; bi = bi->next) + for (copy_info_t const *bi = m_renderer->m_blit_info[m_format]; bi != nullptr; bi = bi->next) { - if ((m_is_rotated == bi->blitter->m_is_rot) - && (m_sdl_blendmode == bi->bm_mask)) + if ((m_is_rotated == bi->blitter->m_is_rot) && (m_sdl_blendmode == bi->bm_mask)) { if (m_renderer->RendererSupportsFormat(bi->dst_fmt, m_sdl_access, bi->dstname)) { - int perf = bi->perf; + int const perf = bi->perf; if (perf == 0) + { return bi; - else if (perf > (maxperf * 102) / 100) + } + else if (perf > ((maxperf * 102) / 100)) { result = bi; maxperf = perf; @@ -639,23 +652,21 @@ copy_info_t *texture_info::compute_size_type() if (result) return result; - /* try last resort handlers */ - for (copy_info_t *bi = renderer_sdl2::s_blit_info[m_format]; bi != nullptr; bi = bi->next) + // try last resort handlers + for (copy_info_t const *bi = m_renderer->m_blit_info[m_format]; bi != nullptr; bi = bi->next) { - if ((m_is_rotated == bi->blitter->m_is_rot) - && (m_sdl_blendmode == bi->bm_mask)) + if ((m_is_rotated == bi->blitter->m_is_rot) && (m_sdl_blendmode == bi->bm_mask)) if (m_renderer->RendererSupportsFormat(bi->dst_fmt, m_sdl_access, bi->dstname)) return bi; } - //FIXME: crash implement a -do nothing handler */ + //FIXME: crash implement a -do nothing handler return nullptr; } -// FIXME: bool texture_info::is_pixels_owned() const -{ // do we own / allocated it ? - return ((m_sdl_access == SDL_TEXTUREACCESS_STATIC) - && (m_copyinfo->blitter->m_is_passthrough)); +{ + // do we own / allocated it ? + return (m_sdl_access == SDL_TEXTUREACCESS_STATIC) && !m_copyinfo->blitter->m_is_passthrough; } //============================================================ @@ -745,12 +756,11 @@ texture_info::texture_info(renderer_sdl2 *renderer, const render_texinfo &texsou m_pixels = malloc(m_setup.rotwidth * m_setup.rotheight * m_copyinfo->blitter->m_dest_bpp); } m_last_access = osd_ticks(); - } texture_info::~texture_info() { - if ( is_pixels_owned() && (m_pixels != nullptr) ) + if (is_pixels_owned() && m_pixels) free(m_pixels); SDL_DestroyTexture(m_texture_id); } @@ -764,7 +774,7 @@ void texture_info::set_data(const render_texinfo &texsource, const uint32_t flag m_copyinfo->time -= osd_ticks(); if (m_sdl_access == SDL_TEXTUREACCESS_STATIC) { - if ( m_copyinfo->blitter->m_is_passthrough ) + if (m_copyinfo->blitter->m_is_passthrough) { m_pixels = texsource.base; m_pitch = m_texinfo.rowpixels * m_copyinfo->blitter->m_dest_bpp; @@ -778,11 +788,11 @@ void texture_info::set_data(const render_texinfo &texsource, const uint32_t flag } else { - SDL_LockTexture(m_texture_id, nullptr, (void **) &m_pixels, &m_pitch); + SDL_LockTexture(m_texture_id, nullptr, (void **)&m_pixels, &m_pitch); if ( m_copyinfo->blitter->m_is_passthrough ) { - uint8_t *src = (uint8_t *) texsource.base; - uint8_t *dst = (uint8_t *) m_pixels; + const uint8_t *src = (uint8_t *)texsource.base; + uint8_t *dst = (uint8_t *)m_pixels; int spitch = texsource.rowpixels * m_copyinfo->blitter->m_dest_bpp; int num = texsource.width * m_copyinfo->blitter->m_dest_bpp; int h = texsource.height; @@ -868,64 +878,38 @@ void quad_setup_data::compute(const render_primitive &prim, const int prescale) texture_info *renderer_sdl2::texture_find(const render_primitive &prim, const quad_setup_data &setup) { - HashT texhash = texture_compute_hash(prim.texture, prim.flags); - texture_info *texture; - osd_ticks_t now = osd_ticks(); + const HashT texhash = texture_compute_hash(prim.texture, prim.flags); + const osd_ticks_t now = osd_ticks(); // find a match - for (texture = m_texlist.first(); texture != nullptr; ) - if (texture->hash() == texhash && - texture->matches(prim, setup)) + for (auto texture = m_texlist.begin(); texture != m_texlist.end(); ) + { + if ((texture->hash() == texhash) && texture->matches(prim, setup)) { - /* would we choose another blitter based on performance ? */ + // would we choose another blitter based on performance? if ((texture->m_copyinfo->samples & 0x7f) == 0x7f) { if (texture->m_copyinfo != texture->compute_size_type()) return nullptr; } texture->m_last_access = now; - return texture; + return &*texture; } else { - /* free resources not needed any longer? */ - texture_info *expire = texture; - texture = texture->next(); - if (now - expire->m_last_access > osd_ticks_per_second()) - m_texlist.remove(*expire); + // free resources not needed any longer? + if ((now - texture->m_last_access) > osd_ticks_per_second()) + texture = m_texlist.erase(texture); + else + ++texture; } + } // nothing found return nullptr; } //============================================================ -// exit -//============================================================ - -void renderer_sdl2::exit() -{ - if (s_blit_info_initialized) - { - for (int i = 0; i <= SDL_TEXFORMAT_LAST; i++) - { - for (copy_info_t *bi = s_blit_info[i]; bi != nullptr; ) - { - if (bi->pixel_count) - osd_printf_verbose("%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", bi->srcname, bi->dstname, - bi->blitter->m_is_rot ? "rot" : "norot", bi->bm_mask, bi->samples, - (int) bi->perf); - copy_info_t *freeme = bi; - bi = bi->next; - delete freeme; - } - s_blit_info[i] = nullptr; - } - s_blit_info_initialized = false; - } -} - -//============================================================ // texture_update //============================================================ @@ -934,22 +918,20 @@ texture_info * renderer_sdl2::texture_update(const render_primitive &prim) quad_setup_data setup; texture_info *texture; - auto win = assert_window(); - setup.compute(prim, win->prescale()); + setup.compute(prim, window().prescale()); texture = texture_find(prim, setup); // if we didn't find one, create a new texture - if (texture == nullptr && prim.texture.base != nullptr) + if (!texture && prim.texture.base) { - texture = new texture_info(this, prim.texture, setup, prim.flags); - /* add us to the texture list */ - m_texlist.prepend(*texture); + // add us to the texture list + texture = &m_texlist.emplace_front(this, prim.texture, setup, prim.flags); } - if (texture != nullptr) + if (texture) { - if (prim.texture.base != nullptr && texture->texinfo().seqid != prim.texture.seqid) + if (prim.texture.base && (texture->texinfo().seqid != prim.texture.seqid)) { texture->texinfo().seqid = prim.texture.seqid; // if we found it, but with a different seqid, copy the data @@ -962,16 +944,249 @@ texture_info * renderer_sdl2::texture_update(const render_primitive &prim) render_primitive_list *renderer_sdl2::get_primitives() { - auto win = assert_window(); - if (win == nullptr) - return nullptr; - - osd_dim nd = win->get_size(); + osd_dim nd = window().get_size(); if (nd != m_blit_dim) { m_blit_dim = nd; notify_changed(); } - win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); +} + + +class video_sdl2 : public osd_module, public render_module +{ +public: + video_sdl2() + : osd_module(OSD_RENDERER_PROVIDER, "accel") + , m_blit_info_initialized(false) + , m_gllib_loaded(false) + { + std::fill(std::begin(m_blit_info), std::end(m_blit_info), nullptr); + } + ~video_sdl2() + { + free_copy_info(); + } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override { free_copy_info(); } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE | FLAG_SDL_NEEDS_OPENGL; } + +private: + static inline constexpr Uint32 BM_ALL = UINT32_MAX; // SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD + + void expand_copy_info(); + void free_copy_info(); + + static void add_list(copy_info_t const *&head, copy_info_t const &element, Uint32 bm); + + copy_info_t const *m_blit_info[SDL_TEXFORMAT_LAST + 1]; + bool m_blit_info_initialized; + bool m_gllib_loaded; + + static copy_info_t const s_blit_info_default[]; +}; + +int video_sdl2::init(osd_interface &osd, osd_options const &options) +{ + osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n"); + + // Load the GL library now - else MT will fail + char const *libname = nullptr; +#if USE_OPENGL + libname = dynamic_cast<sdl_options const &>(options).gl_lib(); + if (libname && (!*libname || !std::strcmp(libname, OSDOPTVAL_AUTO))) + libname = nullptr; +#endif + + if (!m_gllib_loaded) + { + // No fatalerror here since not all video drivers support GL! + if (SDL_GL_LoadLibrary(libname) != 0) + { + osd_printf_error("Unable to load OpenGL shared library: %s\n", libname ? libname : "<default>"); + m_gllib_loaded = true; + } + else + { + osd_printf_verbose("Loaded OpenGL shared library: %s\n", libname ? libname : "<default>"); + } + } + + return 0; +} + +std::unique_ptr<osd_renderer> video_sdl2::create(osd_window &window) +{ + if (!m_blit_info_initialized) + { + // On macOS, calling this from drawsdl2_init will prohibit fullscreen toggling. + // It is than not possible to toggle from fullscreen to window mode. + expand_copy_info(); + m_blit_info_initialized = true; + } + + return std::make_unique<renderer_sdl2>(window, m_blit_info); +} + +void video_sdl2::expand_copy_info() +{ + for (const copy_info_t *bi = s_blit_info_default; bi->src_fmt != -1; bi++) + { + if (bi->bm_mask == BM_ALL) + { + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_NONE); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_ADD); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_MOD); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_BLEND); + } + else + { + add_list(m_blit_info[bi->src_fmt], *bi, bi->bm_mask); + } + } +} + +void video_sdl2::free_copy_info() +{ + if (m_blit_info_initialized) + { + for (int i = 0; i <= SDL_TEXFORMAT_LAST; i++) + { + for (copy_info_t const *bi = m_blit_info[i]; bi != nullptr; ) + { + if (bi->pixel_count) + { + osd_printf_verbose( + "%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", + bi->srcname, + bi->dstname, + bi->blitter->m_is_rot ? "rot" : "norot", + bi->bm_mask, + bi->samples, + bi->perf); + } + delete std::exchange(bi, bi->next); + } + m_blit_info[i] = nullptr; + } + m_blit_info_initialized = false; + } +} + +void video_sdl2::add_list(copy_info_t const *&head, copy_info_t const &element, Uint32 bm) +{ + copy_info_t *const newci = new copy_info_t(element); + + newci->bm_mask = bm; + newci->next = head; + head = newci; } + + +//============================================================ +// STATIC VARIABLES +//============================================================ + +#define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0} +#define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} +#define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} + +copy_info_t const video_sdl2::s_blit_info_default[] = +{ + /* no rotation */ + ENTRY(ARGB32, ARGB8888, argb32_argb32), + ENTRY_LR(ARGB32, RGB888, argb32_rgb32), + /* Entry primarily for directfb */ + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD), + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD), + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE), + + ENTRY(RGB32, ARGB8888, rgb32_argb32), + ENTRY(RGB32, RGB888, rgb32_rgb32), + + ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32), + ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32), + + ENTRY(YUY16, UYVY, yuv16_uyvy), + ENTRY(YUY16, YUY2, yuv16_yuy2), + ENTRY(YUY16, YVYU, yuv16_yvyu), + ENTRY(YUY16, ARGB8888, yuv16_argb32), + ENTRY(YUY16, RGB888, yuv16_argb32), + + ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy), + ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2), + ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu), + ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32), + ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32), + + ENTRY(PALETTE16, ARGB8888, pal16_argb32), + ENTRY(PALETTE16, RGB888, pal16_argb32), + + ENTRY(RGB15, RGB555, rgb15_rgb555), + ENTRY(RGB15, ARGB1555, rgb15_argb1555), + ENTRY(RGB15, ARGB8888, rgb15_argb32), + ENTRY(RGB15, RGB888, rgb15_argb32), + + ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32), + ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32), + + ENTRY(PALETTE16A, ARGB8888, pal16a_argb32), + ENTRY(PALETTE16A, RGB888, pal16a_rgb32), + + /* rotation */ + ENTRY(ARGB32, ARGB8888, rot_argb32_argb32), + ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32), + /* Entry primarily for directfb */ + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD), + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD), + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE), + + ENTRY(RGB32, ARGB8888, rot_rgb32_argb32), + ENTRY(RGB32, RGB888, rot_argb32_argb32), + + ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32), + ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32), + + ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot), + ENTRY(YUY16, RGB888, rot_yuv16_argb32rot), + + ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot), + ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot), + + ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32), + ENTRY(PALETTE16, RGB888, rot_pal16_argb32), + + ENTRY(RGB15, RGB555, rot_rgb15_argb1555), + ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555), + ENTRY(RGB15, ARGB8888, rot_rgb15_argb32), + ENTRY(RGB15, RGB888, rot_rgb15_argb32), + + ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32), + ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32), + + ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32), + ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32), + + { -1 }, +}; + +} // anonymous namespace + +} // namespace osd + + +#else // defined(OSD_SDL) + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_sdl2, OSD_RENDERER_PROVIDER, "accel") } } + +#endif // defined(OSD_SDL) + + +MODULE_DEFINITION(RENDERER_SDL2, osd::video_sdl2) diff --git a/src/osd/modules/render/draw13.h b/src/osd/modules/render/draw13.h deleted file mode 100644 index d69c84c1c9d..00000000000 --- a/src/osd/modules/render/draw13.h +++ /dev/null @@ -1,216 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Couriersud, Olivier Galibert, R. Belmont -//============================================================ -// -// draw13.h - SDL 2.0 drawing implementation -// -// SDLMAME by Olivier Galibert and R. Belmont -// -//============================================================ - -#ifndef MAME_OSD_MODULES_RENDER_DRAW13_H -#define MAME_OSD_MODULES_RENDER_DRAW13_H - -#pragma once - -// OSD headers -#ifndef OSD_WINDOWS -#include "osdsdl.h" -#include "window.h" -#else -#include "../windows/window.h" -typedef uint64_t HashT; -#endif - -// standard SDL headers -#include <SDL2/SDL.h> - -#include "emucore.h" -#include "render.h" - -struct quad_setup_data -{ - quad_setup_data() - : dudx(0) - , dvdx(0) - , dudy(0) - , dvdy(0) - , startu(0) - , startv(0) - , rotwidth(0) - , rotheight(0) - { - } - - void compute(const render_primitive &prim, const int prescale); - - int32_t dudx, dvdx, dudy, dvdy; - int32_t startu, startv; - int32_t rotwidth, rotheight; -}; - -//============================================================ -// Textures -//============================================================ - -class renderer_sdl2; -struct copy_info_t; - -/* texture_info holds information about a texture */ -class texture_info -{ - friend class simple_list<texture_info>; -public: - texture_info(renderer_sdl2 *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const uint32_t flags); - ~texture_info(); - - void set_data(const render_texinfo &texsource, const uint32_t flags); - void render_quad(const render_primitive &prim, const int x, const int y); - bool matches(const render_primitive &prim, const quad_setup_data &setup); - - copy_info_t *compute_size_type(); - - void *m_pixels; // pixels for the texture - int m_pitch; - - copy_info_t *m_copyinfo; - quad_setup_data m_setup; - - osd_ticks_t m_last_access; - - int raw_width() const { return m_texinfo.width; } - int raw_height() const { return m_texinfo.height; } - - texture_info *next() { return m_next; } - const render_texinfo &texinfo() const { return m_texinfo; } - render_texinfo &texinfo() { return m_texinfo; } - - HashT hash() const { return m_hash; } - uint32_t flags() const { return m_flags; } - // FIXME: - bool is_pixels_owned() const; - -private: - void set_coloralphamode(SDL_Texture *texture_id, const render_color *color); - - Uint32 m_sdl_access; - renderer_sdl2 * m_renderer; - render_texinfo m_texinfo; // copy of the texture info - HashT m_hash; // hash value for the texture (must be >= pointer size) - uint32_t m_flags; // rendering flags - - SDL_Texture * m_texture_id; - bool m_is_rotated; - - int m_format; // texture format - SDL_BlendMode m_sdl_blendmode; - - texture_info * m_next; // next texture in the list -}; - -//============================================================ -// TEXCOPY FUNCS -//============================================================ - -enum SDL_TEXFORMAT_E -{ - SDL_TEXFORMAT_ARGB32 = 0, - SDL_TEXFORMAT_RGB32, - SDL_TEXFORMAT_RGB32_PALETTED, - SDL_TEXFORMAT_YUY16, - SDL_TEXFORMAT_YUY16_PALETTED, - SDL_TEXFORMAT_PALETTE16, - SDL_TEXFORMAT_RGB15, - SDL_TEXFORMAT_RGB15_PALETTED, - SDL_TEXFORMAT_PALETTE16A, - SDL_TEXFORMAT_PALETTE16_ARGB1555, - SDL_TEXFORMAT_RGB15_ARGB1555, - SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555, - SDL_TEXFORMAT_LAST = SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555 -}; - -#include "blit13.h" - -struct copy_info_t -{ - int src_fmt; - Uint32 dst_fmt; - const blit_base *blitter; - Uint32 bm_mask; - const char *srcname; - const char *dstname; - /* Statistics */ - uint64_t pixel_count; - int64_t time; - int samples; - int perf; - /* list */ - copy_info_t *next; -}; - -/* renderer_sdl2 is the information about SDL for the current screen */ -class renderer_sdl2 : public osd_renderer -{ -public: - renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags); - - virtual ~renderer_sdl2() - { - destroy_all_textures(); - SDL_DestroyRenderer(m_sdl_renderer); - m_sdl_renderer = nullptr; - } - - static void init(running_machine &machine); - static void exit(); - - virtual int create() override; - virtual int draw(const int update) override; - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; - virtual render_primitive_list *get_primitives() override; - - int RendererSupportsFormat(Uint32 format, Uint32 access, const char *sformat); - - SDL_Renderer * m_sdl_renderer; - - static copy_info_t* s_blit_info[SDL_TEXFORMAT_LAST+1]; - -private: - void expand_copy_info(const copy_info_t *list); - void add_list(copy_info_t **head, const copy_info_t *element, Uint32 bm); - - void render_quad(texture_info *texture, const render_primitive &prim, const int x, const int y); - - texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup); - texture_info *texture_update(const render_primitive &prim); - - void destroy_all_textures(); - - int32_t m_blittimer; - - - simple_list<texture_info> m_texlist; // list of active textures - - float m_last_hofs; - float m_last_vofs; - - int m_width; - int m_height; - - osd_dim m_blit_dim; - - struct - { - Uint32 format; - int status; - } fmt_support[30]; - - // Stats - int64_t m_last_blit_time; - int64_t m_last_blit_pixels; - - static bool s_blit_info_initialized; - static const copy_info_t s_blit_info_default[]; -}; - -#endif // MAME_OSD_MODULES_RENDER_DRAW13_H diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp index fc9214fe446..36758914961 100644 --- a/src/osd/modules/render/drawbgfx.cpp +++ b/src/osd/modules/render/drawbgfx.cpp @@ -5,6 +5,40 @@ // drawbgfx.cpp - BGFX renderer // //============================================================ + +#include "drawbgfx.h" + +// render/bgfx +#include "bgfx/effect.h" +#include "bgfx/effectmanager.h" +#include "bgfx/shadermanager.h" +#include "bgfx/slider.h" +#include "bgfx/target.h" +#include "bgfx/target.h" +#include "bgfx/targetmanager.h" +#include "bgfx/texture.h" +#include "bgfx/texturemanager.h" +#include "bgfx/uniform.h" +#include "bgfx/view.h" + +// render +#include "aviwrite.h" +#include "bgfxutil.h" +#include "render_module.h" + +// emu +#include "emu.h" +#include "config.h" +#include "render.h" +#include "rendutil.h" + +// util +#include "util/xmlfile.h" + +// OSD +#include "modules/lib/osdobj_common.h" +#include "window.h" + #include <bx/math.h> #include <bx/readerwriter.h> @@ -22,334 +56,658 @@ extern void *GetOSWindow(void *wincontroller); #endif #endif -// MAMEOS headers -#include "emu.h" -#include "window.h" -#include "render.h" -#include "rendutil.h" -#include "aviwrite.h" +#if defined(SDLMAME_USE_WAYLAND) +#include <wayland-egl.h> +#endif #include <bgfx/bgfx.h> #include <bgfx/platform.h> -#include <algorithm> -#include "drawbgfx.h" -#include "bgfxutil.h" -#include "bgfx/texturemanager.h" -#include "bgfx/targetmanager.h" -#include "bgfx/shadermanager.h" -#include "bgfx/effectmanager.h" -#include "bgfx/chainmanager.h" -#include "bgfx/effect.h" -#include "bgfx/texture.h" -#include "bgfx/target.h" -#include "bgfx/chain.h" -#include "bgfx/vertex.h" -#include "bgfx/uniform.h" -#include "bgfx/slider.h" -#include "bgfx/target.h" -#include "bgfx/view.h" +#include "imgui/imgui.h" -#include "modules/lib/osdobj_common.h" +#include <algorithm> -#include "imgui/imgui.h" //============================================================ -// DEBUGGING +// Renderer interface to parent module //============================================================ -//============================================================ -// CONSTANTS -//============================================================ +class renderer_bgfx::parent_module +{ +public: + util::xml::data_node &persistent_settings() { return *m_persistent_settings; } + osd_options const &options() const { return *m_options; } + uint32_t max_texture_size() const { return m_max_texture_size; } + + template <typename T> + util::notifier_subscription subscribe_load(void (T::*func)(util::xml::data_node const &), T *obj) + { + return m_load_notifier.subscribe(delegate<void (util::xml::data_node const &)>(func, obj)); + } + + template <typename T> + util::notifier_subscription subscribe_save(void (T::*func)(util::xml::data_node &), T *obj) + { + return m_save_notifier.subscribe(delegate<void (util::xml::data_node &)>(func, obj)); + } + +protected: + parent_module() + : m_options(nullptr) + , m_max_texture_size(0) + , m_renderer_count(0) + { + } + virtual ~parent_module() + { + assert(!m_renderer_count); + } + + bool has_active_renderers() const + { + return 0 < m_renderer_count; + } + + util::notifier<util::xml::data_node const &> m_load_notifier; + util::notifier<util::xml::data_node &> m_save_notifier; + util::xml::file::ptr m_persistent_settings; + osd_options const *m_options; + uint32_t m_max_texture_size; + +private: + friend class parent_module_holder; + + virtual void last_renderer_destroyed() = 0; + + void renderer_created() + { + ++m_renderer_count; + } + + void renderer_destroyed() + { + assert(m_renderer_count); + if (!--m_renderer_count) + last_renderer_destroyed(); + } + + unsigned m_renderer_count; +}; + + +inline renderer_bgfx::parent_module_holder::parent_module_holder(parent_module &parent) + : m_parent(parent) +{ + m_parent.renderer_created(); +} + + +inline renderer_bgfx::parent_module_holder::~parent_module_holder() +{ + m_parent.renderer_destroyed(); +} + -uint16_t const renderer_bgfx::CACHE_SIZE = 1024; -uint32_t const renderer_bgfx::PACKABLE_SIZE = 128; -uint32_t const renderer_bgfx::WHITE_HASH = 0x87654321; -char const *const renderer_bgfx::WINDOW_PREFIX = "Window 0, "; //============================================================ -// MACROS +// OSD MODULE //============================================================ -#define GIBBERISH (0) -#define SCENE_VIEW (0) +namespace osd { + +namespace { + +class video_bgfx : public osd_module, public render_module, protected renderer_bgfx::parent_module +{ +public: + video_bgfx() + : osd_module(OSD_RENDERER_PROVIDER, "bgfx") + , m_bgfx_library_initialized(false) + { + } + ~video_bgfx() { exit(); } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE; } + +private: + virtual void last_renderer_destroyed() override; + + void load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode); + void save_config(config_type cfg_type, util::xml::data_node *parentnode); + + bool init_bgfx_library(osd_window &window); + + static bool set_platform_data(bgfx::PlatformData &platform_data, osd_window const &window); + + bool m_bgfx_library_initialized; +}; + //============================================================ -// STATICS +// video_bgfx::init //============================================================ -uint32_t renderer_bgfx::s_current_view = 0; -bool renderer_bgfx::s_bgfx_library_initialized = false; -uint32_t renderer_bgfx::s_width[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -uint32_t renderer_bgfx::s_height[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +int video_bgfx::init(osd_interface &osd, osd_options const &options) +{ + m_options = &options; + m_persistent_settings = util::xml::file::create(); + + // Check that BGFX directory exists + char const *const bgfx_path = options.bgfx_path(); + osd::directory::ptr directory = osd::directory::open(bgfx_path); + if (!directory) + { + osd_printf_error("Unable to find the BGFX path %s, please install it or fix the bgfx_path setting to use the BGFX renderer.\n", bgfx_path); + return -1; + } + directory.reset(); + + // Verify baseline shaders + const bool gui_opaque_valid = effect_manager::validate_effect(options, "gui_opaque"); + const bool gui_blend_valid = effect_manager::validate_effect(options, "gui_blend"); + const bool gui_multiply_valid = effect_manager::validate_effect(options, "gui_multiply"); + const bool gui_add_valid = effect_manager::validate_effect(options, "gui_add"); + const bool all_gui_valid = gui_opaque_valid && gui_blend_valid && gui_multiply_valid && gui_add_valid; + + const bool screen_opaque_valid = effect_manager::validate_effect(options, "screen_opaque"); + const bool screen_blend_valid = effect_manager::validate_effect(options, "screen_blend"); + const bool screen_multiply_valid = effect_manager::validate_effect(options, "screen_multiply"); + const bool screen_add_valid = effect_manager::validate_effect(options, "screen_add"); + const bool all_screen_valid = screen_opaque_valid && screen_blend_valid && screen_multiply_valid && screen_add_valid; + + if (!all_gui_valid || !all_screen_valid) + { + osd_printf_error("BGFX: Unable to load required shaders. Please update the %s folder or adjust your bgfx_path setting.\n", options.bgfx_path()); + return -1; + } + + m_max_texture_size = 16384; // Relatively safe default on modern GPUs + + // Register configuration handlers - do this last because it can't be undone + downcast<osd_common_t &>(osd).machine().configuration().config_register( + "bgfx", + configuration_manager::load_delegate(&video_bgfx::load_config, this), + configuration_manager::save_delegate(&video_bgfx::save_config, this)); + + return 0; +} + //============================================================ -// renderer_bgfx - constructor +// video_bgfx::exit //============================================================ -renderer_bgfx::renderer_bgfx(std::shared_ptr<osd_window> w) - : osd_renderer(w, FLAG_NONE) - , m_options(downcast<osd_options &>(w->machine().options())) - , m_framebuffer(nullptr) - , m_texture_cache(nullptr) - , m_dimensions(0, 0) - , m_textures(nullptr) - , m_targets(nullptr) - , m_shaders(nullptr) - , m_effects(nullptr) - , m_chains(nullptr) - , m_ortho_view(nullptr) - , m_max_view(0) - , m_avi_view(nullptr) - , m_avi_writer(nullptr) - , m_avi_target(nullptr) +void video_bgfx::exit() { + assert(!has_active_renderers()); + + if (m_bgfx_library_initialized) + { + osd_printf_verbose("Shutting down BGFX library\n"); + imguiDestroy(); + bgfx::shutdown(); + m_bgfx_library_initialized = false; + } + m_max_texture_size = 0; + m_persistent_settings.reset(); + m_options = nullptr; } + //============================================================ -// renderer_bgfx - destructor +// video_bgfx::create //============================================================ -renderer_bgfx::~renderer_bgfx() +std::unique_ptr<osd_renderer> video_bgfx::create(osd_window &window) { - bgfx::reset(0, 0, BGFX_RESET_NONE); - - if (m_avi_writer != nullptr && m_avi_writer->recording()) + // start BGFX if this is the first window + if (!m_bgfx_library_initialized) { - m_avi_writer->stop(); + assert(window.index() == 0); // bad things will happen otherwise + assert(!has_active_renderers()); - m_targets->destroy_target("avibuffer0"); - m_avi_target = nullptr; + osd_printf_verbose("Initializing BGFX library\n"); + if (!init_bgfx_library(window)) + { + osd_printf_error("BGFX library initialization failed\n"); + return nullptr; + } + m_bgfx_library_initialized = true; + } - bgfx::destroy(m_avi_texture); + return std::make_unique<renderer_bgfx>(window, static_cast<renderer_bgfx::parent_module &>(*this)); +} - delete m_avi_writer; - delete [] m_avi_data; - delete m_avi_view; + +//============================================================ +// video_bgfx::last_renderer_destroyed +//============================================================ + +void video_bgfx::last_renderer_destroyed() +{ + if (m_bgfx_library_initialized) + { + osd_printf_verbose("No more renderers - shutting down BGFX library\n"); + imguiDestroy(); + bgfx::shutdown(); + m_bgfx_library_initialized = false; + m_max_texture_size = 0; } +} - // Cleanup. - if (m_ortho_view) - delete m_ortho_view; - delete m_chains; - delete m_effects; - delete m_shaders; - delete m_textures; - delete m_targets; +//============================================================ +// video_bgfx::load_config +//============================================================ + +void video_bgfx::load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode) +{ + if ((cfg_type == config_type::SYSTEM) && parentnode) + m_load_notifier(*parentnode); } +//============================================================ +// video_bgfx::save_config +//============================================================ + +void video_bgfx::save_config(config_type cfg_type, util::xml::data_node *parentnode) +{ + if (cfg_type == config_type::SYSTEM) + m_save_notifier(*parentnode); +} + //============================================================ -// renderer_bgfx::init_bgfx_library +// video_bgfx::init_bgfx_library //============================================================ -void renderer_bgfx::init_bgfx_library() +bool video_bgfx::init_bgfx_library(osd_window &window) { - std::string backend(m_options.bgfx_backend()); + osd_dim const wdim = window.get_size(); bgfx::Init init; init.type = bgfx::RendererType::Count; init.vendorId = BGFX_PCI_ID_NONE; - init.resolution.width = s_width[0]; - init.resolution.height = s_height[0]; + init.resolution.width = wdim.width(); + init.resolution.height = wdim.height(); init.resolution.numBackBuffers = 1; - init.resolution.reset = BGFX_RESET_NONE; - init.platformData = m_platform_data; - if (backend == "auto") + init.resolution.reset = video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE; + if (!set_platform_data(init.platformData, window)) { + osd_printf_error("Setting BGFX platform data failed\n"); + return false; } + + std::string_view const backend(m_options->bgfx_backend()); + if (backend == "auto") + ; // do nothing else if (backend == "dx9" || backend == "d3d9") - { init.type = bgfx::RendererType::Direct3D9; - } else if (backend == "dx11" || backend == "d3d11") - { init.type = bgfx::RendererType::Direct3D11; - } else if (backend == "dx12" || backend == "d3d12") - { init.type = bgfx::RendererType::Direct3D12; - } else if (backend == "gles") - { init.type = bgfx::RendererType::OpenGLES; - } else if (backend == "glsl" || backend == "opengl") - { init.type = bgfx::RendererType::OpenGL; - } else if (backend == "vulkan") - { init.type = bgfx::RendererType::Vulkan; - } else if (backend == "metal") - { init.type = bgfx::RendererType::Metal; - } else - { - osd_printf_verbose("Unknown backend type '%s', going with auto-detection.\n", backend.c_str()); - } + osd_printf_warning("Unknown BGFX backend type '%s', going with auto-detection.\n", backend); - bgfx::init(init); - bgfx::reset(s_width[0], s_height[0], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); - // Enable debug text if requested. - bool bgfx_debug = m_options.bgfx_debug(); + if (!bgfx::init(init)) + return false; + + bgfx::reset(wdim.width(), wdim.height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); + + // Enable debug text if requested + bool bgfx_debug = m_options->bgfx_debug(); bgfx::setDebug(bgfx_debug ? BGFX_DEBUG_STATS : BGFX_DEBUG_TEXT); + // Get actual maximum texture size + bgfx::Caps const *const caps = bgfx::getCaps(); + m_max_texture_size = caps->limits.maxTextureSize; + ScreenVertex::init(); imguiCreate(); -} + return true; +} //============================================================ -// Utilities for setting up window handles +// Helper for creating a wayland window //============================================================ -#ifdef OSD_WINDOWS -inline void winSetHwnd(bgfx::PlatformData &platform_data, ::HWND _window) -{ - platform_data.ndt = NULL; - platform_data.nwh = _window; - platform_data.context = NULL; - platform_data.backBuffer = NULL; - platform_data.backBufferDS = NULL; - bgfx::setPlatformData(platform_data); -} -#elif defined(OSD_MAC) -inline void macSetWindow(bgfx::PlatformData &platform_data, void *_window) -{ - platform_data.ndt = NULL; - platform_data.nwh = GetOSWindow(_window); - platform_data.context = NULL; - platform_data.backBuffer = NULL; - platform_data.backBufferDS = NULL; - bgfx::setPlatformData(platform_data); -} -#elif defined(OSD_SDL) -static void* sdlNativeWindowHandle(SDL_Window* _window) +#if defined(SDLMAME_USE_WAYLAND) +wl_egl_window *create_wl_egl_window(SDL_Window *window, struct wl_surface *surface) { - SDL_SysWMinfo wmi; - SDL_VERSION(&wmi.version); - if (!SDL_GetWindowWMInfo(_window, &wmi)) + if (!surface) { + osd_printf_error("Wayland surface missing, aborting\n"); return nullptr; } - -# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD || BX_PLATFORM_RPI - return (void*)wmi.info.x11.window; -# elif BX_PLATFORM_OSX - return wmi.info.cocoa.window; -# elif BX_PLATFORM_WINDOWS - return wmi.info.win.window; -# elif BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_ANDROID - return nullptr; -# endif // BX_PLATFORM_ + wl_egl_window *win_impl = (wl_egl_window *)SDL_GetWindowData(window, "wl_egl_window"); + if (!win_impl) + { + int width, height; + SDL_GetWindowSize(window, &width, &height); + win_impl = wl_egl_window_create(surface, width, height); + if (!win_impl) + { + osd_printf_error("Creating wayland window failed\n"); + return nullptr; + } + SDL_SetWindowData(window, "wl_egl_window", win_impl); + } + return win_impl; } +#endif -inline bool sdlSetWindow(bgfx::PlatformData &platform_data, SDL_Window* _window) + +//============================================================ +// Utility for setting up window handle +//============================================================ + +bool video_bgfx::set_platform_data(bgfx::PlatformData &platform_data, osd_window const &window) { +#if defined(OSD_WINDOWS) + platform_data.ndt = nullptr; + platform_data.nwh = dynamic_cast<win_window_info const &>(window).platform_window(); +#elif defined(OSD_MAC) + platform_data.ndt = nullptr; + platform_data.nwh = GetOSWindow(dynamic_cast<mac_window_info const &>(window).platform_window()); +#else // defined(OSD_*) SDL_SysWMinfo wmi; SDL_VERSION(&wmi.version); - if (!SDL_GetWindowWMInfo(_window, &wmi) ) + if (!SDL_GetWindowWMInfo(dynamic_cast<sdl_window_info const &>(window).platform_window(), &wmi)) { + osd_printf_error("BGFX: Error getting SDL window info: %s\n", SDL_GetError()); return false; } -# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD - platform_data.ndt = wmi.info.x11.display; - platform_data.nwh = (void*)(uintptr_t)wmi.info.x11.window; -# elif BX_PLATFORM_OSX - platform_data.ndt = NULL; - platform_data.nwh = wmi.info.cocoa.window; -# elif BX_PLATFORM_WINDOWS - platform_data.ndt = NULL; - platform_data.nwh = wmi.info.win.window; -# endif // BX_PLATFORM_ - platform_data.context = NULL; - platform_data.backBuffer = NULL; - platform_data.backBufferDS = NULL; + switch (wmi.subsystem) + { +#if defined(SDL_VIDEO_DRIVER_WINDOWS) + case SDL_SYSWM_WINDOWS: + platform_data.ndt = nullptr; + platform_data.nwh = wmi.info.win.window; + break; +#endif +#if defined(SDL_VIDEO_DRIVER_X11) + case SDL_SYSWM_X11: + platform_data.ndt = wmi.info.x11.display; + platform_data.nwh = (void *)uintptr_t(wmi.info.x11.window); + break; +#endif +#if defined(SDL_VIDEO_DRIVER_COCOA) + case SDL_SYSWM_COCOA: + platform_data.ndt = nullptr; + platform_data.nwh = wmi.info.cocoa.window; + break; +#endif +#if defined(SDL_VIDEO_DRIVER_WAYLAND) && SDL_VERSION_ATLEAST(2, 0, 16) && defined(SDLMAME_USE_WAYLAND) + case SDL_SYSWM_WAYLAND: + platform_data.ndt = wmi.info.wl.display; + platform_data.nwh = create_wl_egl_window(dynamic_cast<sdl_window_info const &>(window).platform_window(), wmi.info.wl.surface); + if (!platform_data.nwh) + { + osd_printf_error("BGFX: Error creating a Wayland window\n"); + return false; + } + platform_data.type = bgfx::NativeWindowHandleType::Wayland; + break; +#endif +#if defined(SDL_VIDEO_DRIVER_ANDROID) + case SDL_SYSWM_ANDROID: + platform_data.ndt = nullptr; + platform_data.nwh = wmi.info.android.window; + break; +#endif + default: + osd_printf_error("BGFX: Unsupported SDL window manager type %u\n", wmi.subsystem); + return false; + } +#endif // defined(OSD_*) + + platform_data.context = nullptr; + platform_data.backBuffer = nullptr; + platform_data.backBufferDS = nullptr; bgfx::setPlatformData(platform_data); return true; } -#endif + +} // anonymous namespace + +} // namespace osd + +MODULE_DEFINITION(RENDERER_BGFX, osd::video_bgfx) //============================================================ -// renderer_bgfx::create +// CONSTANTS //============================================================ -int renderer_bgfx::create() +uint16_t const renderer_bgfx::CACHE_SIZE = 1024; +uint32_t const renderer_bgfx::PACKABLE_SIZE = 128; +uint32_t const renderer_bgfx::WHITE_HASH = 0x87654321; +char const *const renderer_bgfx::WINDOW_PREFIX = "Window 0, "; + + + +//============================================================ +// MACROS +//============================================================ + +#define GIBBERISH (0) +#define SCENE_VIEW (0) + + + +//============================================================ +// STATICS +//============================================================ + +uint32_t renderer_bgfx::s_current_view = 0; +uint32_t renderer_bgfx::s_width[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +uint32_t renderer_bgfx::s_height[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + + +//============================================================ +// helper for getting native platform window +//============================================================ + +#ifdef OSD_SDL +static std::pair<void *, bool> sdlNativeWindowHandle(SDL_Window *window) { - std::shared_ptr<osd_window> win = assert_window(); - osd_dim wdim = win->get_size(); - s_width[win->index()] = wdim.width(); - s_height[win->index()] = wdim.height(); - m_dimensions = wdim; + SDL_SysWMinfo wmi; + SDL_VERSION(&wmi.version); + if (!SDL_GetWindowWMInfo(window, &wmi)) + return std::make_pair(nullptr, false); - if (s_bgfx_library_initialized) + switch (wmi.subsystem) { - exit(); +#if defined(SDL_VIDEO_DRIVER_WINDOWS) + case SDL_SYSWM_WINDOWS: + return std::make_pair(wmi.info.win.window, true); +#endif +#if defined(SDL_VIDEO_DRIVER_X11) + case SDL_SYSWM_X11: + return std::make_pair((void *)uintptr_t(wmi.info.x11.window), true); +#endif +#if defined(SDL_VIDEO_DRIVER_COCOA) + case SDL_SYSWM_COCOA: + return std::make_pair(wmi.info.cocoa.window, true); +#endif +#if defined(SDL_VIDEO_DRIVER_WAYLAND) && SDL_VERSION_ATLEAST(2, 0, 16) && defined(SDLMAME_USE_WAYLAND) + case SDL_SYSWM_WAYLAND: + { + void *const platform_window = osd::create_wl_egl_window(window, wmi.info.wl.surface); + return std::make_pair(platform_window, platform_window != nullptr); + } +#endif +#if defined(SDL_VIDEO_DRIVER_ANDROID) + case SDL_SYSWM_ANDROID: + return std::make_pair(wmi.info.android.window, true); +#endif + default: + return std::make_pair(nullptr, false); } +} +#endif // OSD_SDL + + + +//============================================================ +// renderer_bgfx - constructor +//============================================================ - if (win->index() == 0) +renderer_bgfx::renderer_bgfx(osd_window &window, parent_module &parent) + : osd_renderer(window) + , m_module(parent) + , m_framebuffer(nullptr) + , m_texture_cache(nullptr) + , m_dimensions(0, 0) + , m_max_view(0) + , m_avi_view(nullptr) + , m_avi_writer(nullptr) + , m_avi_target(nullptr) + , m_load_sub(parent.subscribe_load(&renderer_bgfx::load_config, this)) + , m_save_sub(parent.subscribe_save(&renderer_bgfx::save_config, this)) +{ + // load settings if recreated after fullscreen toggle + util::xml::data_node *windownode = m_module().persistent_settings().get_child("window"); + while (windownode) { -#ifdef OSD_WINDOWS - winSetHwnd(m_platform_data, std::static_pointer_cast<win_window_info>(win)->platform_window()); -#elif defined(OSD_MAC) - macSetWindow(m_platform_data, std::static_pointer_cast<mac_window_info>(win)->platform_window()); -#else - sdlSetWindow(m_platform_data, std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()); -#endif + if (windownode->get_attribute_int("index", -1) != window.index()) + { + windownode = windownode->get_next_sibling("window"); + } + else + { + if (!m_config) + { + m_config = util::xml::file::create(); + windownode->copy_into(*m_config); + } + std::exchange(windownode, windownode->get_next_sibling("window"))->delete_node(); + } + } +} + - init_bgfx_library(); + +//============================================================ +// renderer_bgfx - destructor +//============================================================ + +renderer_bgfx::~renderer_bgfx() +{ + // persist settings across fullscreen toggle + if (m_config) + m_config->get_first_child()->copy_into(m_module().persistent_settings()); + else if (m_chains) + m_chains->save_config(m_module().persistent_settings()); + + bgfx::reset(0, 0, BGFX_RESET_NONE); + + if (m_avi_writer != nullptr && m_avi_writer->recording()) + { + m_avi_writer->stop(); + + m_targets->destroy_target("avibuffer0"); + m_avi_target = nullptr; + + bgfx::destroy(m_avi_texture); + + delete m_avi_writer; + delete [] m_avi_data; + delete m_avi_view; } +} - // finish creating the renderer - m_textures = new texture_manager(); - m_targets = new target_manager(*m_textures); - m_shaders = new shader_manager(); - m_effects = new effect_manager(*m_shaders); - // Create program from shaders. - m_gui_effect[0] = m_effects->get_or_load_effect(m_options, "gui_opaque"); - m_gui_effect[1] = m_effects->get_or_load_effect(m_options, "gui_blend"); - m_gui_effect[2] = m_effects->get_or_load_effect(m_options, "gui_multiply"); - m_gui_effect[3] = m_effects->get_or_load_effect(m_options, "gui_add"); +//============================================================ +// renderer_bgfx::create +//============================================================ + +int renderer_bgfx::create() +{ + const osd_dim wdim = window().get_size(); + s_width[window().index()] = wdim.width(); + s_height[window().index()] = wdim.height(); + m_dimensions = wdim; - m_screen_effect[0] = m_effects->get_or_load_effect(m_options, "screen_opaque"); - m_screen_effect[1] = m_effects->get_or_load_effect(m_options, "screen_blend"); - m_screen_effect[2] = m_effects->get_or_load_effect(m_options, "screen_multiply"); - m_screen_effect[3] = m_effects->get_or_load_effect(m_options, "screen_add"); + // finish creating the renderer + m_textures = std::make_unique<texture_manager>(); + m_targets = std::make_unique<target_manager>(*m_textures); - if (win->index() != 0) + if (window().index() != 0) { #ifdef OSD_WINDOWS - m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), s_width[win->index()], s_height[win->index()]); + m_framebuffer = m_targets->create_backbuffer(dynamic_cast<win_window_info &>(window()).platform_window(), s_width[window().index()], s_height[window().index()]); #elif defined(OSD_MAC) - m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), s_width[win->index()], s_height[win->index()]); + m_framebuffer = m_targets->create_backbuffer(GetOSWindow(dynamic_cast<mac_window_info &>(window()).platform_window()), s_width[window().index()], s_height[window().index()]); #else - m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), s_width[win->index()], s_height[win->index()]); + auto const [winhdl, success] = sdlNativeWindowHandle(dynamic_cast<sdl_window_info &>(window()).platform_window()); + if (!success) + { + m_targets.reset(); + m_textures.reset(); + return -1; + } + m_framebuffer = m_targets->create_backbuffer(winhdl, s_width[window().index()], s_height[window().index()]); #endif - bgfx::touch(win->index()); + bgfx::touch(window().index()); - if (m_ortho_view) { + if (m_ortho_view) m_ortho_view->set_backbuffer(m_framebuffer); - } } - m_chains = new chain_manager(win->machine(), m_options, *m_textures, *m_targets, *m_effects, win->index(), *this); + m_shaders = std::make_unique<shader_manager>(); + m_effects = std::make_unique<effect_manager>(*m_shaders); + + // Create program from shaders. + m_gui_effect[0] = m_effects->get_or_load_effect(m_module().options(), "gui_opaque"); + m_gui_effect[1] = m_effects->get_or_load_effect(m_module().options(), "gui_blend"); + m_gui_effect[2] = m_effects->get_or_load_effect(m_module().options(), "gui_multiply"); + m_gui_effect[3] = m_effects->get_or_load_effect(m_module().options(), "gui_add"); + + m_screen_effect[0] = m_effects->get_or_load_effect(m_module().options(), "screen_opaque"); + m_screen_effect[1] = m_effects->get_or_load_effect(m_module().options(), "screen_blend"); + m_screen_effect[2] = m_effects->get_or_load_effect(m_module().options(), "screen_multiply"); + m_screen_effect[3] = m_effects->get_or_load_effect(m_module().options(), "screen_add"); + + const uint32_t max_prescale_size = std::min(2u * std::max(wdim.width(), wdim.height()), m_module().max_texture_size()); + m_chains = std::make_unique<chain_manager>( + window().machine(), + m_module().options(), + *m_textures, + *m_targets, + *m_effects, + window().index(), + *this, + window().prescale(), + max_prescale_size); m_sliders_dirty = true; uint32_t flags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT; - m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::BGRA8, CACHE_SIZE, CACHE_SIZE, nullptr, flags); + m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::BGRA8, CACHE_SIZE, 0, CACHE_SIZE, nullptr, flags); memset(m_white, 0xff, sizeof(uint32_t) * 16 * 16); m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white)); @@ -365,16 +723,12 @@ int renderer_bgfx::create() void renderer_bgfx::record() { - std::shared_ptr<osd_window> win = assert_window(); - - if (win->index() > 0) - { + if (window().index() > 0) return; - } if (m_avi_writer == nullptr) { - m_avi_writer = new avi_write(win->machine(), s_width[0], s_height[0]); + m_avi_writer = new avi_write(window().machine(), s_width[0], s_height[0]); m_avi_data = new uint8_t[s_width[0] * s_height[0] * 4]; m_avi_bitmap.allocate(s_width[0], s_height[0]); } @@ -390,8 +744,8 @@ void renderer_bgfx::record() } else { - m_avi_writer->record(m_options.bgfx_avi_name()); - m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::BGRA8, s_width[0], s_height[0], TARGET_STYLE_CUSTOM, false, true, 1, 0); + m_avi_writer->record(m_module().options().bgfx_avi_name()); + m_avi_target = m_targets->create_target("avibuffer", bgfx::TextureFormat::BGRA8, s_width[0], s_height[0], 1, 1, TARGET_STYLE_CUSTOM, false, true, 1, 0); m_avi_texture = bgfx::createTexture2D(s_width[0], s_height[0], false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK); if (m_avi_view == nullptr) @@ -401,47 +755,6 @@ void renderer_bgfx::record() } } -bool renderer_bgfx::init(running_machine &machine) -{ - osd_options &options = downcast<osd_options &>(machine.options()); - const char *bgfx_path = options.bgfx_path(); - - osd::directory::ptr directory = osd::directory::open(bgfx_path); - if (directory == nullptr) - { - osd_printf_error("Unable to find the BGFX path %s, please install it or fix the bgfx_path setting to use the BGFX renderer.\n", bgfx_path); - return true; - } - - // Verify baseline shaders. - const bool gui_opaque_valid = effect_manager::validate_effect(options, "gui_opaque"); - const bool gui_blend_valid = effect_manager::validate_effect(options, "gui_blend"); - const bool gui_multiply_valid = effect_manager::validate_effect(options, "gui_multiply"); - const bool gui_add_valid = effect_manager::validate_effect(options, "gui_add"); - const bool all_gui_valid = gui_opaque_valid && gui_blend_valid && gui_multiply_valid && gui_add_valid; - - const bool screen_opaque_valid = effect_manager::validate_effect(options, "screen_opaque"); - const bool screen_blend_valid = effect_manager::validate_effect(options, "screen_blend"); - const bool screen_multiply_valid = effect_manager::validate_effect(options, "screen_multiply"); - const bool screen_add_valid = effect_manager::validate_effect(options, "screen_add"); - const bool all_screen_valid = screen_opaque_valid && screen_blend_valid && screen_multiply_valid && screen_add_valid; - - if (!all_gui_valid || !all_screen_valid) - { - osd_printf_error("BGFX: Unable to load required shaders. Please update the %s folder or adjust your bgfx_path setting.\n", options.bgfx_path()); - return true; - } - - return false; -} - -void renderer_bgfx::exit() -{ - imguiDestroy(); - bgfx::shutdown(); - s_bgfx_library_initialized = false; -} - //============================================================ // drawsdl_xy_to_render_target //============================================================ @@ -480,15 +793,6 @@ void renderer_bgfx::put_packed_quad(render_primitive *prim, uint32_t hash, Scree float u[4] = { u0, u1, u0, u1 }; float v[4] = { v0, v0, v1, v1 }; - if (bgfx::getRendererType() == bgfx::RendererType::Direct3D9) - { - for (int i = 0; i < 4; i++) - { - u[i] += 0.5f / size; - v[i] += 0.5f / size; - } - } - if (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_SWAP_XY) { std::swap(u[1], u[2]); @@ -529,7 +833,7 @@ void renderer_bgfx::vertex(ScreenVertex* vertex, float x, float y, float z, uint vertex->m_v = v; } -void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen) +void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index) { auto* vertices = reinterpret_cast<ScreenVertex*>(buffer->data); @@ -554,6 +858,15 @@ void renderer_bgfx::render_post_screen_quad(int view, render_primitive* prim, bg uint32_t blend = PRIMFLAG_GET_BLENDMODE(prim->flags); bgfx::setVertexBuffer(0,buffer); bgfx::setTexture(0, m_screen_effect[blend]->uniform("s_tex")->handle(), m_targets->target(screen, "output")->texture(), texture_flags); + + bgfx_uniform* inv_view_dims = m_screen_effect[blend]->uniform("u_inv_view_dims"); + if (inv_view_dims) + { + float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] }; + inv_view_dims->set(values, sizeof(float) * 2); + inv_view_dims->upload(); + } + m_screen_effect[blend]->submit(m_ortho_view->get_index()); } @@ -563,7 +876,7 @@ void renderer_bgfx::render_avi_quad() m_avi_view->setup(); bgfx::setViewRect(s_current_view, 0, 0, s_width[0], s_height[0]); - bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0); + bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0); bgfx::TransientVertexBuffer buffer; bgfx::allocTransientVertexBuffer(&buffer, 6, ScreenVertex::ms_decl); @@ -584,11 +897,21 @@ void renderer_bgfx::render_avi_quad() bgfx::setVertexBuffer(0,&buffer); bgfx::setTexture(0, m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]->uniform("s_tex")->handle(), m_avi_target->texture()); - m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]->submit(s_current_view); + + bgfx_effect* effect = m_gui_effect[PRIMFLAG_GET_BLENDMODE(BLENDMODE_NONE)]; + bgfx_uniform* inv_view_dims = effect->uniform("u_inv_view_dims"); + if (inv_view_dims) + { + float values[2] = { -1.0f / s_width[0], 1.0f / s_height[0] }; + inv_view_dims->set(values, sizeof(float) * 2); + inv_view_dims->upload(); + } + + effect->submit(s_current_view); s_current_view++; } -void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer) +void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int window_index) { auto* vertices = reinterpret_cast<ScreenVertex*>(buffer->data); uint32_t rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255); @@ -625,7 +948,7 @@ void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::Transient else { texture = m_textures->create_or_update_mame_texture(prim->flags & PRIMFLAG_TEXFORMAT_MASK - , tex_width, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base, prim->texture.seqid + , tex_width, prim->texture.width_margin, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base, prim->texture.seqid , texture_flags, prim->texture.unique_id, prim->texture.old_id); } @@ -634,6 +957,15 @@ void renderer_bgfx::render_textured_quad(render_primitive* prim, bgfx::Transient uint32_t blend = PRIMFLAG_GET_BLENDMODE(prim->flags); bgfx::setVertexBuffer(0,buffer); bgfx::setTexture(0, effects[blend]->uniform("s_tex")->handle(), texture); + + bgfx_uniform* inv_view_dims = effects[blend]->uniform("u_inv_view_dims"); + if (inv_view_dims) + { + float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] }; + inv_view_dims->set(values, sizeof(float) * 2); + inv_view_dims->upload(); + } + effects[blend]->submit(m_ortho_view->get_index()); if (is_screen) @@ -852,16 +1184,13 @@ uint32_t renderer_bgfx::u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a int renderer_bgfx::draw(int update) { - std::shared_ptr<osd_window> win = assert_window(); - - int window_index = win->index(); + int window_index = window().index(); m_seen_views.clear(); - if (m_ortho_view) { + if (m_ortho_view) m_ortho_view->set_index(UINT_MAX); - } - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); s_width[window_index] = wdim.width(); s_height[window_index] = wdim.height(); @@ -871,9 +1200,9 @@ int renderer_bgfx::draw(int update) s_current_view = 0; } - win->m_primlist->acquire_lock(); - uint32_t num_screens = m_chains->update_screen_textures(s_current_view, win->m_primlist->first(), *win.get()); - win->m_primlist->release_lock(); + window().m_primlist->acquire_lock(); + uint32_t num_screens = m_chains->update_screen_textures(s_current_view, window().m_primlist->first(), window()); + window().m_primlist->release_lock(); bool skip_frame = update_dimensions(); if (skip_frame) @@ -883,7 +1212,21 @@ int renderer_bgfx::draw(int update) if (num_screens) { - uint32_t chain_view_count = m_chains->process_screen_chains(s_current_view, *win.get()); + // Restore config after counting screens the first time + // Doing this here is hacky - it means config is restored at the wrong + // time if the initial view has no screens and the user switches to a + // view with screens. The trouble is there's no real interface between + // the render targets and the renderer so we don't actually know when + // we're first called on to render a live view (as opposed to an info + // screen). + if (m_config) + { + osd_printf_verbose("BGFX: Applying configuration for window %d\n", window().index()); + m_chains->load_config(*m_config->get_first_child()); + m_config.reset(); + } + + uint32_t chain_view_count = m_chains->process_screen_chains(s_current_view, window()); s_current_view += chain_view_count; } @@ -896,12 +1239,12 @@ int renderer_bgfx::draw(int update) s_current_view = m_max_view; } - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // Mark our texture atlas as dirty if we need to do so bool atlas_valid = update_atlas(); - render_primitive *prim = win->m_primlist->first(); + render_primitive *prim = window().m_primlist->first(); std::vector<void*> sources; while (prim != nullptr) { @@ -926,12 +1269,21 @@ int renderer_bgfx::draw(int update) } } - buffer_status status = buffer_primitives(atlas_valid, &prim, &buffer, screen); + buffer_status status = buffer_primitives(atlas_valid, &prim, &buffer, screen, window_index); if (status != BUFFER_EMPTY && status != BUFFER_SCREEN) { - bgfx::setVertexBuffer(0,&buffer); + bgfx::setVertexBuffer(0, &buffer); bgfx::setTexture(0, m_gui_effect[blend]->uniform("s_tex")->handle(), m_texture_cache->texture()); + + bgfx_uniform* inv_view_dims = m_gui_effect[blend]->uniform("u_inv_view_dims"); + if (inv_view_dims) + { + float values[2] = { -1.0f / s_width[window_index], 1.0f / s_height[window_index] }; + inv_view_dims->set(values, sizeof(float) * 2); + inv_view_dims->upload(); + } + m_gui_effect[blend]->submit(m_ortho_view->get_index()); } @@ -941,7 +1293,7 @@ int renderer_bgfx::draw(int update) } } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); // This dummy draw call is here to make sure that view 0 is cleared // if no other draw calls are submitted to view 0. @@ -959,7 +1311,7 @@ int renderer_bgfx::draw(int update) } } - if (win->index() == osd_common_t::s_window_list.size() - 1) + if (window().index() == osd_common_t::window_list().size() - 1) { bgfx::frame(); } @@ -989,8 +1341,7 @@ void renderer_bgfx::update_recording() void renderer_bgfx::add_audio_to_recording(const int16_t *buffer, int samples_this_frame) { - std::shared_ptr<osd_window> win = assert_window(); - if (m_avi_writer != nullptr && m_avi_writer->recording() && win->index() == 0) + if (m_avi_writer != nullptr && m_avi_writer->recording() && window().index() == 0) { m_avi_writer->audio_frame(buffer, samples_this_frame); } @@ -998,9 +1349,7 @@ void renderer_bgfx::add_audio_to_recording(const int16_t *buffer, int samples_th bool renderer_bgfx::update_dimensions() { - std::shared_ptr<osd_window> win = assert_window(); - - const uint32_t window_index = win->index(); + const uint32_t window_index = window().index(); const uint32_t width = s_width[window_index]; const uint32_t height = s_height[window_index]; @@ -1009,15 +1358,14 @@ bool renderer_bgfx::update_dimensions() bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); m_dimensions = osd_dim(width, height); - if (win->index() != 0) + if (window().index() != 0) { - delete m_framebuffer; #ifdef OSD_WINDOWS - m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), width, height); + m_framebuffer = m_targets->create_backbuffer(dynamic_cast<win_window_info &>(window()).platform_window(), width, height); #elif defined(OSD_MAC) - m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), width, height); + m_framebuffer = m_targets->create_backbuffer(GetOSWindow(dynamic_cast<mac_window_info &>(window()).platform_window()), width, height); #else - m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), width, height); + m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(dynamic_cast<sdl_window_info &>(window()).platform_window()).first, width, height); #endif if (m_ortho_view) { @@ -1026,7 +1374,7 @@ bool renderer_bgfx::update_dimensions() bgfx::setViewFrameBuffer(s_current_view, m_framebuffer->target()); } - bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0); + bgfx::setViewClear(s_current_view, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0); bgfx::setViewMode(s_current_view, bgfx::ViewMode::Sequential); bgfx::touch(s_current_view); bgfx::frame(); @@ -1039,7 +1387,7 @@ void renderer_bgfx::setup_ortho_view() { if (!m_ortho_view) { - m_ortho_view = new bgfx_ortho_view(this, 0, m_framebuffer, m_seen_views); + m_ortho_view = std::make_unique<bgfx_ortho_view>(this, 0, m_framebuffer, m_seen_views); } if (m_ortho_view->get_index() == UINT_MAX) { @@ -1052,10 +1400,6 @@ void renderer_bgfx::setup_ortho_view() render_primitive_list *renderer_bgfx::get_primitives() { - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - // determines whether the screen container is transformed by the chain's shaders bool chain_transform = false; @@ -1066,15 +1410,15 @@ render_primitive_list *renderer_bgfx::get_primitives() chain_transform = chain->transform(); } - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (wdim.width() > 0 && wdim.height() > 0) - win->target()->set_bounds(wdim.width(), wdim.height(), win->pixel_aspect()); + window().target()->set_bounds(wdim.width(), wdim.height(), window().pixel_aspect()); - win->target()->set_transform_container(!chain_transform); - return &win->target()->get_primitives(); + window().target()->set_transform_container(!chain_transform); + return &window().target()->get_primitives(); } -renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen) +renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index) { int vertices = 0; @@ -1116,18 +1460,18 @@ renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid, { #if SCENE_VIEW setup_view(s_current_view, true); - render_post_screen_quad(s_current_view, *prim, buffer, screen); + render_post_screen_quad(s_current_view, *prim, buffer, screen, window_index); s_current_view++; #else setup_ortho_view(); - render_post_screen_quad(m_ortho_view->get_index(), *prim, buffer, screen); + render_post_screen_quad(m_ortho_view->get_index(), *prim, buffer, screen, window_index); #endif return BUFFER_SCREEN; } else { setup_ortho_view(); - render_textured_quad(*prim, buffer); + render_textured_quad(*prim, buffer, window_index); return BUFFER_EMPTY; } } @@ -1208,7 +1552,7 @@ void renderer_bgfx::process_atlas_packs(std::vector<std::vector<rectangle_packer uint16_t pitch = rect.width(); int width_div_factor = 1; int width_mul_factor = 1; - const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, rect.format(), rect.rowpixels(), rect.height(), rect.palette(), rect.base(), pitch, width_div_factor, width_mul_factor); + const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, rect.format(), rect.rowpixels(), 0, rect.height(), rect.palette(), rect.base(), pitch, width_div_factor, width_mul_factor); bgfx::updateTexture2D(m_texture_cache->texture(), 0, 0, rect.x(), rect.y(), (rect.width() * width_mul_factor) / width_div_factor, rect.height(), mem, pitch); } } @@ -1246,9 +1590,8 @@ bool renderer_bgfx::check_for_dirty_atlas() { bool atlas_dirty = false; - std::shared_ptr<osd_window> win = assert_window(); std::map<uint32_t, rectangle_packer::packable_rectangle> acquired_infos; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { bool pack = prim.packable(PACKABLE_SIZE); if (prim.type == render_primitive::QUAD && prim.texture.base != nullptr && pack) @@ -1261,8 +1604,7 @@ bool renderer_bgfx::check_for_dirty_atlas() atlas_dirty = true; m_texinfo.push_back(rectangle_packer::packable_rectangle(hash, prim.flags & PRIMFLAG_TEXFORMAT_MASK, - prim.texture.width, prim.texture.height, - prim.texture.rowpixels, prim.texture.palette, prim.texture.base)); + prim.texture.width, prim.texture.height, prim.texture.rowpixels, prim.texture.palette, prim.texture.base)); acquired_infos[hash] = m_texinfo[m_texinfo.size() - 1]; } } @@ -1339,11 +1681,44 @@ void renderer_bgfx::set_sliders_dirty() m_sliders_dirty = true; } -uint32_t renderer_bgfx::get_window_width(uint32_t index) const { +uint32_t renderer_bgfx::get_window_width(uint32_t index) const +{ return s_width[index]; } -uint32_t renderer_bgfx::get_window_height(uint32_t index) const { +uint32_t renderer_bgfx::get_window_height(uint32_t index) const +{ return s_height[index]; } + +void renderer_bgfx::load_config(util::xml::data_node const &parentnode) +{ + util::xml::data_node const *windownode = parentnode.get_child("window"); + while (windownode) + { + if (windownode->get_attribute_int("index", -1) != window().index()) + { + windownode = windownode->get_next_sibling("window"); + continue; + } + + if (!m_config) + m_config = util::xml::file::create(); + else + m_config->get_first_child()->delete_node(); + windownode->copy_into(*m_config); + m_config->get_first_child()->set_attribute("persist", "0"); + osd_printf_verbose("BGFX: Found configuration for window %d\n", window().index()); + break; + } +} + + +void renderer_bgfx::save_config(util::xml::data_node &parentnode) +{ + if (m_config) + m_config->get_first_child()->copy_into(parentnode); + else + m_chains->save_config(parentnode); +} diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h index fc728e41d67..bb9f538aafa 100644 --- a/src/osd/modules/render/drawbgfx.h +++ b/src/osd/modules/render/drawbgfx.h @@ -1,30 +1,34 @@ // license:BSD-3-Clause // copyright-holders:Ryan Holtz +#ifndef MAME_RENDER_DRAWBGFX_H +#define MAME_RENDER_DRAWBGFX_H + #pragma once -#ifndef RENDER_BGFX -#define RENDER_BGFX +#include "binpacker.h" +#include "bgfx/chain.h" +#include "bgfx/chainmanager.h" +#include "bgfx/vertex.h" +#include "sliderdirtynotifier.h" + +#include "modules/osdwindow.h" + +#include "notifier.h" #include <bgfx/bgfx.h> #include <map> +#include <memory> #include <vector> -#include "binpacker.h" -#include "bgfx/vertex.h" -#include "bgfx/chain.h" -#include "bgfx/chainmanager.h" -#include "sliderdirtynotifier.h" class texture_manager; class target_manager; class shader_manager; class effect_manager; -class chain_manager; class bgfx_texture; class bgfx_effect; class bgfx_target; -class bgfx_chain; class bgfx_view; class osd_options; class avi_write; @@ -33,11 +37,10 @@ class avi_write; class renderer_bgfx : public osd_renderer, public slider_dirty_notifier { public: - renderer_bgfx(std::shared_ptr<osd_window> w); - virtual ~renderer_bgfx(); + class parent_module; - static bool init(running_machine &machine); - static void exit(); + renderer_bgfx(osd_window &window, parent_module &parent_module); + virtual ~renderer_bgfx(); virtual int create() override; virtual int draw(const int update) override; @@ -62,7 +65,24 @@ public: static char const *const WINDOW_PREFIX; private: - void init_bgfx_library(); + enum buffer_status + { + BUFFER_PRE_FLUSH, + BUFFER_FLUSH, + BUFFER_SCREEN, + BUFFER_EMPTY, + BUFFER_DONE + }; + + class parent_module_holder + { + public: + parent_module_holder(parent_module &parent); + ~parent_module_holder(); + parent_module &operator()() const { return m_parent; } + private: + parent_module &m_parent; + }; void vertex(ScreenVertex* vertex, float x, float y, float z, uint32_t rgba, float u, float v); void render_avi_quad(); @@ -73,18 +93,10 @@ private: void setup_ortho_view(); void allocate_buffer(render_primitive *prim, uint32_t blend, bgfx::TransientVertexBuffer *buffer); - enum buffer_status - { - BUFFER_PRE_FLUSH, - BUFFER_FLUSH, - BUFFER_SCREEN, - BUFFER_EMPTY, - BUFFER_DONE - }; - buffer_status buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen); + buffer_status buffer_primitives(bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index); - void render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer); - void render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen); + void render_textured_quad(render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int window_index); + void render_post_screen_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer, int32_t screen, int window_index); void put_packed_quad(render_primitive *prim, uint32_t hash, ScreenVertex* vertex); void put_packed_line(render_primitive *prim, ScreenVertex* vertex); @@ -100,8 +112,10 @@ private: void process_atlas_packs(std::vector<std::vector<rectangle_packer::packed_rectangle>>& packed); uint32_t get_texture_hash(render_primitive *prim); - osd_options& m_options; - bgfx::PlatformData m_platform_data; + void load_config(util::xml::data_node const &parentnode); + void save_config(util::xml::data_node &parentnode); + + parent_module_holder m_module; // keep this where it will be destructed last bgfx_target *m_framebuffer; bgfx_texture *m_texture_cache; @@ -109,11 +123,11 @@ private: // Original display_mode osd_dim m_dimensions; - texture_manager *m_textures; - target_manager *m_targets; - shader_manager *m_shaders; - effect_manager *m_effects; - chain_manager *m_chains; + std::unique_ptr<texture_manager> m_textures; + std::unique_ptr<target_manager> m_targets; + std::unique_ptr<shader_manager> m_shaders; + std::unique_ptr<effect_manager> m_effects; + std::unique_ptr<chain_manager> m_chains; bgfx_effect *m_gui_effect[4]; bgfx_effect *m_screen_effect[4]; @@ -124,7 +138,7 @@ private: rectangle_packer m_packer; uint32_t m_white[16*16]; - bgfx_view *m_ortho_view; + std::unique_ptr<bgfx_view> m_ortho_view; uint32_t m_max_view; bgfx_view *m_avi_view; @@ -134,14 +148,17 @@ private: bitmap_rgb32 m_avi_bitmap; uint8_t *m_avi_data; + std::unique_ptr<util::xml::file> m_config; + const util::notifier_subscription m_load_sub; + const util::notifier_subscription m_save_sub; + static const uint16_t CACHE_SIZE; static const uint32_t PACKABLE_SIZE; static const uint32_t WHITE_HASH; static uint32_t s_current_view; - static bool s_bgfx_library_initialized; static uint32_t s_width[16]; static uint32_t s_height[16]; }; -#endif // RENDER_BGFX +#endif // MAME_RENDER_DRAWBGFX_H diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp index cfc494a2be9..542e2f8955d 100644 --- a/src/osd/modules/render/drawd3d.cpp +++ b/src/osd/modules/render/drawd3d.cpp @@ -13,21 +13,132 @@ #include "rendutil.h" #include "screen.h" -#include "aviio.h" - // MAMEOS headers -#include "winmain.h" -#include "window.h" #include "drawd3d.h" -#include "modules/render/d3d/d3dhlsl.h" + +#include "d3d/d3dhlsl.h" + +#include "render_module.h" + +// from OSD implementation +#include "window.h" +#include "winmain.h" + +// general OSD headers #include "modules/monitor/monitor_module.h" + +// lib/util +#include "aviio.h" + #include <utility> + +//============================================================ +// OSD MODULE +//============================================================ + +namespace osd { + +namespace { + +class video_d3d : public osd_module, public render_module +{ +public: + video_d3d() + : osd_module(OSD_RENDERER_PROVIDER, "d3d") + , m_options(nullptr) + { + } + + virtual bool probe() override; + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE; } + +private: + using d3d9_create_fn = IDirect3D9 *(WINAPI *)(UINT); + + dynamic_module::ptr m_d3d9_dll; + Microsoft::WRL::ComPtr<IDirect3D9> m_d3dobj; + osd_options const *m_options; +}; + + +//============================================================ +// video_d3d::probe +//============================================================ + +bool video_d3d::probe() +{ + // do a dry run of loading the Direct3D 9 DLL + return dynamic_module::open({ "d3d9.dll" })->bind<d3d9_create_fn>("Direct3DCreate9") != nullptr; +} + + +//============================================================ +// video_d3d::init +//============================================================ + +int video_d3d::init(osd_interface &osd, osd_options const &options) +{ + m_options = &options; + + m_d3d9_dll = dynamic_module::open({ "d3d9.dll" }); + auto const d3d9_create_ptr = m_d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9"); + if (!d3d9_create_ptr) + { + osd_printf_warning("Direct3D: Could not find Direct3DCreate9 function in d3d9.dll\n"); + m_d3d9_dll.reset(); + m_options = nullptr; + return -1; + } + + m_d3dobj.Attach((d3d9_create_ptr)(D3D_SDK_VERSION)); + if (!m_d3dobj) + { + osd_printf_warning("Direct3D: Unable to initialize Direct3D 9\n"); + m_d3d9_dll.reset(); + m_options = nullptr; + return -1; + } + + osd_printf_verbose("Direct3D: Using Direct3D 9\n"); + + return 0; +} + + +//============================================================ +// video_d3d::exit +//============================================================ + +void video_d3d::exit() +{ + m_d3dobj.Reset(); + m_d3d9_dll.reset(); + m_options = nullptr; +} + + //============================================================ -// TYPE DEFINITIONS +// video_d3d::create //============================================================ -typedef IDirect3D9* (WINAPI *d3d9_create_fn)(UINT); +std::unique_ptr<osd_renderer> video_d3d::create(osd_window &window) +{ + return std::make_unique<renderer_d3d9>(window, m_d3dobj); +} + +} // anonymous namespace + +} // namespace osd + +MODULE_DEFINITION(RENDERER_D3D, osd::video_d3d) + //============================================================ @@ -116,13 +227,6 @@ static inline uint32_t ycc_to_rgb(uint8_t y, uint8_t cb, uint8_t cr) //============================================================ -// drawd3d_init -//============================================================ - -static d3d_base *d3dintf = nullptr; // FIX ME - - -//============================================================ // drawd3d_window_init //============================================================ @@ -174,60 +278,22 @@ void renderer_d3d9::save() render_primitive_list *renderer_d3d9::get_primitives() { RECT client; - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - - HWND hWnd = std::static_pointer_cast<win_window_info>(win)->platform_window(); + HWND hWnd = dynamic_cast<win_window_info &>(window()).platform_window(); if (IsIconic(hWnd)) return nullptr; - GetClientRectExceptMenu(hWnd, &client, win->fullscreen()); + GetClientRectExceptMenu(hWnd, &client, window().fullscreen()); if (rect_width(&client) > 0 && rect_height(&client) > 0) { - win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect()); - win->target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); + window().target()->set_bounds(rect_width(&client), rect_height(&client), window().pixel_aspect()); + window().target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); } if (m_shaders != nullptr) { // do not transform primitives (scale, offset) if shaders are enabled, the shaders will handle the transformation - win->target()->set_transform_container(!m_shaders->enabled()); + window().target()->set_transform_container(!m_shaders->enabled()); } - return &win->target()->get_primitives(); -} - - -//============================================================ -// renderer_d3d9::init -//============================================================ - -bool renderer_d3d9::init(running_machine &machine) -{ - d3dintf = new d3d_base; - - d3dintf->d3d9_dll = osd::dynamic_module::open({ "d3d9.dll" }); - - d3d9_create_fn d3d9_create_ptr = d3dintf->d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9"); - if (d3d9_create_ptr == nullptr) - { - delete d3dintf; - d3dintf = nullptr; - osd_printf_verbose("Direct3D: Unable to find Direct3D 9 runtime library\n"); - return true; - } - - d3dintf->d3dobj = (*d3d9_create_ptr)(D3D_SDK_VERSION); - if (d3dintf->d3dobj == nullptr) - { - delete d3dintf; - d3dintf = nullptr; - osd_printf_verbose("Direct3D: Unable to initialize Direct3D 9\n"); - return true; - } - - osd_printf_verbose("Direct3D: Using Direct3D 9\n"); - - return false; + return &window().target()->get_primitives(); } @@ -242,7 +308,12 @@ int renderer_d3d9::draw(const int update) return check; begin_frame(); + + // reset blend mode + set_blendmode(BLENDMODE_NONE); + process_primitives(); + end_frame(); return 0; @@ -254,8 +325,12 @@ void renderer_d3d9::set_texture(texture_info *texture) { m_last_texture = texture; m_last_texture_flags = (texture == nullptr ? 0 : texture->get_flags()); + if (m_shaders->enabled()) + { + m_shaders->set_texture(texture); + } + HRESULT result = m_device->SetTexture(0, (texture == nullptr) ? get_default_texture()->get_finaltex() : texture->get_finaltex()); - m_shaders->set_texture(texture); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device set_texture call\n", result); } @@ -353,15 +428,20 @@ void renderer_d3d9::set_blendmode(int blendmode) } // adjust the bits that changed + bool new_blend_enable = false; if (blendenable != m_last_blendenable) { m_last_blendenable = blendenable; + if (blendenable) + { + new_blend_enable = true; + } HRESULT result = m_device->SetRenderState(D3DRS_ALPHABLENDENABLE, blendenable); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result); } - if (blendop != m_last_blendop) + if (blendop != m_last_blendop || new_blend_enable) { m_last_blendop = blendop; HRESULT result = m_device->SetRenderState(D3DRS_BLENDOP, blendop); @@ -369,7 +449,7 @@ void renderer_d3d9::set_blendmode(int blendmode) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result); } - if (blendsrc != m_last_blendsrc) + if (blendsrc != m_last_blendsrc || new_blend_enable) { m_last_blendsrc = blendsrc; HRESULT result = m_device->SetRenderState(D3DRS_SRCBLEND, blendsrc); @@ -377,7 +457,7 @@ void renderer_d3d9::set_blendmode(int blendmode) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderState call\n", result); } - if (blenddst != m_last_blenddst) + if (blenddst != m_last_blenddst || new_blend_enable) { m_last_blenddst = blenddst; HRESULT result = m_device->SetRenderState(D3DRS_DESTBLEND, blenddst); @@ -398,14 +478,12 @@ void renderer_d3d9::reset_render_states() m_last_wrap = (D3DTEXTUREADDRESS)-1; } -d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d) +d3d_texture_manager::d3d_texture_manager(renderer_d3d9 &d3d, IDirect3D9 *d3dobj) + : m_renderer(d3d) + , m_default_texture(nullptr) { - m_renderer = d3d; - - m_default_texture = nullptr; - D3DCAPS9 caps; - HRESULT result = d3dintf->d3dobj->GetDeviceCaps(d3d->get_adapter(), D3DDEVTYPE_HAL, &caps); + HRESULT result = d3dobj->GetDeviceCaps(d3d.get_adapter(), D3DDEVTYPE_HAL, &caps); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result); @@ -417,35 +495,30 @@ d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d) // pick a YUV texture format m_yuv_format = D3DFMT_UYVY; - result = d3dintf->d3dobj->CheckDeviceFormat(d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY); + result = d3dobj->CheckDeviceFormat(d3d.get_adapter(), D3DDEVTYPE_HAL, d3d.get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY); if (FAILED(result)) { m_yuv_format = D3DFMT_YUY2; - result = d3dintf->d3dobj->CheckDeviceFormat(d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); + result = d3dobj->CheckDeviceFormat(d3d.get_adapter(), D3DDEVTYPE_HAL, d3d.get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); if (FAILED(result)) m_yuv_format = D3DFMT_A8R8G8B8; } osd_printf_verbose("Direct3D: YUV format = %s\n", (m_yuv_format == D3DFMT_YUY2) ? "YUY2" : (m_yuv_format == D3DFMT_UYVY) ? "UYVY" : "RGB"); - auto win = d3d->assert_window(); - // set the max texture size - win->target()->set_max_texture_size(m_texture_max_width, m_texture_max_height); - osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", (int)m_texture_max_width, (int)m_texture_max_height); + d3d.window().target()->set_max_texture_size(m_texture_max_width, m_texture_max_height); + osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", m_texture_max_width, m_texture_max_height); } void d3d_texture_manager::create_resources() { - auto win = m_renderer->assert_window(); - m_default_bitmap.allocate(8, 8); - m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); - if (m_default_bitmap.valid()) { - render_texinfo texture; + m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); // fake in the basic data so it looks like it came from render.c + render_texinfo texture; texture.base = m_default_bitmap.raw_pixptr(0); texture.rowpixels = m_default_bitmap.rowpixels(); texture.width = m_default_bitmap.width(); @@ -456,7 +529,7 @@ void d3d_texture_manager::create_resources() texture.old_id = ~0ULL; // now create it - auto tex = std::make_unique<texture_info>(this, &texture, win->prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + auto tex = std::make_unique<texture_info>(*this, &texture, m_renderer.window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); m_default_texture = tex.get(); m_texture_list.push_back(std::move(tex)); } @@ -465,7 +538,6 @@ void d3d_texture_manager::create_resources() void d3d_texture_manager::delete_resources() { // is part of m_texlist and will be free'd there - //delete m_default_texture; m_default_texture = nullptr; // free all textures @@ -479,16 +551,16 @@ uint32_t d3d_texture_manager::texture_compute_hash(const render_texinfo *texture texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, uint32_t flags) { - uint32_t hash = texture_compute_hash(texinfo, flags); + const uint32_t hash = texture_compute_hash(texinfo, flags); // find a match for (auto it = m_texture_list.begin(); it != m_texture_list.end(); it++) { - auto test_screen = (uint32_t)((*it)->get_texinfo().unique_id >> 57); - uint32_t test_page = (uint32_t)((*it)->get_texinfo().unique_id >> 56) & 1; - auto prim_screen = (uint32_t)(texinfo->unique_id >> 57); - uint32_t prim_page = (uint32_t)(texinfo->unique_id >> 56) & 1; - if (test_screen != prim_screen || test_page != prim_page) + const uint32_t test_screen = uint32_t((*it)->get_texinfo().unique_id >> 57); + const uint32_t test_page = uint32_t((*it)->get_texinfo().unique_id >> 56) & 1; + const uint32_t prim_screen = uint32_t(texinfo->unique_id >> 57); + const uint32_t prim_page = uint32_t(texinfo->unique_id >> 56) & 1; + if ((test_screen != prim_screen) || (test_page != prim_page)) continue; if ((*it)->get_hash() == hash && @@ -504,11 +576,35 @@ texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, u return nullptr; } -renderer_d3d9::renderer_d3d9(std::shared_ptr<osd_window> window) - : osd_renderer(window, FLAG_NONE), m_adapter(0), m_width(0), m_height(0), m_refresh(0), m_create_error_count(0), m_device(nullptr), m_gamma_supported(0), m_pixformat(), - m_vertexbuf(nullptr), m_lockedbuf(nullptr), m_numverts(0), m_vectorbatch(nullptr), m_batchindex(0), m_numpolys(0), m_toggle(false), - m_screen_format(), m_last_texture(nullptr), m_last_texture_flags(0), m_last_blendenable(0), m_last_blendop(0), m_last_blendsrc(0), m_last_blenddst(0), m_last_filter(0), - m_last_wrap(), m_last_modmode(0), m_shaders(nullptr), m_texture_manager() +renderer_d3d9::renderer_d3d9(osd_window &window, const IDirect3D9Ptr &d3dobj) + : osd_renderer(window) + , m_d3dobj(d3dobj) + , m_adapter(0) + , m_width(0) + , m_height(0) + , m_refresh(0) + , m_create_error_count(0) + , m_post_fx_available(true) + , m_gamma_supported(0) + , m_pixformat() + , m_lockedbuf(nullptr) + , m_numverts(0) + , m_vectorbatch(nullptr) + , m_batchindex(0) + , m_numpolys(0) + , m_toggle(false) + , m_screen_format() + , m_last_texture(nullptr) + , m_last_texture_flags(0) + , m_last_blendenable(0) + , m_last_blendop(0) + , m_last_blendsrc(0) + , m_last_blenddst(0) + , m_last_filter(0) + , m_last_wrap() + , m_last_modmode(0) + , m_shaders(nullptr) + , m_texture_manager() { } @@ -523,8 +619,7 @@ int renderer_d3d9::initialize() } // create the device immediately for the full screen case (defer for window mode in update_window_size()) - auto win = assert_window(); - if (win->fullscreen() && device_create(std::static_pointer_cast<win_window_info>(win->main_window())->platform_window())) + if (window().fullscreen() && device_create(dynamic_cast<win_window_info &>(window()).main_window()->platform_window())) { return false; } @@ -534,10 +629,8 @@ int renderer_d3d9::initialize() int renderer_d3d9::pre_window_draw_check() { - auto win = assert_window(); - // if we're in the middle of resizing, leave things alone - if (win->m_resize_state == RESIZE_STATE_RESIZING) + if (dynamic_cast<win_window_info &>(window()).m_resize_state == win_window_info::RESIZE_STATE_RESIZING) return 0; // check if shaders should be toggled @@ -561,7 +654,7 @@ int renderer_d3d9::pre_window_draw_check() } // if we have a device, check the cooperative level - if (m_device != nullptr) + if (m_device) { if (device_test_cooperative()) { @@ -570,14 +663,14 @@ int renderer_d3d9::pre_window_draw_check() } // in window mode, we need to track the window size - if (!win->fullscreen() || m_device == nullptr) + if (!window().fullscreen() || !m_device) { // if the size changes, skip this update since the render target will be out of date if (update_window_size()) return 0; // if we have no device, after updating the size, return an error so GDI can try - if (m_device == nullptr) + if (!m_device) return 1; } @@ -586,18 +679,16 @@ int renderer_d3d9::pre_window_draw_check() void d3d_texture_manager::update_textures() { - auto win = m_renderer->assert_window(); - - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *m_renderer.window().m_primlist) { if (prim.texture.base != nullptr) { texture_info *texture = find_texinfo(&prim.texture, prim.flags); if (texture == nullptr) { - int prescale = m_renderer->get_shaders()->enabled() ? 1 : win->prescale(); + const int prescale = m_renderer.get_shaders()->enabled() ? 1 : m_renderer.window().prescale(); - auto tex = std::make_unique<texture_info>(this, &prim.texture, prescale, prim.flags); + auto tex = std::make_unique<texture_info>(*this, &prim.texture, prescale, prim.flags); texture = tex.get(); m_texture_list.push_back(std::move(tex)); } @@ -613,21 +704,19 @@ void d3d_texture_manager::update_textures() } } - if (!m_renderer->get_shaders()->enabled()) - { + if (!m_renderer.get_shaders()->enabled()) return; - } int screen_index = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *m_renderer.window().m_primlist) { if (PRIMFLAG_GET_SCREENTEX(prim.flags)) { - if (!m_renderer->get_shaders()->get_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) + if (!m_renderer.get_shaders()->get_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) { - if (!m_renderer->get_shaders()->create_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) + if (!m_renderer.get_shaders()->create_texture_target(&prim, prim.texture.width, prim.texture.height, screen_index)) { - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); break; } } @@ -635,11 +724,11 @@ void d3d_texture_manager::update_textures() } else if (PRIMFLAG_GET_VECTORBUF(prim.flags)) { - if (!m_renderer->get_shaders()->get_vector_target(&prim, screen_index)) + if (!m_renderer.get_shaders()->get_vector_target(&prim, screen_index)) { - if (!m_renderer->get_shaders()->create_vector_target(&prim, screen_index)) + if (!m_renderer.get_shaders()->create_vector_target(&prim, screen_index)) { - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); break; } } @@ -650,13 +739,11 @@ void d3d_texture_manager::update_textures() void renderer_d3d9::begin_frame() { - auto win = assert_window(); - - HRESULT result = m_device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); + HRESULT result = m_device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0xff,0,0,0), 0, 0); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device clear call\n", result); - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // first update any textures m_texture_manager->update_textures(); @@ -667,16 +754,17 @@ void renderer_d3d9::begin_frame() osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result); if (m_shaders->enabled()) - m_shaders->init_fsfx_quad(); + m_shaders->begin_frame(window().m_primlist); + + // set an initial default texture + set_texture(nullptr); } void renderer_d3d9::process_primitives() { - auto win = assert_window(); - // loop over line primitives int vector_count = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { if (prim.type == render_primitive::LINE && PRIMFLAG_GET_VECTOR(prim.flags)) { @@ -685,7 +773,7 @@ void renderer_d3d9::process_primitives() } // Rotating index for vector time offsets - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { switch (prim.type) { @@ -716,13 +804,14 @@ void renderer_d3d9::process_primitives() void renderer_d3d9::end_frame() { - auto win = assert_window(); - - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); // flush any pending polygons primitive_flush_pending(); + if (m_shaders->enabled()) + m_shaders->end_frame(); + // finish the scene HRESULT result = m_device->EndScene(); if (FAILED(result)) @@ -736,8 +825,6 @@ void renderer_d3d9::end_frame() void renderer_d3d9::update_presentation_parameters() { - auto win = assert_window(); - memset(&m_presentation, 0, sizeof(m_presentation)); m_presentation.BackBufferWidth = m_width; m_presentation.BackBufferHeight = m_height; @@ -745,14 +832,14 @@ void renderer_d3d9::update_presentation_parameters() m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1; m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE; m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD; - m_presentation.hDeviceWindow = std::static_pointer_cast<win_window_info>(win)->platform_window(); - m_presentation.Windowed = !win->fullscreen() || win->win_has_menu(); + m_presentation.hDeviceWindow = dynamic_cast<win_window_info &>(window()).platform_window(); + m_presentation.Windowed = !window().fullscreen(); m_presentation.EnableAutoDepthStencil = FALSE; m_presentation.AutoDepthStencilFormat = D3DFMT_D16; m_presentation.Flags = 0; m_presentation.FullScreen_RefreshRateInHz = m_refresh; m_presentation.PresentationInterval = ( - (video_config.triplebuf && win->fullscreen()) + (video_config.triplebuf && window().fullscreen()) || video_config.waitvsync || video_config.syncrefresh) ? D3DPRESENT_INTERVAL_ONE @@ -767,13 +854,11 @@ void renderer_d3d9::update_gamma_ramp() return; } - auto win = assert_window(); - // set the gamma if we need to - if (win->fullscreen()) + if (window().fullscreen()) { // only set the gamma if it's not 1.0 - auto &options = downcast<windows_options &>(win->machine().options()); + auto &options = downcast<windows_options &>(window().machine().options()); float brightness = options.full_screen_brightness(); float contrast = options.full_screen_contrast(); float gamma = options.full_screen_gamma(); @@ -803,27 +888,23 @@ int renderer_d3d9::device_create(HWND hwnd) HWND device_hwnd = GetAncestor(hwnd, GA_ROOT); // if a device exists, free it - if (m_device != nullptr) - { + if (m_device) device_delete(); - } // verify the caps if (!device_verify_caps()) - { return 1; - } - m_texture_manager = std::make_unique<d3d_texture_manager>(this); + m_texture_manager = std::make_unique<d3d_texture_manager>(*this, m_d3dobj.Get()); // try for XRGB first m_screen_format = D3DFMT_X8R8G8B8; - HRESULT result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); + HRESULT result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); if (FAILED(result)) { // if not, try for ARGB m_screen_format = D3DFMT_A8R8G8B8; - result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); + result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, m_screen_format); if (FAILED(result)) { osd_printf_error("Error: unable to configure a screen texture format\n"); @@ -835,8 +916,13 @@ int renderer_d3d9::device_create(HWND hwnd) update_presentation_parameters(); // create the D3D device - result = d3dintf->d3dobj->CreateDevice( - m_adapter, D3DDEVTYPE_HAL, device_hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device); + result = m_d3dobj->CreateDevice( + m_adapter, + D3DDEVTYPE_HAL, + device_hwnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, + &m_presentation, + &m_device); if (FAILED(result)) { // if we got a "DEVICELOST" error, it may be transitory; count it and only fail if @@ -869,16 +955,13 @@ int renderer_d3d9::device_create(HWND hwnd) int renderer_d3d9::device_create_resources() { - auto win = assert_window(); - // create shaders only once - if (m_shaders == nullptr) - { - m_shaders = new shaders; - } + if (!m_shaders) + m_shaders = std::make_unique<shaders>(); - if (m_shaders->init(d3dintf, &win->machine(), this)) + if (m_shaders->init(m_d3dobj.Get(), &window().machine(), this)) { + m_post_fx_available = true; m_shaders->init_slider_list(); m_sliders_dirty = true; } @@ -892,12 +975,12 @@ int renderer_d3d9::device_create_resources() // allocate a vertex buffer to use HRESULT result = m_device->CreateVertexBuffer( - sizeof(vertex) * VERTEX_BUFFER_SIZE, - D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, - VERTEX_BASE_FORMAT | ((m_shaders->enabled()) - ? D3DFVF_XYZW - : D3DFVF_XYZRHW), - D3DPOOL_DEFAULT, &m_vertexbuf, nullptr); + sizeof(vertex) * VERTEX_BUFFER_SIZE, + D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, + VERTEX_BASE_FORMAT | (m_shaders->enabled() ? D3DFVF_XYZW : D3DFVF_XYZRHW), + D3DPOOL_DEFAULT, + &m_vertexbuf, + nullptr); if (FAILED(result)) { osd_printf_error("Error creating vertex buffer (%08X)\n", (uint32_t)result); @@ -906,9 +989,7 @@ int renderer_d3d9::device_create_resources() // set the vertex format result = m_device->SetFVF( - (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled()) - ? D3DFVF_XYZW - : D3DFVF_XYZRHW))); + D3DFORMAT(VERTEX_BASE_FORMAT | (m_shaders->enabled() ? D3DFVF_XYZW : D3DFVF_XYZRHW))); if (FAILED(result)) { osd_printf_error("Error setting vertex format (%08X)\n", (uint32_t)result); @@ -960,24 +1041,6 @@ int renderer_d3d9::device_create_resources() renderer_d3d9::~renderer_d3d9() { device_delete(); - - // todo: throws error when switching from full screen to window mode - //if (m_shaders != nullptr) - //{ - // // delete the HLSL interface - // delete m_shaders; - // m_shaders = nullptr; - //} -} - -void renderer_d3d9::exit() -{ - if (d3dintf != nullptr) - { - d3dintf->d3dobj->Release(); - delete d3dintf; - d3dintf = nullptr; - } } void renderer_d3d9::device_delete() @@ -990,11 +1053,7 @@ void renderer_d3d9::device_delete() m_texture_manager.reset(); // free the device itself - if (m_device != nullptr) - { - m_device->Release(); - m_device = nullptr; - } + m_device.Reset(); } @@ -1004,22 +1063,14 @@ void renderer_d3d9::device_delete() void renderer_d3d9::device_delete_resources() { - if (m_shaders != nullptr) - { + if (m_shaders) m_shaders->delete_resources(); - } - if (m_texture_manager != nullptr) - { + if (m_texture_manager) m_texture_manager->delete_resources(); - } // free the vertex buffer - if (m_vertexbuf != nullptr) - { - m_vertexbuf->Release(); - m_vertexbuf = nullptr; - } + m_vertexbuf.Reset(); } @@ -1032,7 +1083,7 @@ bool renderer_d3d9::device_verify_caps() bool success = true; D3DCAPS9 caps; - HRESULT result = d3dintf->d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps); + HRESULT result = m_d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps); if (FAILED(result)) { osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result); @@ -1042,7 +1093,7 @@ bool renderer_d3d9::device_verify_caps() if (caps.MaxPixelShader30InstructionSlots < 512) { osd_printf_verbose("Direct3D: Warning - Device does not support Pixel Shader 3.0, falling back to non-PS rendering\n"); - d3dintf->post_fx_available = false; + set_post_fx_unavailable(); } // verify presentation capabilities @@ -1097,7 +1148,7 @@ bool renderer_d3d9::device_verify_caps() } // verify texture formats - result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); + result = m_d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); if (FAILED(result)) { osd_printf_error("Direct3D Error: Your graphics card does not support the A8R8G8B8 texture format.\n"); @@ -1173,7 +1224,7 @@ int renderer_d3d9::config_adapter_mode() // get the identifier D3DADAPTER_IDENTIFIER9 id; - HRESULT result = d3dintf->d3dobj->GetAdapterIdentifier(m_adapter, 0, &id); + HRESULT result = m_d3dobj->GetAdapterIdentifier(m_adapter, 0, &id); if (FAILED(result)) { osd_printf_error("Error getting identifier for adapter #%d\n", m_adapter); @@ -1183,22 +1234,20 @@ int renderer_d3d9::config_adapter_mode() osd_printf_verbose("Direct3D: Configuring adapter #%d = %s\n", m_adapter, id.Description); // get the current display mode - result = d3dintf->d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode); + result = m_d3dobj->GetAdapterDisplayMode(m_adapter, &m_origmode); if (FAILED(result)) { osd_printf_error("Error getting mode for adapter #%d\n", m_adapter); return 1; } - auto win = assert_window(); - - // choose a resolution: window mode case - if (!win->fullscreen() || !video_config.switchres || win->win_has_menu()) + if (!window().fullscreen() || !video_config.switchres) { - RECT client; + // choose a resolution: window mode case // bounds are from the window client rect - GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen()); + RECT client; + GetClientRectExceptMenu(dynamic_cast<win_window_info &>(window()).platform_window(), &client, window().fullscreen()); m_width = client.right - client.left; m_height = client.bottom - client.top; @@ -1209,14 +1258,14 @@ int renderer_d3d9::config_adapter_mode() // make sure it's a pixel format we can get behind if (m_pixformat != D3DFMT_X1R5G5B5 && m_pixformat != D3DFMT_R5G6B5 && m_pixformat != D3DFMT_X8R8G8B8) { - osd_printf_error("Device %s currently in an unsupported mode\n", win->monitor()->devicename()); + osd_printf_error("Device %s currently in an unsupported mode\n", window().monitor()->devicename()); return 1; } } - - // choose a resolution: full screen mode case else { + // choose a resolution: full screen mode case + // default to the current mode exactly m_width = m_origmode.Width; m_height = m_origmode.Height; @@ -1229,10 +1278,10 @@ int renderer_d3d9::config_adapter_mode() } // see if we can handle the device type - result = d3dintf->d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !win->fullscreen()); + result = m_d3dobj->CheckDeviceType(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !window().fullscreen()); if (FAILED(result)) { - osd_printf_error("Proposed video mode not supported on device %s\n", win->monitor()->devicename()); + osd_printf_error("Proposed video mode not supported on device %s\n", window().monitor()->devicename()); return 1; } @@ -1246,18 +1295,16 @@ int renderer_d3d9::config_adapter_mode() int renderer_d3d9::get_adapter_for_monitor() { - int maxadapter = d3dintf->d3dobj->GetAdapterCount(); - - auto win = assert_window(); + int maxadapter = m_d3dobj->GetAdapterCount(); // iterate over adapters until we error or find a match for (int adapternum = 0; adapternum < maxadapter; adapternum++) { // get the monitor for this adapter - HMONITOR curmonitor = d3dintf->d3dobj->GetAdapterMonitor(adapternum); + HMONITOR curmonitor = m_d3dobj->GetAdapterMonitor(adapternum); // if we match the proposed monitor, this is it - if (curmonitor == reinterpret_cast<HMONITOR>(win->monitor()->oshandle())) + if (curmonitor == reinterpret_cast<HMONITOR>(window().monitor()->oshandle())) { return adapternum; } @@ -1278,10 +1325,8 @@ void renderer_d3d9::pick_best_mode() int32_t minwidth, minheight; float best_score = 0.0f; - auto win = assert_window(); - // determine the refresh rate of the primary screen - const screen_device *primary_screen = screen_device_enumerator(win->machine().root_device()).first(); + const screen_device *primary_screen = screen_device_enumerator(window().machine().root_device()).first(); if (primary_screen != nullptr) { target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); @@ -1291,14 +1336,14 @@ void renderer_d3d9::pick_best_mode() // note: technically we should not be calling this from an alternate window // thread; however, it is only done during init time, and the init code on // the main thread is waiting for us to finish, so it is safe to do so here - win->target()->compute_minimum_size(minwidth, minheight); + window().target()->compute_minimum_size(minwidth, minheight); // use those as the target for now int32_t target_width = minwidth; int32_t target_height = minheight; // determine the maximum number of modes - int maxmodes = d3dintf->d3dobj->GetAdapterModeCount(m_adapter, D3DFMT_X8R8G8B8); + int maxmodes = m_d3dobj->GetAdapterModeCount(m_adapter, D3DFMT_X8R8G8B8); // enumerate all the video modes and find the best match osd_printf_verbose("Direct3D: Selecting video mode...\n"); @@ -1306,7 +1351,7 @@ void renderer_d3d9::pick_best_mode() { // check this mode D3DDISPLAYMODE mode; - HRESULT result = d3dintf->d3dobj->EnumAdapterModes(m_adapter, D3DFMT_X8R8G8B8, modenum, &mode); + HRESULT result = m_d3dobj->EnumAdapterModes(m_adapter, D3DFMT_X8R8G8B8, modenum, &mode); if (FAILED(result)) break; @@ -1326,7 +1371,7 @@ void renderer_d3d9::pick_best_mode() size_score *= 0.1f; // if we're looking for a particular mode, that's a winner - if (mode.Width == win->m_win_config.width && mode.Height == win->m_win_config.height) + if (mode.Width == window().m_win_config.width && mode.Height == window().m_win_config.height) size_score = 2.0f; // compute refresh score @@ -1337,7 +1382,7 @@ void renderer_d3d9::pick_best_mode() refresh_score *= 0.1f; // if we're looking for a particular refresh, make sure it matches - if (mode.RefreshRate == win->m_win_config.refresh) + if (mode.RefreshRate == window().m_win_config.refresh) refresh_score = 2.0f; // weight size and refresh equally @@ -1364,33 +1409,32 @@ void renderer_d3d9::pick_best_mode() bool renderer_d3d9::update_window_size() { - auto win = assert_window(); - // get the current window bounds + auto &win = dynamic_cast<win_window_info &>(window()); RECT client; - GetClientRectExceptMenu(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client, win->fullscreen()); + GetClientRectExceptMenu(win.platform_window(), &client, window().fullscreen()); // if we have a device and matching width/height, nothing to do - if (m_device != nullptr && rect_width(&client) == m_width && rect_height(&client) == m_height) + if (m_device && rect_width(&client) == m_width && rect_height(&client) == m_height) { // clear out any pending resizing if the area didn't change - if (win->m_resize_state == RESIZE_STATE_PENDING) - win->m_resize_state = RESIZE_STATE_NORMAL; + if (win.m_resize_state == win_window_info::RESIZE_STATE_PENDING) + win.m_resize_state = win_window_info::RESIZE_STATE_NORMAL; return false; } // if we're in the middle of resizing, leave it alone as well - if (win->m_resize_state == RESIZE_STATE_RESIZING) + if (win.m_resize_state == win_window_info::RESIZE_STATE_RESIZING) return false; // set the new bounds and create the device again m_width = rect_width(&client); m_height = rect_height(&client); - if (device_create(std::static_pointer_cast<win_window_info>(win->main_window())->platform_window())) + if (device_create(win.main_window()->platform_window())) return false; // reset the resize state to normal, and indicate we made a change - win->m_resize_state = RESIZE_STATE_NORMAL; + win.m_resize_state = win_window_info::RESIZE_STATE_NORMAL; return true; } @@ -1401,8 +1445,6 @@ bool renderer_d3d9::update_window_size() void renderer_d3d9::batch_vectors(int vector_count) { - auto win = assert_window(); - float quad_width = 0.0f; float quad_height = 0.0f; float target_width = 0.0f; @@ -1412,9 +1454,10 @@ void renderer_d3d9::batch_vectors(int vector_count) int triangle_count = vector_count * 2; m_vectorbatch = mesh_alloc(vertex_count); m_batchindex = 0; + uint32_t tint = 0xffffffff; uint32_t cached_flags = 0; - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { switch (prim.type) { @@ -1423,6 +1466,12 @@ void renderer_d3d9::batch_vectors(int vector_count) { batch_vector(prim); cached_flags = prim.flags; + + const uint8_t a = (uint8_t)std::round(prim.color.a * 255); + const uint8_t r = (uint8_t)std::round(prim.color.r * 255); + const uint8_t g = (uint8_t)std::round(prim.color.g * 255); + const uint8_t b = (uint8_t)std::round(prim.color.b * 255); + tint = (a << 24) | (b << 16) | (g << 8) | r; } break; @@ -1433,6 +1482,12 @@ void renderer_d3d9::batch_vectors(int vector_count) quad_height = prim.get_quad_height(); target_width = prim.get_full_quad_width(); target_height = prim.get_full_quad_height(); + + const uint8_t a = (uint8_t)std::round(prim.color.a * 255); + const uint8_t r = (uint8_t)std::round(prim.color.r * 255); + const uint8_t g = (uint8_t)std::round(prim.color.g * 255); + const uint8_t b = (uint8_t)std::round(prim.color.b * 255); + tint = (a << 24) | (b << 16) | (g << 8) | r; } break; @@ -1446,15 +1501,15 @@ void renderer_d3d9::batch_vectors(int vector_count) if (m_shaders->enabled()) { bool orientation_swap_xy = - (win->machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; + (window().machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; bool rotation_swap_xy = - (win->target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; + (window().target()->orientation() & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; bool swap_xy = orientation_swap_xy ^ rotation_swap_xy; - bool rotation_0 = win->target()->orientation() == ROT0; - bool rotation_90 = win->target()->orientation() == ROT90; - bool rotation_180 = win->target()->orientation() == ROT180; - bool rotation_270 = win->target()->orientation() == ROT270; + bool rotation_0 = window().target()->orientation() == ROT0; + bool rotation_90 = window().target()->orientation() == ROT90; + bool rotation_180 = window().target()->orientation() == ROT180; + bool rotation_270 = window().target()->orientation() == ROT270; bool flip_x = ((rotation_0 || rotation_270) && orientation_swap_xy) || ((rotation_180 || rotation_270) && !orientation_swap_xy); @@ -1510,7 +1565,7 @@ void renderer_d3d9::batch_vectors(int vector_count) } // now add a polygon entry - m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, triangle_count, vertex_count, cached_flags, nullptr, D3DTOP_MODULATE, quad_width, quad_height); + m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, triangle_count, vertex_count, cached_flags, nullptr, D3DTOP_MODULATE, quad_width, quad_height, tint); m_numpolys++; } @@ -1652,10 +1707,10 @@ void renderer_d3d9::draw_line(const render_primitive &prim) vertex[3].v0 = stop.c.y; // determine the color of the line - auto r = (int32_t)(prim.color.r * 255.0f); - auto g = (int32_t)(prim.color.g * 255.0f); - auto b = (int32_t)(prim.color.b * 255.0f); - auto a = (int32_t)(prim.color.a * 255.0f); + auto r = (int32_t)std::round(prim.color.r * 255.0f); + auto g = (int32_t)std::round(prim.color.g * 255.0f); + auto b = (int32_t)std::round(prim.color.b * 255.0f); + auto a = (int32_t)std::round(prim.color.a * 255.0f); DWORD color = D3DCOLOR_ARGB(a, r, g, b); // set the color, Z parameters to standard values @@ -1667,7 +1722,7 @@ void renderer_d3d9::draw_line(const render_primitive &prim) } // now add a polygon entry - m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, nullptr, D3DTOP_MODULATE, 0.0f, 0.0f); + m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, nullptr, D3DTOP_MODULATE, 0.0f, 0.0f, (uint32_t)color); m_numpolys++; } @@ -1721,10 +1776,10 @@ void renderer_d3d9::draw_quad(const render_primitive &prim) } // determine the color, allowing for over modulation - auto r = (int32_t)(prim.color.r * 255.0f); - auto g = (int32_t)(prim.color.g * 255.0f); - auto b = (int32_t)(prim.color.b * 255.0f); - auto a = (int32_t)(prim.color.a * 255.0f); + auto r = (int32_t)std::round(prim.color.r * 255.0f); + auto g = (int32_t)std::round(prim.color.g * 255.0f); + auto b = (int32_t)std::round(prim.color.b * 255.0f); + auto a = (int32_t)std::round(prim.color.a * 255.0f); DWORD color = D3DCOLOR_ARGB(a, r, g, b); // adjust half pixel X/Y offset, set the color, Z parameters to standard values @@ -1738,7 +1793,7 @@ void renderer_d3d9::draw_quad(const render_primitive &prim) } // now add a polygon entry - m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, texture, D3DTOP_MODULATE, quad_width, quad_height); + m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, texture, D3DTOP_MODULATE, quad_width, quad_height, (uint32_t)color); m_numpolys++; } @@ -1798,7 +1853,7 @@ void renderer_d3d9::primitive_flush_pending() m_lockedbuf = nullptr; // set the stream - result = m_device->SetStreamSource(0, m_vertexbuf, 0, sizeof(vertex)); + result = m_device->SetStreamSource(0, m_vertexbuf.Get(), 0, sizeof(vertex)); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result); @@ -1826,9 +1881,17 @@ void renderer_d3d9::primitive_flush_pending() newfilter = FALSE; if (PRIMFLAG_GET_SCREENTEX(flags)) newfilter = video_config.filter; - set_filter(newfilter); - set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); - set_modmode(m_poly[polynum].modmode()); + + if (m_shaders->enabled()) + { + m_shaders->set_filter(newfilter); + } + else + { + set_filter(newfilter); + set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); + set_modmode(m_poly[polynum].modmode()); + } } if (vertnum + m_poly[polynum].numverts() > m_numverts) @@ -1841,9 +1904,6 @@ void renderer_d3d9::primitive_flush_pending() if(m_shaders->enabled()) { - // reset blend mode (handled by shader passes) - set_blendmode(BLENDMODE_NONE); - m_shaders->render_quad(&m_poly[polynum], vertnum); } else @@ -1896,19 +1956,6 @@ void renderer_d3d9::set_sliders_dirty() texture_info::~texture_info() { - if (m_d3dfinaltex != nullptr) - { - if (m_d3dtex == m_d3dfinaltex) - m_d3dtex = nullptr; - - m_d3dfinaltex->Release(); - } - - if (m_d3dtex != nullptr) - m_d3dtex->Release(); - - if (m_d3dsurface != nullptr) - m_d3dsurface->Release(); } @@ -1916,153 +1963,117 @@ texture_info::~texture_info() // texture_info constructor //============================================================ -texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* texsource, int prescale, uint32_t flags) +texture_info::texture_info(d3d_texture_manager &manager, const render_texinfo* texsource, int prescale, uint32_t flags) + : m_texture_manager(manager) + , m_renderer(manager.get_d3d()) + , m_hash(manager.texture_compute_hash(texsource, flags)) + , m_flags(flags) + , m_texinfo(*texsource) + , m_type(!PRIMFLAG_GET_SCREENTEX(flags) ? TEXTURE_TYPE_PLAIN : TEXTURE_TYPE_DYNAMIC) // required to compute texture size + , m_xprescale(PRIMFLAG_GET_SCREENTEX(flags) ? prescale : 1) + , m_yprescale(PRIMFLAG_GET_SCREENTEX(flags) ? prescale : 1) { - HRESULT result; - - // fill in the core data - m_texture_manager = manager; - m_renderer = m_texture_manager->get_d3d(); - m_hash = m_texture_manager->texture_compute_hash(texsource, flags); - m_flags = flags; - m_texinfo = *texsource; - m_xprescale = prescale; - m_yprescale = prescale; - - m_d3dtex = nullptr; - m_d3dsurface = nullptr; - m_d3dfinaltex = nullptr; - - // determine texture type, required to compute texture size - if (!PRIMFLAG_GET_SCREENTEX(flags)) - { - m_type = TEXTURE_TYPE_PLAIN; - } - else - { - m_type = TEXTURE_TYPE_DYNAMIC; - } - // compute the size compute_size(texsource->width, texsource->height); - // non-screen textures are easy if (!PRIMFLAG_GET_SCREENTEX(flags)) { + // non-screen textures are easy assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16); - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex, nullptr); + const HRESULT result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex, nullptr); if (FAILED(result)) goto error; + m_d3dfinaltex = m_d3dtex; } - - // screen textures are allocated differently else { - D3DFORMAT format; - DWORD usage = D3DUSAGE_DYNAMIC; - D3DPOOL pool = D3DPOOL_DEFAULT; - int maxdim = std::max(m_renderer->get_presentation()->BackBufferWidth, m_renderer->get_presentation()->BackBufferHeight); + // screen textures are allocated differently // pick the format + const DWORD usage = D3DUSAGE_DYNAMIC; + const D3DPOOL pool = D3DPOOL_DEFAULT; + D3DFORMAT format; if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_YUY16) - { - format = m_texture_manager->get_yuv_format(); - } + format = m_texture_manager.get_yuv_format(); else if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_ARGB32) - { format = D3DFMT_A8R8G8B8; - } else - { - format = m_renderer->get_screen_format(); - } + format = m_renderer.get_screen_format(); // don't prescale above screen size - while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale >= 2 * maxdim) - { + const int maxdim = std::max( + m_renderer.get_presentation()->BackBufferWidth, + m_renderer.get_presentation()->BackBufferHeight); + + while ((m_xprescale > 1) && ((m_rawdims.c.x * m_xprescale) >= (2 * maxdim))) m_xprescale--; - } - while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale > manager->get_max_texture_width()) - { + while ((m_xprescale > 1) && ((m_rawdims.c.x * m_xprescale) > manager.get_max_texture_width())) m_xprescale--; - } - while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale >= 2 * maxdim) - { + + while ((m_yprescale > 1) && ((m_rawdims.c.y * m_yprescale) >= (2 * maxdim))) m_yprescale--; - } - while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale > manager->get_max_texture_height()) - { + while ((m_yprescale > 1) && ((m_rawdims.c.y * m_yprescale) > manager.get_max_texture_height())) m_yprescale--; - } - - auto win = m_renderer->assert_window(); - int prescale = win->prescale(); - if (m_xprescale != prescale || m_yprescale != prescale) - { + const int prescale = m_renderer.window().prescale(); + if ((m_xprescale != prescale) || (m_yprescale != prescale)) osd_printf_verbose("Direct3D: adjusting prescale from %dx%d to %dx%d\n", prescale, prescale, m_xprescale, m_yprescale); - } // loop until we allocate something or error + HRESULT result; for (int attempt = 0; attempt < 2; attempt++) { - // second attempt is always 1:1 - if (attempt == 1) - { - m_xprescale = m_yprescale = 1; - } - - // screen textures with no prescaling are pretty easy - if (m_xprescale == 1 && m_yprescale == 1) + if ((m_xprescale == 1) && (m_yprescale == 1)) { - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); + // screen textures with no prescaling are pretty easy + result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); if (result == D3D_OK) { m_d3dfinaltex = m_d3dtex; break; } } - // screen textures with prescaling require two allocations else { - result = m_renderer->get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); - if (FAILED(result)) + // screen textures with prescaling require two allocations + result = m_renderer.get_device()->CreateTexture(m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex, nullptr); + if (result == D3D_OK) { - continue; - } + // for the target surface, we allocate a render target texture + const int scwidth = m_rawdims.c.x * m_xprescale; + const int scheight = m_rawdims.c.y * m_yprescale; - // for the target surface, we allocate a render target texture - int scwidth = m_rawdims.c.x * m_xprescale; - int scheight = m_rawdims.c.y * m_yprescale; + // target surfaces typically cannot be YCbCr, so we always pick RGB in that case + const D3DFORMAT finalfmt = (format != m_texture_manager.get_yuv_format()) ? format : D3DFMT_A8R8G8B8; - // target surfaces typically cannot be YCbCr, so we always pick RGB in that case - D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8; + result = m_renderer.get_device()->CreateTexture(scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex, nullptr); + if (result == D3D_OK) + break; - result = m_renderer->get_device()->CreateTexture(scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex, nullptr); - if (result == D3D_OK) - { - break; + m_d3dtex.Reset(); } - - m_d3dtex->Release(); - m_d3dtex = nullptr; } + + // second attempt is always 1:1 + m_xprescale = m_yprescale = 1; } + if (FAILED(result)) + goto error; } // copy the data to the texture + assert(m_d3dtex); + assert(m_d3dfinaltex); set_data(texsource, flags); return; error: - d3dintf->post_fx_available = false; + m_renderer.set_post_fx_unavailable(); osd_printf_error("Direct3D: Critical warning: A texture failed to allocate. Expect things to get bad quickly.\n"); - if (m_d3dsurface != nullptr) - m_d3dsurface->Release(); - if (m_d3dtex != nullptr) - m_d3dtex->Release(); + m_d3dsurface.Reset(); + m_d3dtex.Reset(); } @@ -2076,11 +2087,11 @@ void texture_info::compute_size_subroutine(int texwidth, int texheight, int* p_w int finalwidth = texwidth; // adjust the aspect ratio if we need to - while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect()) + while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager.get_max_texture_aspect()) { finalwidth *= 2; } - while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect()) + while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager.get_max_texture_aspect()) { finalheight *= 2; } @@ -2102,7 +2113,7 @@ void texture_info::compute_size(int texwidth, int texheight) m_xborderpix = 0; m_yborderpix = 0; - bool shaders_enabled = m_renderer->get_shaders()->enabled(); + bool shaders_enabled = m_renderer.get_shaders()->enabled(); bool wrap_texture = (m_flags & PRIMFLAG_TEXWRAP_MASK) == PRIMFLAG_TEXWRAP_MASK; // skip border when shaders are enabled @@ -2126,7 +2137,7 @@ void texture_info::compute_size(int texwidth, int texheight) compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight); // if we added pixels for the border, and that just barely pushed us over, take it back - if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) + if (finalwidth > m_texture_manager.get_max_texture_width() || finalheight > m_texture_manager.get_max_texture_height()) { finalheight = texheight; finalwidth = texwidth; @@ -2139,10 +2150,18 @@ void texture_info::compute_size(int texwidth, int texheight) } // if we're above the max width/height, do what? - if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) + if (finalwidth > m_texture_manager.get_max_texture_width() || finalheight > m_texture_manager.get_max_texture_height()) { static bool printed = false; - if (!printed) osd_printf_warning("Texture too big! (wanted: %dx%d, max is %dx%d)\n", finalwidth, finalheight, (int)m_texture_manager->get_max_texture_width(), (int)m_texture_manager->get_max_texture_height()); + if (!printed) + { + osd_printf_warning( + "Texture too big! (wanted: %dx%d, max is %dx%d)\n", + finalwidth, + finalheight, + m_texture_manager.get_max_texture_width(), + m_texture_manager.get_max_texture_height()); + } printed = true; } @@ -2395,9 +2414,9 @@ void texture_info::set_data(const render_texinfo *texsource, uint32_t flags) break; case TEXFORMAT_YUY16: - if (m_texture_manager->get_yuv_format() == D3DFMT_YUY2) + if (m_texture_manager.get_yuv_format() == D3DFMT_YUY2) copyline_yuy16_to_yuy2((uint16_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); - else if (m_texture_manager->get_yuv_format() == D3DFMT_UYVY) + else if (m_texture_manager.get_yuv_format() == D3DFMT_UYVY) copyline_yuy16_to_uyvy((uint16_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); else copyline_yuy16_to_argb((uint32_t *)dst, (uint16_t *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette); @@ -2432,48 +2451,51 @@ void texture_info::set_data(const render_texinfo *texsource, uint32_t flags) void texture_info::prescale() { - IDirect3DSurface9 *scale_surface; - HRESULT result; - int i; - // if we don't need to, just skip it - if (m_d3dtex == m_d3dfinaltex) + if (m_d3dtex.Get() == m_d3dfinaltex.Get()) + { + assert(m_xprescale == 1); + assert(m_yprescale == 1); return; + } + + assert(m_d3dtex); + assert((m_xprescale > 1) || (m_yprescale > 1)); + HRESULT result; // for all cases, we need to get the surface of the render target + Microsoft::WRL::ComPtr<IDirect3DSurface9> scale_surface; result = m_d3dfinaltex->GetSurfaceLevel(0, &scale_surface); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during texture GetSurfaceLevel call\n", result); // if we have an offscreen plain surface, we can just StretchRect to it - IDirect3DSurface9 *backbuffer; - - assert(m_d3dtex != nullptr); // first remember the original render target and set the new one - result = m_renderer->get_device()->GetRenderTarget(0, &backbuffer); + Microsoft::WRL::ComPtr<IDirect3DSurface9> backbuffer; + result = m_renderer.get_device()->GetRenderTarget(0, &backbuffer); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device GetRenderTarget call\n", result); - result = m_renderer->get_device()->SetRenderTarget(0, scale_surface); + result = m_renderer.get_device()->SetRenderTarget(0, scale_surface.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 1\n", result); - m_renderer->reset_render_states(); + m_renderer.reset_render_states(); // start the scene - result = m_renderer->get_device()->BeginScene(); + result = m_renderer.get_device()->BeginScene(); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device BeginScene call\n", result); // configure the rendering pipeline - m_renderer->set_filter(FALSE); - m_renderer->set_blendmode(BLENDMODE_NONE); - result = m_renderer->get_device()->SetTexture(0, m_d3dtex); + m_renderer.set_filter(FALSE); + m_renderer.set_blendmode(BLENDMODE_NONE); + result = m_renderer.get_device()->SetTexture(0, m_d3dtex.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetTexture call\n", result); // lock the vertex buffer vertex *lockedbuf; - result = m_renderer->get_vertex_buffer()->Lock(0, 0, (VOID **)&lockedbuf, D3DLOCK_DISCARD); + result = m_renderer.get_vertex_buffer()->Lock(0, 0, (VOID **)&lockedbuf, D3DLOCK_DISCARD); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during vertex buffer lock call\n", result); @@ -2498,7 +2520,7 @@ void texture_info::prescale() lockedbuf[3].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; // reset the remaining vertex parameters - for (i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { lockedbuf[i].z = 0.0f; lockedbuf[i].rhw = 1.0f; @@ -2506,32 +2528,32 @@ void texture_info::prescale() } // unlock the vertex buffer - result = m_renderer->get_vertex_buffer()->Unlock(); + result = m_renderer.get_vertex_buffer()->Unlock(); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during vertex buffer unlock call\n", result); // set the stream and draw the triangle strip - result = m_renderer->get_device()->SetStreamSource(0, m_renderer->get_vertex_buffer(), 0, sizeof(vertex)); + result = m_renderer.get_device()->SetStreamSource(0, m_renderer.get_vertex_buffer(), 0, sizeof(vertex)); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetStreamSource call\n", result); - result = m_renderer->get_device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + result = m_renderer.get_device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device DrawPrimitive call\n", result); // end the scene - result = m_renderer->get_device()->EndScene(); + result = m_renderer.get_device()->EndScene(); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device end_scene call\n", result); // reset the render target and release our reference to the backbuffer - result = m_renderer->get_device()->SetRenderTarget(0, backbuffer); + result = m_renderer.get_device()->SetRenderTarget(0, backbuffer.Get()); if (FAILED(result)) osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call 2\n", result); - backbuffer->Release(); - m_renderer->reset_render_states(); + backbuffer.Reset(); + m_renderer.reset_render_states(); // release our reference to the target surface - scale_surface->Release(); + scale_surface.Reset(); } @@ -2541,35 +2563,6 @@ void texture_info::prescale() d3d_render_target::~d3d_render_target() { - for (int index = 0; index < MAX_BLOOM_COUNT; index++) - { - if (bloom_texture[index] != nullptr) - bloom_texture[index]->Release(); - - if (bloom_surface[index] != nullptr) - bloom_surface[index]->Release(); - } - - for (int index = 0; index < 2; index++) - { - if (source_texture[index] != nullptr) - source_texture[index]->Release(); - - if (source_surface[index] != nullptr) - source_surface[index]->Release(); - - if (target_texture[index] != nullptr) - target_texture[index]->Release(); - - if (target_surface[index] != nullptr) - target_surface[index]->Release(); - } - - if (cache_texture != nullptr) - cache_texture->Release(); - - if (cache_surface != nullptr) - cache_surface->Release(); } @@ -2610,9 +2603,7 @@ bool d3d_render_target::init(renderer_d3d9 *d3d, int source_width, int source_he cache_texture->GetSurfaceLevel(0, &cache_surface); - auto win = d3d->assert_window(); - - const screen_device *first_screen = screen_device_enumerator(win->machine().root_device()).first(); + const screen_device *first_screen = screen_device_enumerator(d3d->window().machine().root_device()).first(); bool vector_screen = first_screen != nullptr && first_screen->screen_type() == SCREEN_TYPE_VECTOR; diff --git a/src/osd/modules/render/drawd3d.h b/src/osd/modules/render/drawd3d.h index 2fa4a30873c..3ab7651d87c 100644 --- a/src/osd/modules/render/drawd3d.h +++ b/src/osd/modules/render/drawd3d.h @@ -10,20 +10,24 @@ #pragma once +#include "d3d/d3dcomm.h" -#ifdef OSD_WINDOWS +#include "modules/lib/osdlib.h" +#include "modules/osdwindow.h" + +#include "sliderdirtynotifier.h" #include <windows.h> #include <tchar.h> #include <mmsystem.h> #include <d3d9.h> #include <d3dx9.h> -#include <cmath> #undef interface -#include "d3d/d3dcomm.h" -#include "sliderdirtynotifier.h" -#include "modules/lib/osdlib.h" +#include <memory> +#include <vector> +#include <cmath> + //============================================================ // CONSTANTS @@ -36,15 +40,6 @@ // TYPE DEFINITIONS //============================================================ -struct d3d_base -{ - // internal objects - IDirect3D9 *d3dobj; - bool post_fx_available; - - osd::dynamic_module::ptr d3d9_dll; -}; - class shaders; struct hlsl_options; @@ -52,11 +47,10 @@ struct hlsl_options; class renderer_d3d9 : public osd_renderer, public slider_dirty_notifier { public: - renderer_d3d9(std::shared_ptr<osd_window> window); - virtual ~renderer_d3d9(); + using IDirect3D9Ptr = Microsoft::WRL::ComPtr<IDirect3D9>; - static bool init(running_machine &machine); - static void exit(); + renderer_d3d9(osd_window &window, const IDirect3D9Ptr &d3dobj); + virtual ~renderer_d3d9(); virtual int create() override; virtual render_primitive_list *get_primitives() override; @@ -113,11 +107,13 @@ public: vec2f get_dims() const { return vec2f(m_width, m_height); } int get_height() const { return m_height; } int get_refresh() const { return m_refresh; } + bool post_fx_available() const { return m_post_fx_available; } + void set_post_fx_unavailable() { m_post_fx_available = false; } - IDirect3DDevice9 * get_device() const { return m_device; } + IDirect3DDevice9 * get_device() const { return m_device.Get(); } D3DPRESENT_PARAMETERS * get_presentation() { return &m_presentation; } - IDirect3DVertexBuffer9 *get_vertex_buffer() const { return m_vertexbuf; } + IDirect3DVertexBuffer9 *get_vertex_buffer() const { return m_vertexbuf.Get(); } void set_toggle(bool toggle) { m_toggle = toggle; } @@ -125,27 +121,32 @@ public: D3DFORMAT get_pixel_format() const { return m_pixformat; } D3DDISPLAYMODE get_origmode() const { return m_origmode; } - uint32_t get_last_texture_flags() const { return m_last_texture_flags; } + uint32_t get_last_texture_flags() const { return m_last_texture_flags; } d3d_texture_manager * get_texture_manager() const { return m_texture_manager.get(); } texture_info * get_default_texture(); - shaders * get_shaders() const { return m_shaders; } + shaders * get_shaders() const { return m_shaders.get(); } private: + using IDirect3DDevice9Ptr = Microsoft::WRL::ComPtr<IDirect3DDevice9>; + using IDirect3DVertexBuffer9Ptr = Microsoft::WRL::ComPtr<IDirect3DVertexBuffer9>; + + const IDirect3D9Ptr m_d3dobj; // Direct3D 9 API object int m_adapter; // ordinal adapter number int m_width; // current width int m_height; // current height int m_refresh; // current refresh rate int m_create_error_count; // number of consecutive create errors + bool m_post_fx_available; - IDirect3DDevice9 * m_device; // pointer to the Direct3DDevice object + IDirect3DDevice9Ptr m_device; // pointer to the Direct3DDevice object int m_gamma_supported; // is full screen gamma supported? D3DPRESENT_PARAMETERS m_presentation; // set of presentation parameters D3DDISPLAYMODE m_origmode; // original display mode for the adapter D3DFORMAT m_pixformat; // pixel format we are using - IDirect3DVertexBuffer9 *m_vertexbuf; // pointer to the vertex buffer object + IDirect3DVertexBuffer9Ptr m_vertexbuf; // pointer to the vertex buffer object vertex * m_lockedbuf; // pointer to the locked vertex buffer int m_numverts; // number of accumulated vertices @@ -160,20 +161,18 @@ private: D3DFORMAT m_screen_format; // format to use for screen textures texture_info * m_last_texture; // previous texture - uint32_t m_last_texture_flags; // previous texture flags + uint32_t m_last_texture_flags; // previous texture flags int m_last_blendenable; // previous blendmode int m_last_blendop; // previous blendmode int m_last_blendsrc; // previous blendmode int m_last_blenddst; // previous blendmode int m_last_filter; // previous texture filter - uint32_t m_last_wrap; // previous wrap state + uint32_t m_last_wrap; // previous wrap state int m_last_modmode; // previous texture modulation - shaders * m_shaders; // HLSL interface + std::unique_ptr<shaders> m_shaders; // HLSL interface std::unique_ptr<d3d_texture_manager> m_texture_manager; // texture manager }; -#endif // OSD_WINDOWS - #endif // MAME_OSD_MODULES_RENDER_DRAWD3D_H diff --git a/src/osd/modules/render/drawgdi.cpp b/src/osd/modules/render/drawgdi.cpp index 32dac94c24a..f922ca24e8f 100644 --- a/src/osd/modules/render/drawgdi.cpp +++ b/src/osd/modules/render/drawgdi.cpp @@ -2,21 +2,53 @@ // copyright-holders:Aaron Giles //============================================================ // -// drawgdi.c - Win32 GDI drawing +// drawgdi.cpp - Win32 GDI drawing // //============================================================ +#include "render_module.h" + +#include "modules/osdmodule.h" + +#if defined(OSD_WINDOWS) + +#include "window.h" + +// emu #include "emu.h" -#include "drawgdi.h" #include "rendersw.hxx" -//============================================================ -// destructor -//============================================================ +// standard windows headers +#include <windows.h> + + +namespace osd { + +namespace { -renderer_gdi::~renderer_gdi() +// renderer_gdi is the information for the current screen +class renderer_gdi : public osd_renderer { -} +public: + renderer_gdi(osd_window &window) + : osd_renderer(window) + , m_bmdata(nullptr) + , m_bmsize(0) + { + } + + virtual int create() override; + virtual render_primitive_list *get_primitives() override; + virtual int draw(const int update) override; + virtual void save() override {} + virtual void record() override {} + virtual void toggle_fsfx() override {} + +private: + BITMAPINFO m_bminfo; + std::unique_ptr<uint8_t []> m_bmdata; + size_t m_bmsize; +}; //============================================================ // renderer_gdi::create @@ -34,6 +66,7 @@ int renderer_gdi::create() m_bminfo.bmiHeader.biYPelsPerMeter = 0; m_bminfo.bmiHeader.biClrUsed = 0; m_bminfo.bmiHeader.biClrImportant = 0; + return 0; } @@ -43,16 +76,12 @@ int renderer_gdi::create() render_primitive_list *renderer_gdi::get_primitives() { - auto win = try_getwindow(); - if (win == nullptr) + osd_dim const dimensions = window().get_size(); + if ((dimensions.width() <= 0) || (dimensions.height() <= 0)) return nullptr; - RECT client; - GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client); - if ((rect_width(&client) == 0) || (rect_height(&client) == 0)) - return nullptr; - win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(dimensions.width(), dimensions.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); } //============================================================ @@ -61,23 +90,24 @@ render_primitive_list *renderer_gdi::get_primitives() int renderer_gdi::draw(const int update) { - auto win = assert_window(); + auto &win = dynamic_cast<win_window_info &>(window()); // we don't have any special resize behaviors - if (win->m_resize_state == RESIZE_STATE_PENDING) - win->m_resize_state = RESIZE_STATE_NORMAL; + if (win.m_resize_state == win_window_info::RESIZE_STATE_PENDING) + win.m_resize_state = win_window_info::RESIZE_STATE_NORMAL; // get the target bounds RECT bounds; - GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &bounds); + GetClientRect(win.platform_window(), &bounds); // compute width/height/pitch of target - int width = rect_width(&bounds); - int height = rect_height(&bounds); - int pitch = (width + 3) & ~3; + osd_dim const dimensions = win.get_size(); + int const width = dimensions.width(); + int const height = dimensions.height(); + int const pitch = (width + 3) & ~3; // make sure our temporary bitmap is big enough - if (pitch * height * 4 > m_bmsize) + if ((pitch * height * 4) > m_bmsize) { m_bmsize = pitch * height * 4 * 2; m_bmdata.reset(); @@ -85,9 +115,9 @@ int renderer_gdi::draw(const int update) } // draw the primitives to the bitmap - win->m_primlist->acquire_lock(); - software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*win->m_primlist, m_bmdata.get(), width, height, pitch); - win->m_primlist->release_lock(); + win.m_primlist->acquire_lock(); + software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*win.m_primlist, m_bmdata.get(), width, height, pitch); + win.m_primlist->release_lock(); // fill in bitmap-specific info m_bminfo.bmiHeader.biWidth = pitch; @@ -95,8 +125,43 @@ int renderer_gdi::draw(const int update) // blit to the screen StretchDIBits( - win->m_dc, 0, 0, width, height, + win.m_dc, 0, 0, width, height, 0, 0, width, height, m_bmdata.get(), &m_bminfo, DIB_RGB_COLORS, SRCCOPY); + return 0; } + + +class video_gdi : public osd_module, public render_module +{ +public: + video_gdi() : osd_module(OSD_RENDERER_PROVIDER, "gdi") { } + + virtual int init(osd_interface &osd, osd_options const &options) override { return 0; } + virtual void exit() override { } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE; } +}; + +std::unique_ptr<osd_renderer> video_gdi::create(osd_window &window) +{ + return std::make_unique<renderer_gdi>(window); +} + +} // anonymous namespace + +} // namespace osd + + +#else // defined(OSD_WINDOWS) + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_gdi, OSD_RENDERER_PROVIDER, "gdi") } } + +#endif // defined(OSD_WINDOWS) + + +MODULE_DEFINITION(RENDERER_GDI, osd::video_gdi) diff --git a/src/osd/modules/render/drawgdi.h b/src/osd/modules/render/drawgdi.h deleted file mode 100644 index 0dfc4bf2641..00000000000 --- a/src/osd/modules/render/drawgdi.h +++ /dev/null @@ -1,55 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -//============================================================ -// -// drawgdi.h - Win32 GDI drawing -// -//============================================================ -#ifndef MAME_OSD_MODULES_RENDER_DRAWGDI_H -#define MAME_OSD_MODULES_RENDER_DRAWGDI_H - -#pragma once - - -// standard windows headers -#include <windows.h> - -// MAME headers - -// MAMEOS headers -#include "window.h" - - -//============================================================ -// TYPE DEFINITIONS -//============================================================ - -/* renderer_gdi is the information for the current screen */ -class renderer_gdi : public osd_renderer -{ -public: - renderer_gdi(std::shared_ptr<osd_window> window) - : osd_renderer(window, FLAG_NONE) - , m_bmdata(nullptr) - , m_bmsize(0) - { - } - virtual ~renderer_gdi(); - - static bool init(running_machine &machine) { return false; } - static void exit() { } - - virtual int create() override; - virtual render_primitive_list *get_primitives() override; - virtual int draw(const int update) override; - virtual void save() override {} - virtual void record() override {} - virtual void toggle_fsfx() override {} - -private: - BITMAPINFO m_bminfo; - std::unique_ptr<uint8_t []> m_bmdata; - size_t m_bmsize; -}; - -#endif // MAME_OSD_MODULES_RENDER_DRAWGDI_H diff --git a/src/osd/modules/render/drawnone.cpp b/src/osd/modules/render/drawnone.cpp index 6f591879038..55ce1bbed18 100644 --- a/src/osd/modules/render/drawnone.cpp +++ b/src/osd/modules/render/drawnone.cpp @@ -6,25 +6,76 @@ // //============================================================ -// standard windows headers -#include <windows.h> +#include "render_module.h" -#include "drawnone.h" +#include "modules/lib/osdobj_common.h" +#include "modules/osdmodule.h" +#include "modules/osdwindow.h" -//============================================================ -// drawnone_window_get_primitives -//============================================================ +#include "main.h" +#include "render.h" + +#include <memory> + + +namespace osd { + +namespace { + +class renderer_none : public osd_renderer +{ +public: + renderer_none(osd_window &window) : osd_renderer(window) { } + + virtual int create() override { return 0; } + virtual render_primitive_list *get_primitives() override; + virtual int draw(const int update) override { return 0; } + virtual void save() override { } + virtual void record() override { } + virtual void toggle_fsfx() override { } +}; render_primitive_list *renderer_none::get_primitives() { - auto win = try_getwindow(); - if (win == nullptr) + osd_dim const dimensions = window().get_size(); + if ((dimensions.width() <= 0) || (dimensions.height() <= 0)) return nullptr; - RECT client; - GetClientRect(std::static_pointer_cast<win_window_info>(win)->platform_window(), &client); - if ((rect_width(&client) == 0) || (rect_height(&client) == 0)) - return nullptr; - win->target()->set_bounds(rect_width(&client), rect_height(&client), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(dimensions.width(), dimensions.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); } + + +class video_none : public osd_module, public render_module +{ +public: + video_none() : osd_module(OSD_RENDERER_PROVIDER, "none") { } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override { } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return 0; } +}; + +int video_none::init(osd_interface &osd, osd_options const &options) +{ + if (!emulator_info::standalone() && (options.seconds_to_run() == 0)) + osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n"); + + return 0; +} + +std::unique_ptr<osd_renderer> video_none::create(osd_window &window) +{ + return std::make_unique<renderer_none>(window); +} + +} // anonymous namespace + +} // namespace osd + + +MODULE_DEFINITION(RENDERER_NONE, osd::video_none) diff --git a/src/osd/modules/render/drawnone.h b/src/osd/modules/render/drawnone.h deleted file mode 100644 index c884f969204..00000000000 --- a/src/osd/modules/render/drawnone.h +++ /dev/null @@ -1,33 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -//============================================================ -// -// drawnone.h - stub "nothing" drawer -// -//============================================================ - -#ifndef __DRAWNONE__ -#define __DRAWNONE__ - -#include "window.h" - -class renderer_none : public osd_renderer -{ -public: - renderer_none(std::shared_ptr<osd_window> window) - : osd_renderer(window, FLAG_NONE) { } - - virtual ~renderer_none() { } - - static bool init(running_machine &machine) { return false; } - static void exit() { } - - virtual int create() override { return 0; } - virtual render_primitive_list *get_primitives() override; - virtual int draw(const int update) override { return 0; } - virtual void save() override { } - virtual void record() override { } - virtual void toggle_fsfx() override { } -}; - -#endif // __DRAWNONE__ diff --git a/src/osd/modules/render/drawogl.cpp b/src/osd/modules/render/drawogl.cpp index 9e200f3817c..f9f76946bf4 100644 --- a/src/osd/modules/render/drawogl.cpp +++ b/src/osd/modules/render/drawogl.cpp @@ -12,37 +12,60 @@ // //============================================================ -// standard C headers -#include <cmath> -#include <cstdio> +#include "render_module.h" + +#include "modules/osdmodule.h" + +#if USE_OPENGL -// MAME headers +// will be picked up from specific OSD implementation +#include "window.h" + +// OSD common headers +#include "modules/lib/osdlib.h" +#include "modules/lib/osdobj_common.h" +#include "modules/opengl/gl_shader_mgr.h" #include "osdcomm.h" -#include "emu.h" -#include "emuopts.h" -#ifdef OSD_MAC +// OSD headers +#if defined(OSD_WINDOWS) +typedef uint64_t HashT; +#include "winglcontext.h" +#elif defined(OSD_MAC) #define GL_SILENCE_DEPRECATION (1) +#include "osdmac.h" +#else +#include "osdsdl.h" +#include "sdlglcontext.h" #endif +// emu +#include "emucore.h" +#include "emuopts.h" +#include "render.h" + + #if !defined(OSD_WINDOWS) && !defined(OSD_MAC) + // standard SDL headers #define TOBEMIGRATED 1 #include <SDL2/SDL.h> -#endif -#include "modules/lib/osdlib.h" -#include "modules/lib/osdobj_common.h" +#endif // !defined(OSD_WINDOWS && !defined(OSD_MAC) -// OpenGL headers -#include "modules/opengl/osd_opengl.h" -#include "modules/opengl/gl_shader_tool.h" -#include "modules/opengl/gl_shader_mgr.h" +// standard C headers +#include <cmath> +#include <cstdio> +#include <memory> +#include <utility> + #if defined(SDLMAME_MACOSX) || defined(OSD_MAC) + #include <cstring> #include <cstdio> + #include <sys/types.h> #include <sys/sysctl.h> @@ -72,7 +95,13 @@ typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum m_target, GLuint r typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum m_target, GLenum internalformat, GLsizei width, GLsizei height); typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum m_target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); -#endif + +#endif // defined(SDLMAME_MACOSX) || defined(OSD_MAC) + + +namespace osd { + +namespace { // make sure the extensions compile OK everywhere #ifndef GL_TEXTURE_STORAGE_HINT_APPLE @@ -128,7 +157,283 @@ typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuin #define GL_DEPTH_COMPONENT32 0x81A7 #endif -#include "drawogl.h" + +//============================================================ +// Configuration +//============================================================ + +#define GLSL_SHADER_MAX 10 + +struct ogl_video_config +{ + ogl_video_config() = default; + + bool vbo = false; + bool pbo = false; + bool allowtexturerect = false; // allow GL_ARB_texture_rectangle, default: no + bool forcepow2texture = false; // force power of two textures, default: no + bool glsl = false; + int glsl_filter = 0; // glsl filtering, >0 disables filter + std::string glsl_shader_mamebm[GLSL_SHADER_MAX]; // custom glsl shader set, mame bitmap + int glsl_shader_mamebm_num = 0; // custom glsl shader set number, mame bitmap + std::string glsl_shader_scrn[GLSL_SHADER_MAX]; // custom glsl shader set, screen bitmap + int glsl_shader_scrn_num = 0; // custom glsl shader number, screen bitmap +}; + + +//============================================================ +// Textures +//============================================================ + +/* ogl_texture_info holds information about a texture */ +class ogl_texture_info +{ +public: + ogl_texture_info( +#if defined(USE_DISPATCH_GL) + osd_gl_dispatch *gld +#endif + ) +#if defined(USE_DISPATCH_GL) + : gl_dispatch(gld) +#endif + { + for (int i=0; i<2; i++) + { + mpass_textureunit[i] = 0; + mpass_texture_mamebm[i] = 0; + mpass_fbo_mamebm[i] = 0; + mpass_texture_scrn[i] = 0; + mpass_fbo_scrn[i] = 0; + } + for (int i=0; i<8; i++) + texCoord[i] = 0.0f; + } + +#if defined(USE_DISPATCH_GL) + osd_gl_dispatch *const gl_dispatch; // name is magic, can't be changed +#endif + HashT hash = 0; // hash value for the texture (must be >= pointer size) + uint32_t flags = 0; // rendering flags + render_texinfo texinfo; // copy of the texture info + int rawwidth = 0, rawheight = 0; // raw width/height of the texture + int rawwidth_create = 0; // raw width/height, pow2 compatible, if needed + int rawheight_create = 0; // (create and initial set the texture, not for copy!) + int type = 0; // what type of texture are we? + int format = 0; // texture format + int borderpix = 0; // do we have a 1 pixel border? + int xprescale = 0; // what is our X prescale factor? + int yprescale = 0; // what is our Y prescale factor? + int nocopy = 0; // must the texture date be copied? + + uint32_t texture = 0; // OpenGL texture "name"/ID + + GLenum texTarget = 0; // OpenGL texture target + int texpow2 = 0; // Is this texture pow2 + + uint32_t mpass_dest_idx = 0; // Multipass dest idx [0..1] + uint32_t mpass_textureunit[2]; // texture unit names for GLSL + + uint32_t mpass_texture_mamebm[2]; // Multipass OpenGL texture "name"/ID for the shader + uint32_t mpass_fbo_mamebm[2]; // framebuffer object for this texture, multipass + uint32_t mpass_texture_scrn[2]; // Multipass OpenGL texture "name"/ID for the shader + uint32_t mpass_fbo_scrn[2]; // framebuffer object for this texture, multipass + + uint32_t pbo = 0; // pixel buffer object for this texture (DYNAMIC only!) + uint32_t *data = nullptr; // pixels for the texture + bool data_own = false; // do we own / allocated it ? + GLfloat texCoord[8]; + GLuint texCoordBufferName; + +}; + +// renderer_ogl is the information about OpenGL for the current screen +class renderer_ogl : public osd_renderer +{ +public: + renderer_ogl(osd_window &window, ogl_video_config const &ogl_config) + : osd_renderer(window) + , m_ogl_config(ogl_config) + , m_blittimer(0) + , m_width(0) + , m_height(0) + , m_blit_dim(0, 0) + , m_initialized(0) + , m_last_blendmode(0) + , m_texture_max_width(0) + , m_texture_max_height(0) + , m_texpoweroftwo(0) + , m_usevbo(0) + , m_usepbo(0) + , m_usefbo(0) + , m_useglsl(0) + , m_glsl_program_num(0) + , m_glsl_program_mb2sc(0) + , m_usetexturerect(0) + , m_init_context(0) + , m_last_hofs(0.0f) + , m_last_vofs(0.0f) + , m_surf_w(0) + , m_surf_h(0) + { + for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++) + m_texhash[i] = nullptr; + for (int i=0; i < 2*GLSL_SHADER_MAX; i++) + m_glsl_program[i] = 0; + for (int i=0; i < 8; i++) + m_texVerticex[i] = 0.0f; + } + virtual ~renderer_ogl() + { + // free the memory in the window + destroy_all_textures(); + } + + virtual int create() override; + virtual int draw(const int update) override; + +#ifndef OSD_WINDOWS + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; +#endif + virtual render_primitive_list *get_primitives() override + { + osd_dim nd = window().get_size(); + if (nd != m_blit_dim) + { + m_blit_dim = nd; + notify_changed(); + } + if ((m_blit_dim.width() == 0) || (m_blit_dim.height() == 0)) + return nullptr; + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); + } + +#ifdef OSD_WINDOWS + virtual void save() override { } + virtual void record() override { } + virtual void toggle_fsfx() override { } +#endif + +private: + static const uint32_t HASH_SIZE = ((1 << 18) + 1); + static const uint32_t OVERFLOW_SIZE = (1 << 12); + + void destroy_all_textures(); + + void loadGLExtensions(); + void loadgl_functions(); + void initialize_gl(); + void set_blendmode(int blendmode); + HashT texture_compute_hash(const render_texinfo *texture, uint32_t flags); + void texture_compute_type_subroutine(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); + void texture_compute_size_subroutine(ogl_texture_info *texture, uint32_t flags, + uint32_t width, uint32_t height, + int* p_width, int* p_height, int* p_width_create, int* p_height_create); + void texture_compute_size_type(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); + ogl_texture_info *texture_create(const render_texinfo *texsource, uint32_t flags); + int texture_shader_create(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); + ogl_texture_info *texture_find(const render_primitive *prim); + void texture_coord_update(ogl_texture_info *texture, const render_primitive *prim, int shaderIdx); + void texture_mpass_flip(ogl_texture_info *texture, int shaderIdx); + void texture_shader_update(ogl_texture_info *texture, render_container *container, int shaderIdx); + ogl_texture_info * texture_update(const render_primitive *prim, int shaderIdx); + void texture_disable(ogl_texture_info * texture); + void texture_all_disable(); + + int gl_checkFramebufferStatus() const; + int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) const; + void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) const; + + int gl_check_error(bool log, const char *file, int line) const + { + GLenum const glerr = glGetError(); + if (GL_NO_ERROR != glerr) + { + if (log) + osd_printf_warning("%s:%d: GL Error: %d 0x%X\n", file, line, int(glerr), unsigned(glerr)); + } + return (GL_NO_ERROR != glerr) ? glerr : 0; + } + +#define GL_CHECK_ERROR_QUIET() gl_check_error(false, __FILE__, __LINE__) +#define GL_CHECK_ERROR_NORMAL() gl_check_error(true, __FILE__, __LINE__) + + ogl_video_config const &m_ogl_config; + + int32_t m_blittimer; + int m_width; + int m_height; + osd_dim m_blit_dim; + + std::unique_ptr<osd_gl_context> m_gl_context; + std::unique_ptr<glsl_shader_info> m_shader_tool; + + int m_initialized; // is everything well initialized, i.e. all GL stuff etc. + // 3D info (GL mode only) + ogl_texture_info * m_texhash[HASH_SIZE + OVERFLOW_SIZE]; + int m_last_blendmode; // previous blendmode + int32_t m_texture_max_width; // texture maximum width + int32_t m_texture_max_height; // texture maximum height + int m_texpoweroftwo; // must textures be power-of-2 sized? + int m_usevbo; // runtime check if VBO is available + int m_usepbo; // runtime check if PBO is available + int m_usefbo; // runtime check if FBO is available + int m_useglsl; // runtime check if GLSL is available + + GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0 + int m_glsl_program_num; // number of GLSL programs + int m_glsl_program_mb2sc; // GLSL program idx, which transforms + // the mame-bitmap. screen-bitmap (size/rotation/..) + // All progs <= glsl_program_mb2sc using the mame bitmap + // as input, otherwise the screen bitmap. + // All progs >= glsl_program_mb2sc using the screen bitmap + // as output, otherwise the mame bitmap. + int m_usetexturerect; // use ARB_texture_rectangle for non-power-of-2, general use + + int m_init_context; // initialize context before next draw + + float m_last_hofs; + float m_last_vofs; + + // Static vars from draogl_window_dra + int32_t m_surf_w; + int32_t m_surf_h; + GLfloat m_texVerticex[8]; + +#if defined(USE_DISPATCH_GL) + std::unique_ptr<osd_gl_dispatch> gl_dispatch; // name is magic, can't be changed +#endif + + // OGL 1.3 +#if defined(GL_ARB_multitexture) && !defined(OSD_MAC) + PFNGLACTIVETEXTUREARBPROC m_glActiveTexture = nullptr; +#else + PFNGLACTIVETEXTUREPROC m_glActiveTexture = nullptr; +#endif + + // VBO + PFNGLGENBUFFERSPROC m_glGenBuffers = nullptr; + PFNGLDELETEBUFFERSPROC m_glDeleteBuffers = nullptr; + PFNGLBINDBUFFERPROC m_glBindBuffer = nullptr; + PFNGLBUFFERDATAPROC m_glBufferData = nullptr; + PFNGLBUFFERSUBDATAPROC m_glBufferSubData = nullptr; + + // PBO + PFNGLMAPBUFFERPROC m_glMapBuffer = nullptr; + PFNGLUNMAPBUFFERPROC m_glUnmapBuffer = nullptr; + + // FBO + PFNGLISFRAMEBUFFEREXTPROC m_glIsFramebuffer = nullptr; + PFNGLBINDFRAMEBUFFEREXTPROC m_glBindFramebuffer = nullptr; + PFNGLDELETEFRAMEBUFFERSEXTPROC m_glDeleteFramebuffers = nullptr; + PFNGLGENFRAMEBUFFERSEXTPROC m_glGenFramebuffers = nullptr; + PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC m_glCheckFramebufferStatus = nullptr; + PFNGLFRAMEBUFFERTEXTURE2DEXTPROC m_glFramebufferTexture2D = nullptr; + + static bool s_shown_video_info; +}; + //============================================================ // DEBUGGING @@ -241,103 +546,22 @@ void renderer_ogl::set_blendmode(int blendmode) } } -//============================================================ -// STATIC VARIABLES -//============================================================ - -// OGL 1.3 -#if defined(GL_ARB_multitexture) && !defined(OSD_MAC) -static PFNGLACTIVETEXTUREARBPROC pfn_glActiveTexture = nullptr; -#else -static PFNGLACTIVETEXTUREPROC pfn_glActiveTexture = nullptr; -#endif - -// VBO -static PFNGLGENBUFFERSPROC pfn_glGenBuffers = nullptr; -static PFNGLDELETEBUFFERSPROC pfn_glDeleteBuffers = nullptr; -static PFNGLBINDBUFFERPROC pfn_glBindBuffer = nullptr; -static PFNGLBUFFERDATAPROC pfn_glBufferData = nullptr; -static PFNGLBUFFERSUBDATAPROC pfn_glBufferSubData = nullptr; - -// PBO -static PFNGLMAPBUFFERPROC pfn_glMapBuffer = nullptr; -static PFNGLUNMAPBUFFERPROC pfn_glUnmapBuffer = nullptr; - -// FBO -static PFNGLISFRAMEBUFFEREXTPROC pfn_glIsFramebuffer = nullptr; -static PFNGLBINDFRAMEBUFFEREXTPROC pfn_glBindFramebuffer = nullptr; -static PFNGLDELETEFRAMEBUFFERSEXTPROC pfn_glDeleteFramebuffers = nullptr; -static PFNGLGENFRAMEBUFFERSEXTPROC pfn_glGenFramebuffers = nullptr; -static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pfn_glCheckFramebufferStatus = nullptr; -static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pfn_glFramebufferTexture2D = nullptr; - -static int glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN; - -//============================================================ -// Textures -//============================================================ - -static void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags); +static int glsl_shader_feature = glsl_shader_info::FEAT_PLAIN; // FIXME: why is this static? //============================================================ // Static Variables //============================================================ bool renderer_ogl::s_shown_video_info = false; -bool renderer_ogl::s_dll_loaded = false; - -void renderer_ogl::init(running_machine &machine) -{ - s_dll_loaded = false; - - load_gl_lib(machine); -#if defined(OSD_WINDOWS) - osd_printf_verbose("Using Windows OpenGL driver\n"); -#else - osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n"); -#endif -} - -//============================================================ -// CONSTRUCTOR & DESTRUCTOR -//============================================================ - -renderer_ogl::~renderer_ogl() -{ - // free the memory in the window - destroy_all_textures(); - - delete m_gl_context; - m_gl_context = nullptr; -} - -void renderer_ogl::exit() -{ - for (int i = 0; i < video_config.glsl_shader_mamebm_num; i++) - { - if (nullptr != video_config.glsl_shader_mamebm[i]) - { - free(video_config.glsl_shader_mamebm[i]); - video_config.glsl_shader_mamebm[i] = nullptr; - } - } - for (int i =0; i < video_config.glsl_shader_scrn_num; i++) - { - if (nullptr != video_config.glsl_shader_scrn[i]) - { - free(video_config.glsl_shader_scrn[i]); - video_config.glsl_shader_scrn[i] = nullptr; - } - } -} //============================================================ // Load the OGL function addresses //============================================================ -static void loadgl_functions(osd_gl_context *context) +void renderer_ogl::loadgl_functions() { -#ifdef USE_DISPATCH_GL +#if defined(USE_DISPATCH_GL) + gl_dispatch = std::make_unique<osd_gl_dispatch>(); int err_count = 0; @@ -345,11 +569,11 @@ static void loadgl_functions(osd_gl_context *context) * while func will be expanded to disp_p->glBegin */ - #define OSD_GL(ret,func,params) \ - if (!( func = (ret (APIENTRY *)params) context->getProcAddress( #func ) )) \ - { err_count++; osd_printf_error("GL function %s not found!\n", #func ); } + #define OSD_GL(ret, func, params) \ + if (!m_gl_context->get_proc_address(func, #func)) \ + { err_count++; osd_printf_error("GL function %s not found!\n", #func); } - #define OSD_GL_UNUSED(ret,func,params) + #define OSD_GL_UNUSED(ret, func, params) #define GET_GLFUNC 1 #include "modules/opengl/osd_opengl.h" @@ -361,45 +585,6 @@ static void loadgl_functions(osd_gl_context *context) #endif } -//============================================================ -// Load GL library -//============================================================ - -#ifdef USE_DISPATCH_GL -osd_gl_dispatch *gl_dispatch = nullptr; -#endif - -void renderer_ogl::load_gl_lib(running_machine &machine) -{ - if (!s_dll_loaded) - { -#ifndef OSD_WINDOWS -#ifdef USE_DISPATCH_GL - /* - * directfb and and x11 use this env var - * SDL_VIDEO_GL_DRIVER - */ - const char *stemp; - - stemp = downcast<sdl_options &>(machine.options()).gl_lib(); - if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) == 0) - stemp = nullptr; - - if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==nullptr - { - fatalerror("Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); - } - osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); - /* FIXME: must be freed as well */ -#endif -#endif -#ifdef USE_DISPATCH_GL - gl_dispatch = new osd_gl_dispatch; -#endif - s_dll_loaded = true; - } -} - void renderer_ogl::initialize_gl() { int has_and_allow_texturerect = 0; @@ -425,7 +610,7 @@ void renderer_ogl::initialize_gl() m_usefbo = 0; m_useglsl = 0; - if (video_config.allowtexturerect && (strstr(extstr, "GL_ARB_texture_rectangle") || strstr(extstr, "GL_EXT_texture_rectangle"))) + if (m_ogl_config.allowtexturerect && (strstr(extstr, "GL_ARB_texture_rectangle") || strstr(extstr, "GL_EXT_texture_rectangle"))) { has_and_allow_texturerect = 1; if (!s_shown_video_info) @@ -435,7 +620,7 @@ void renderer_ogl::initialize_gl() } // does this card support non-power-of-two sized textures? (they're faster, so use them if possible) - if ( !video_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two")) + if ( !m_ogl_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two")) { if (!s_shown_video_info) { @@ -465,7 +650,7 @@ void renderer_ogl::initialize_gl() if (strstr(extstr, "GL_ARB_vertex_buffer_object")) { - m_usevbo = video_config.vbo; + m_usevbo = m_ogl_config.vbo; if (!s_shown_video_info) { if(m_usevbo) @@ -479,7 +664,7 @@ void renderer_ogl::initialize_gl() { if( m_usevbo ) { - m_usepbo = video_config.pbo; + m_usepbo = m_ogl_config.pbo; if (!s_shown_video_info) { if(m_usepbo) @@ -522,7 +707,7 @@ void renderer_ogl::initialize_gl() strstr(extstr, "GL_ARB_fragment_shader") ) { - m_useglsl = video_config.glsl; + m_useglsl = m_ogl_config.glsl; if (!s_shown_video_info) { if(m_useglsl) @@ -562,24 +747,22 @@ void renderer_ogl::initialize_gl() int renderer_ogl::create() { - auto win = assert_window(); - // create renderer #if defined(OSD_WINDOWS) - m_gl_context = new win_gl_context(std::static_pointer_cast<win_window_info>(win)->platform_window()); + m_gl_context.reset(new win_gl_context(dynamic_cast<win_window_info &>(window()).platform_window())); #elif defined(OSD_MAC) // TODO -// m_gl_context = new mac_gl_context(std::static_pointer_cast<mac_window_info>(win)->platform_window()); +// m_gl_context.reset(new mac_gl_context(dynamic_cast<mac_window_info &>(window()).platform_window())); #else - m_gl_context = new sdl_gl_context(std::static_pointer_cast<sdl_window_info>(win)->platform_window()); + m_gl_context.reset(new sdl_gl_context(dynamic_cast<sdl_window_info &>(window()).platform_window())); #endif - if (m_gl_context->LastErrorMsg() != nullptr) + if (!*m_gl_context) { - osd_printf_error("%s\n", m_gl_context->LastErrorMsg()); + char const *const msg = m_gl_context->last_error_message(); + osd_printf_error("Creating OpenGL context failed: %s\n", msg ? msg : "unknown error"); return 1; } - m_gl_context->SetSwapInterval(video_config.waitvsync ? 1 : 0); - + m_gl_context->set_swap_interval(video_config.waitvsync ? 1 : 0); m_blittimer = 0; m_surf_w = 0; @@ -595,10 +778,9 @@ int renderer_ogl::create() /* load any GL function addresses * this must be done here because we need a context */ - loadgl_functions(m_gl_context); + loadgl_functions(); initialize_gl(); - m_init_context = 0; osd_printf_verbose("Leave renderer_ogl::create\n"); @@ -628,27 +810,15 @@ int renderer_ogl::xy_to_render_target(int x, int y, int *xt, int *yt) void renderer_ogl::destroy_all_textures() { - ogl_texture_info *texture = nullptr; - bool lock=false; - int i; - if ( !m_initialized ) + if (!m_initialized) return; - auto win = try_getwindow(); - - // During destroy this can get called - // and the window is no longer available - if (win == nullptr) - return; + m_gl_context->make_current(); - m_gl_context->MakeCurrent(); - - if(win->m_primlist) - { - lock=true; - win->m_primlist->acquire_lock(); - } + bool const lock = bool(window().m_primlist); + if (lock) + window().m_primlist->acquire_lock(); glFinish(); @@ -656,41 +826,39 @@ void renderer_ogl::destroy_all_textures() glFinish(); glDisableClientState(GL_VERTEX_ARRAY); - i=0; - while (i<HASH_SIZE+OVERFLOW_SIZE) + for (int i = 0; i < (HASH_SIZE + OVERFLOW_SIZE); ++i) { - texture = m_texhash[i]; - m_texhash[i] = nullptr; - if (texture != nullptr) + ogl_texture_info *const texture = std::exchange(m_texhash[i], nullptr); + if (texture) { - if(m_usevbo) + if (m_usevbo) { - pfn_glDeleteBuffers( 1, &(texture->texCoordBufferName) ); + m_glDeleteBuffers( 1, &(texture->texCoordBufferName) ); texture->texCoordBufferName=0; } - if(m_usepbo && texture->pbo) + if (m_usepbo && texture->pbo) { - pfn_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) ); + m_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) ); texture->pbo=0; } - if( m_glsl_program_num > 1 ) + if (m_glsl_program_num > 1) { assert(m_usefbo); - pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); + m_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); glDeleteTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]); } - if ( m_glsl_program_mb2sc < m_glsl_program_num - 1 ) + if (m_glsl_program_mb2sc < m_glsl_program_num - 1) { assert(m_usefbo); - pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); + m_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); glDeleteTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]); } glDeleteTextures(1, (GLuint *)&texture->texture); - if ( texture->data_own ) + if (texture->data_own) { free(texture->data); texture->data=nullptr; @@ -698,18 +866,14 @@ void renderer_ogl::destroy_all_textures() } delete texture; } - i++; - } - if ( m_useglsl ) - { - glsl_shader_free(m_glsl); - m_glsl = nullptr; } + m_shader_tool.reset(); + m_initialized = 0; if (lock) - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); } //============================================================ // loadGLExtensions @@ -745,178 +909,138 @@ void renderer_ogl::loadGLExtensions() // Get Pointers To The GL Functions // VBO: - if( m_usevbo ) + if (m_usevbo) { - pfn_glGenBuffers = (PFNGLGENBUFFERSPROC) m_gl_context->getProcAddress("glGenBuffers"); - pfn_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) m_gl_context->getProcAddress("glDeleteBuffers"); - pfn_glBindBuffer = (PFNGLBINDBUFFERPROC) m_gl_context->getProcAddress("glBindBuffer"); - pfn_glBufferData = (PFNGLBUFFERDATAPROC) m_gl_context->getProcAddress("glBufferData"); - pfn_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) m_gl_context->getProcAddress("glBufferSubData"); + m_gl_context->get_proc_address(m_glGenBuffers, "glGenBuffers"); + m_gl_context->get_proc_address(m_glDeleteBuffers, "glDeleteBuffers"); + m_gl_context->get_proc_address(m_glBindBuffer, "glBindBuffer"); + m_gl_context->get_proc_address(m_glBufferData, "glBufferData"); + m_gl_context->get_proc_address(m_glBufferSubData, "glBufferSubData"); } // PBO: - if ( m_usepbo ) + if (m_usepbo) { - pfn_glMapBuffer = (PFNGLMAPBUFFERPROC) m_gl_context->getProcAddress("glMapBuffer"); - pfn_glUnmapBuffer= (PFNGLUNMAPBUFFERPROC) m_gl_context->getProcAddress("glUnmapBuffer"); + m_gl_context->get_proc_address(m_glMapBuffer, "glMapBuffer"); + m_gl_context->get_proc_address(m_glUnmapBuffer, "glUnmapBuffer"); } // FBO: - if ( m_usefbo ) + if (m_usefbo) { - pfn_glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glIsFramebufferEXT"); - pfn_glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glBindFramebufferEXT"); - pfn_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glDeleteFramebuffersEXT"); - pfn_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glGenFramebuffersEXT"); - pfn_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) m_gl_context->getProcAddress("glCheckFramebufferStatusEXT"); - pfn_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) m_gl_context->getProcAddress("glFramebufferTexture2DEXT"); + m_gl_context->get_proc_address(m_glIsFramebuffer, "glIsFramebufferEXT"); + m_gl_context->get_proc_address(m_glBindFramebuffer, "glBindFramebufferEXT"); + m_gl_context->get_proc_address(m_glDeleteFramebuffers, "glDeleteFramebuffersEXT"); + m_gl_context->get_proc_address(m_glGenFramebuffers, "glGenFramebuffersEXT"); + m_gl_context->get_proc_address(m_glCheckFramebufferStatus, "glCheckFramebufferStatusEXT"); + m_gl_context->get_proc_address(m_glFramebufferTexture2D, "glFramebufferTexture2DEXT"); } - if ( m_usevbo && - ( !pfn_glGenBuffers || !pfn_glDeleteBuffers || - !pfn_glBindBuffer || !pfn_glBufferData || !pfn_glBufferSubData - ) ) + if (m_usevbo && (!m_glGenBuffers || !m_glDeleteBuffers || !m_glBindBuffer || !m_glBufferData || !m_glBufferSubData)) { - m_usepbo=false; + m_usepbo = false; if (_once) { - osd_printf_warning("OpenGL: VBO not supported, missing: "); - if (!pfn_glGenBuffers) - { - osd_printf_warning("glGenBuffers, "); - } - if (!pfn_glDeleteBuffers) - { - osd_printf_warning("glDeleteBuffers"); - } - if (!pfn_glBindBuffer) - { - osd_printf_warning("glBindBuffer, "); - } - if (!pfn_glBufferData) - { - osd_printf_warning("glBufferData, "); - } - if (!pfn_glBufferSubData) - { - osd_printf_warning("glBufferSubData, "); - } + osd_printf_warning("OpenGL: VBO not supported, missing:"); + if (!m_glGenBuffers) + osd_printf_warning(" glGenBuffers"); + if (!m_glDeleteBuffers) + osd_printf_warning(" glDeleteBuffers"); + if (!m_glBindBuffer) + osd_printf_warning(" glBindBuffer"); + if (!m_glBufferData) + osd_printf_warning(" glBufferData"); + if (!m_glBufferSubData) + osd_printf_warning(" glBufferSubData"); osd_printf_warning("\n"); } - if ( m_usevbo ) + if (m_usevbo) { if (_once) - { osd_printf_warning("OpenGL: PBO not supported, no VBO support.\n"); - } - m_usepbo=false; + m_usepbo = false; } } - if ( m_usepbo && ( !pfn_glMapBuffer || !pfn_glUnmapBuffer ) ) + if (m_usepbo && (!m_glMapBuffer || !m_glUnmapBuffer)) { - m_usepbo=false; + m_usepbo = false; if (_once) { - osd_printf_warning("OpenGL: PBO not supported, missing: "); - if (!pfn_glMapBuffer) - { - osd_printf_warning("glMapBuffer, "); - } - if (!pfn_glUnmapBuffer) - { - osd_printf_warning("glUnmapBuffer, "); - } + osd_printf_warning("OpenGL: PBO not supported, missing:"); + if (!m_glMapBuffer) + osd_printf_warning(" glMapBuffer"); + if (!m_glUnmapBuffer) + osd_printf_warning(" glUnmapBuffer"); osd_printf_warning("\n"); } } if ( m_usefbo && - ( !pfn_glIsFramebuffer || !pfn_glBindFramebuffer || !pfn_glDeleteFramebuffers || - !pfn_glGenFramebuffers || !pfn_glCheckFramebufferStatus || !pfn_glFramebufferTexture2D + ( !m_glIsFramebuffer || !m_glBindFramebuffer || !m_glDeleteFramebuffers || + !m_glGenFramebuffers || !m_glCheckFramebufferStatus || !m_glFramebufferTexture2D )) { - m_usefbo=false; + m_usefbo = false; if (_once) { - osd_printf_warning("OpenGL: FBO not supported, missing: "); - if (!pfn_glIsFramebuffer) - { - osd_printf_warning("pfn_glIsFramebuffer, "); - } - if (!pfn_glBindFramebuffer) - { - osd_printf_warning("pfn_glBindFramebuffer, "); - } - if (!pfn_glDeleteFramebuffers) - { - osd_printf_warning("pfn_glDeleteFramebuffers, "); - } - if (!pfn_glGenFramebuffers) - { - osd_printf_warning("pfn_glGenFramebuffers, "); - } - if (!pfn_glCheckFramebufferStatus) - { - osd_printf_warning("pfn_glCheckFramebufferStatus, "); - } - if (!pfn_glFramebufferTexture2D) - { - osd_printf_warning("pfn_glFramebufferTexture2D, "); - } + osd_printf_warning("OpenGL: FBO not supported, missing:"); + if (!m_glIsFramebuffer) + osd_printf_warning(" m_glIsFramebuffer"); + if (!m_glBindFramebuffer) + osd_printf_warning(" m_glBindFramebuffer"); + if (!m_glDeleteFramebuffers) + osd_printf_warning(" m_glDeleteFramebuffers"); + if (!m_glGenFramebuffers) + osd_printf_warning(" m_glGenFramebuffers"); + if (!m_glCheckFramebufferStatus) + osd_printf_warning(" m_glCheckFramebufferStatus"); + if (!m_glFramebufferTexture2D) + osd_printf_warning(" m_glFramebufferTexture2D"); osd_printf_warning("\n"); } } if (_once) { - if ( m_usevbo ) - { + if (m_usevbo) osd_printf_verbose("OpenGL: VBO supported\n"); - } else - { osd_printf_warning("OpenGL: VBO not supported\n"); - } - if ( m_usepbo ) - { + if (m_usepbo) osd_printf_verbose("OpenGL: PBO supported\n"); - } else - { osd_printf_warning("OpenGL: PBO not supported\n"); - } - if ( m_usefbo ) - { + if (m_usefbo) osd_printf_verbose("OpenGL: FBO supported\n"); - } else - { osd_printf_warning("OpenGL: FBO not supported\n"); - } } - if ( m_useglsl ) + if (m_useglsl) { #if defined(GL_ARB_multitexture) && !defined(OSD_MAC) - pfn_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB"); + m_gl_context->get_proc_address(m_glActiveTexture, "glActiveTextureARB"); #else - pfn_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture"); + m_gl_context->get_proc_address(m_glActiveTexture, "glActiveTexture"); #endif - if (!pfn_glActiveTexture) + if (!m_glActiveTexture) { if (_once) - { osd_printf_warning("OpenGL: GLSL disabled, glActiveTexture(ARB) not supported\n"); - } m_useglsl = 0; } } - if ( m_useglsl ) + if (m_useglsl) { - m_glsl = glsl_shader_init(m_gl_context); - m_useglsl = (m_glsl != nullptr ? 1 : 0); + m_shader_tool = glsl_shader_info::init( + *m_gl_context +#if defined(USE_DISPATCH_GL) + , gl_dispatch.get() +#endif + ); + m_useglsl = (m_shader_tool ? 1 : 0); if ( ! m_useglsl ) { @@ -927,9 +1051,9 @@ void renderer_ogl::loadGLExtensions() } } - if ( m_useglsl ) + if (m_useglsl) { - if (assert_window()->prescale() != 1 ) + if (window().prescale() != 1 ) { m_useglsl = 0; if (_once) @@ -939,15 +1063,14 @@ void renderer_ogl::loadGLExtensions() } } - if ( m_useglsl ) + if (m_useglsl) { - int i; video_config.filter = false; - glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN; + glsl_shader_feature = glsl_shader_info::FEAT_PLAIN; m_glsl_program_num = 0; m_glsl_program_mb2sc = 0; - for(i=0; i<video_config.glsl_shader_mamebm_num; i++) + for (int i=0; i<m_ogl_config.glsl_shader_mamebm_num; i++) { if ( !m_usefbo && m_glsl_program_num==1 ) { @@ -958,60 +1081,65 @@ void renderer_ogl::loadGLExtensions() break; } - if ( glsl_shader_add_mamebm(m_glsl, video_config.glsl_shader_mamebm[i], m_glsl_program_num) ) + if ( m_shader_tool->add_mamebm(m_ogl_config.glsl_shader_mamebm[i].c_str(), m_glsl_program_num) ) { osd_printf_error("OpenGL: GLSL loading mame bitmap shader %d failed (%s)\n", - i, video_config.glsl_shader_mamebm[i]); - } else { - glsl_shader_feature = GLSL_SHADER_FEAT_CUSTOM; + i, m_ogl_config.glsl_shader_mamebm[i]); + } + else + { + glsl_shader_feature = glsl_shader_info::FEAT_CUSTOM; if (_once) { osd_printf_verbose("OpenGL: GLSL using mame bitmap shader filter %d: '%s'\n", - m_glsl_program_num, video_config.glsl_shader_mamebm[i]); + m_glsl_program_num, m_ogl_config.glsl_shader_mamebm[i]); } m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it. m_glsl_program_num++; } } - if ( video_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 ) + if ( m_ogl_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 ) { osd_printf_verbose("OpenGL: GLSL cannot use screen bitmap shader without bitmap shader\n"); } - for(i=0; m_usefbo && m_glsl_program_num>0 && i<video_config.glsl_shader_scrn_num; i++) + for(int i=0; m_usefbo && m_glsl_program_num>0 && i<m_ogl_config.glsl_shader_scrn_num; i++) { - if ( glsl_shader_add_scrn(m_glsl, video_config.glsl_shader_scrn[i], - m_glsl_program_num-1-m_glsl_program_mb2sc) ) + if ( m_shader_tool->add_scrn(m_ogl_config.glsl_shader_scrn[i].c_str(), m_glsl_program_num-1-m_glsl_program_mb2sc) ) { osd_printf_error("OpenGL: GLSL loading screen bitmap shader %d failed (%s)\n", - i, video_config.glsl_shader_scrn[i]); - } else { + i, m_ogl_config.glsl_shader_scrn[i]); + } + else + { if (_once) { osd_printf_verbose("OpenGL: GLSL using screen bitmap shader filter %d: '%s'\n", - m_glsl_program_num, video_config.glsl_shader_scrn[i]); + m_glsl_program_num, m_ogl_config.glsl_shader_scrn[i]); } m_glsl_program_num++; } } if ( 0==m_glsl_program_num && - 0 <= video_config.glsl_filter && video_config.glsl_filter < GLSL_SHADER_FEAT_INT_NUMBER ) + 0 <= m_ogl_config.glsl_filter && m_ogl_config.glsl_filter < glsl_shader_info::FEAT_INT_NUMBER ) { m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it. m_glsl_program_num++; - glsl_shader_feature = video_config.glsl_filter; + glsl_shader_feature = m_ogl_config.glsl_filter; if (_once) { osd_printf_verbose("OpenGL: GLSL using shader filter '%s', idx: %d, num %d (vid filter: %d)\n", - glsl_shader_get_filter_name_mamebm(glsl_shader_feature), + m_shader_tool->get_filter_name_mamebm(glsl_shader_feature), glsl_shader_feature, m_glsl_program_num, video_config.filter); } } - } else { + } + else + { if (_once) { osd_printf_verbose("OpenGL: using vid filter: %d\n", video_config.filter); @@ -1031,16 +1159,7 @@ int renderer_ogl::draw(const int update) float vofs, hofs; int pendingPrimitive=GL_NO_PRIMITIVE, curPrimitive=GL_NO_PRIMITIVE; -#ifdef TOBEMIGRATED - if (video_config.novideo) - { - return 0; - } -#endif - - auto win = assert_window(); - - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) { @@ -1052,7 +1171,7 @@ int renderer_ogl::draw(const int update) clear_flags(FI_CHANGED); } - m_gl_context->MakeCurrent(); + m_gl_context->make_current(); if (m_init_context) { @@ -1192,16 +1311,15 @@ int renderer_ogl::draw(const int update) hofs = (cw - m_blit_dim.width()) / 2.0f; } } -#else #endif m_last_hofs = hofs; m_last_vofs = vofs; - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // now draw - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { int i; @@ -1236,7 +1354,10 @@ int renderer_ogl::draw(const int update) if(pendingPrimitive!=curPrimitive) { - glLineWidth(prim.width); + if (curPrimitive==GL_POINTS) + glPointSize(prim.width); + else + glLineWidth(prim.width); glBegin(curPrimitive); pendingPrimitive=curPrimitive; } @@ -1407,10 +1528,10 @@ int renderer_ogl::draw(const int update) pendingPrimitive=GL_NO_PRIMITIVE; } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); m_init_context = 0; - m_gl_context->SwapBuffer(); + m_gl_context->swap_buffer(); return 0; } @@ -1543,9 +1664,8 @@ void renderer_ogl::texture_compute_size_subroutine(ogl_texture_info *texture, ui while (texture->yprescale > 1 && height_create * texture->yprescale > m_texture_max_height) texture->yprescale--; - auto win = assert_window(); - if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != win->prescale() || texture->yprescale != win->prescale())) - osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", win->prescale(), win->prescale(), texture->xprescale, texture->yprescale); + if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != window().prescale() || texture->yprescale != window().prescale())) + osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", window().prescale(), window().prescale(), texture->xprescale, texture->yprescale); width *= texture->xprescale; height *= texture->yprescale; @@ -1640,10 +1760,9 @@ void renderer_ogl::texture_compute_size_type(const render_texinfo *texsource, og // texture_create //============================================================ -static int gl_checkFramebufferStatus() +int renderer_ogl::gl_checkFramebufferStatus() const { - GLenum status; - status=(GLenum)pfn_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + GLenum const status = (GLenum)m_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); switch(status) { case GL_FRAMEBUFFER_COMPLETE_EXT: return 0; @@ -1683,14 +1802,14 @@ static int gl_checkFramebufferStatus() return -1; } -static int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) +int renderer_ogl::texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) const { - pfn_glActiveTexture(text_unit); - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name); + m_glActiveTexture(text_unit); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name); glBindTexture(GL_TEXTURE_2D, text_name); { GLint _width, _height; - if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, + if ( m_shader_tool->texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &_width, &_height, 1) ) { osd_printf_error("cannot create fbo texture, req: %dx%d, avail: %dx%d - bail out\n", @@ -1708,7 +1827,7 @@ static int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t f glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - pfn_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + m_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, text_name, 0); if ( gl_checkFramebufferStatus() ) @@ -1745,51 +1864,49 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex for(i=0; i<m_glsl_program_num; i++) { if ( i<=m_glsl_program_mb2sc ) - { - m_glsl_program[i] = glsl_shader_get_program_mamebm(glsl_shader_feature, i); - } else { - m_glsl_program[i] = glsl_shader_get_program_scrn(i-1-m_glsl_program_mb2sc); - } - pfn_glUseProgramObjectARB(m_glsl_program[i]); + m_glsl_program[i] = m_shader_tool->get_program_mamebm(glsl_shader_feature, i); + else + m_glsl_program[i] = m_shader_tool->get_program_scrn(i-1-m_glsl_program_mb2sc); + m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[i]); if ( i<=m_glsl_program_mb2sc ) { // GL_TEXTURE0 GLSL Uniforms - uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture"); - pfn_glUniform1iARB(uniform_location, 0); + uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture"); + m_shader_tool->pfn_glUniform1iARB(uniform_location, 0); GL_CHECK_ERROR_NORMAL(); } { GLfloat color_texture_sz[2] = { (GLfloat)texture->rawwidth, (GLfloat)texture->rawheight }; - uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz"); - pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0])); + uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz"); + m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0])); GL_CHECK_ERROR_NORMAL(); } GLfloat color_texture_pow2_sz[2] = { (GLfloat)texture->rawwidth_create, (GLfloat)texture->rawheight_create }; - uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz"); - pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0])); + uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz"); + m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0])); GL_CHECK_ERROR_NORMAL(); GLfloat screen_texture_sz[2] = { (GLfloat) m_blit_dim.width(), (GLfloat) m_blit_dim.height() }; - uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz"); - pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0])); + uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz"); + m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0])); GL_CHECK_ERROR_NORMAL(); GLfloat screen_texture_pow2_sz[2] = { (GLfloat)surf_w_pow2, (GLfloat)surf_h_pow2 }; - uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz"); - pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0])); + uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz"); + m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0])); GL_CHECK_ERROR_NORMAL(); } - pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader + m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader if( m_glsl_program_num > 1 ) { // multipass mode // GL_TEXTURE2/GL_TEXTURE3 - pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); + m_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); glGenTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]); for (i=0; i<2; i++) @@ -1803,7 +1920,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex } } - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); osd_printf_verbose("GL texture: mpass mame-bmp 2x %dx%d (pow2 %dx%d)\n", texture->rawwidth, texture->rawheight, texture->rawwidth_create, texture->rawheight_create); @@ -1813,7 +1930,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex { // multipass mode // GL_TEXTURE2/GL_TEXTURE3 - pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); + m_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); glGenTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]); for (i=0; i<2; i++) @@ -1834,14 +1951,14 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex // GL_TEXTURE0 // get a name for this texture glGenTextures(1, (GLuint *)&texture->texture); - pfn_glActiveTexture(GL_TEXTURE0); + m_glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture->texture); glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth_create); uint32_t * dummy = nullptr; GLint _width, _height; - if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, + if ( m_shader_tool->texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, texture->rawwidth_create, texture->rawheight_create, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, @@ -1863,7 +1980,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter) { - assert( glsl_shader_feature == GLSL_SHADER_FEAT_PLAIN ); + assert( glsl_shader_feature == glsl_shader_info::FEAT_PLAIN ); // screen textures get the user's choice of filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -1898,7 +2015,11 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, ogl_texture_info *texture; // allocate a new texture - texture = new ogl_texture_info; + texture = new ogl_texture_info( +#if defined(USE_DISPATCH_GL) + gl_dispatch.get() +#endif + ); // fill in the core data texture->hash = texture_compute_hash(texsource, flags); @@ -1907,9 +2028,8 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, texture->texinfo.seqid = -1; // force set data if (PRIMFLAG_GET_SCREENTEX(flags)) { - auto win = assert_window(); - texture->xprescale = win->prescale(); - texture->yprescale = win->prescale(); + texture->xprescale = window().prescale(); + texture->yprescale = window().prescale(); } else { @@ -1963,7 +2083,7 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, if ( texture->type != TEXTURE_TYPE_SHADER && m_useglsl) { - pfn_glUseProgramObjectARB(0); // back to fixed function pipeline + m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline } if ( texture->type==TEXTURE_TYPE_SHADER ) @@ -2028,12 +2148,12 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, assert(m_usepbo); // create the PBO - pfn_glGenBuffers(1, (GLuint *)&texture->pbo); + m_glGenBuffers(1, (GLuint *)&texture->pbo); - pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); + m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); // set up the PBO dimension, .. - pfn_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, + m_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, texture->rawwidth * texture->rawheight * sizeof(uint32_t), nullptr, GL_STREAM_DRAW); } @@ -2063,10 +2183,10 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, if (m_usevbo) { // Generate And Bind The Texture Coordinate Buffer - pfn_glGenBuffers( 1, &(texture->texCoordBufferName) ); - pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); + m_glGenBuffers( 1, &(texture->texCoordBufferName) ); + m_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); // Load The Data - pfn_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW ); + m_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW ); glTexCoordPointer( 2, GL_FLOAT, 0, (char *) nullptr ); // we are using ARB VBO buffers } else @@ -2327,14 +2447,14 @@ static inline void copyline_yuy16_to_argb(uint32_t *dst, const uint16_t *src, in // texture_set_data //============================================================ -static void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) +void renderer_ogl::texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) const { if ( texture->type == TEXTURE_TYPE_DYNAMIC ) { assert(texture->pbo); assert(!texture->nocopy); - texture->data = (uint32_t *) pfn_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); + texture->data = (uint32_t *) m_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } // note that nocopy and borderpix are mutually exclusive, IOW @@ -2401,7 +2521,7 @@ static void texture_set_data(ogl_texture_info *texture, const render_texinfo *te if ( texture->type == TEXTURE_TYPE_SHADER ) { - pfn_glActiveTexture(GL_TEXTURE0); + m_glActiveTexture(GL_TEXTURE0); glBindTexture(texture->texTarget, texture->texture); if (texture->nocopy) @@ -2420,7 +2540,7 @@ static void texture_set_data(ogl_texture_info *texture, const render_texinfo *te glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth); // unmap the buffer from the CPU space so it can DMA - pfn_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); + m_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); // kick off the DMA glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight, @@ -2570,12 +2690,12 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx) if ( shaderIdx>0 ) { int uniform_location; - uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture"); - pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0); + uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture"); + m_shader_tool->pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0); GL_CHECK_ERROR_NORMAL(); } - pfn_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]); + m_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]); if ( shaderIdx<=m_glsl_program_mb2sc ) { glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[mpass_src_idx]); @@ -2584,22 +2704,22 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx) { glBindTexture(texture->texTarget, texture->mpass_texture_scrn[mpass_src_idx]); } - pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); + m_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); glBindTexture(texture->texTarget, 0); - pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); + m_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); if ( shaderIdx<m_glsl_program_num-1 ) { if ( shaderIdx>=m_glsl_program_mb2sc ) { glBindTexture(texture->texTarget, texture->mpass_texture_scrn[texture->mpass_dest_idx]); - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]); } else { glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[texture->mpass_dest_idx]); - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]); } if ( shaderIdx==0 ) @@ -2620,7 +2740,7 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx) else { glBindTexture(texture->texTarget, 0); - pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); if ( m_glsl_program_mb2sc == m_glsl_program_num-1 ) { @@ -2628,7 +2748,7 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx) GL_CHECK_ERROR_NORMAL(); } - pfn_glActiveTexture(GL_TEXTURE0); + m_glActiveTexture(GL_TEXTURE0); glBindTexture(texture->texTarget, 0); } } @@ -2649,8 +2769,8 @@ void renderer_ogl::texture_shader_update(ogl_texture_info *texture, render_conta vid_attributes[1] = settings.m_contrast; vid_attributes[2] = settings.m_brightness; vid_attributes[3] = 0.0f; - uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes"); - pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx])); + uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes"); + m_shader_tool->pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx])); if ( GL_CHECK_ERROR_QUIET() ) { osd_printf_verbose("GLSL: could not set 'vid_attributes' for shader prog idx %d\n", shaderIdx); } @@ -2671,12 +2791,12 @@ ogl_texture_info * renderer_ogl::texture_update(const render_primitive *prim, in { if ( texture->type == TEXTURE_TYPE_SHADER ) { - pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader + m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader } else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) { assert ( m_usepbo ) ; - pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); + m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); glEnable(texture->texTarget); } else @@ -2716,9 +2836,9 @@ ogl_texture_info * renderer_ogl::texture_update(const render_primitive *prim, in glEnableClientState(GL_TEXTURE_COORD_ARRAY); if(m_usevbo) { - pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); + m_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); // Load The Data - pfn_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord ); + m_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord ); glTexCoordPointer( 2, GL_FLOAT, 0, (char *) nullptr ); // we are using ARB VBO buffers } else @@ -2735,34 +2855,41 @@ void renderer_ogl::texture_disable(ogl_texture_info * texture) if ( texture->type == TEXTURE_TYPE_SHADER ) { assert ( m_useglsl ); - pfn_glUseProgramObjectARB(0); // back to fixed function pipeline - } else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) + m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline + } + else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) { - pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); + m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDisable(texture->texTarget); - } else { + } + else + { glDisable(texture->texTarget); } } void renderer_ogl::texture_all_disable() { - if ( m_useglsl ) + if (m_useglsl) { - pfn_glUseProgramObjectARB(0); // back to fixed function pipeline + m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline - pfn_glActiveTexture(GL_TEXTURE3); + m_glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, 0); - if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - pfn_glActiveTexture(GL_TEXTURE2); + if (m_usefbo) + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0); - if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - pfn_glActiveTexture(GL_TEXTURE1); + if (m_usefbo) + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); - if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - pfn_glActiveTexture(GL_TEXTURE0); + if (m_usefbo) + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + m_glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); - if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + if (m_usefbo) + m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); @@ -2775,10 +2902,140 @@ void renderer_ogl::texture_all_disable() glDisableClientState(GL_TEXTURE_COORD_ARRAY); if(m_usevbo) { - pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind .. + m_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind .. } if ( m_usepbo ) { - pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); + m_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); + } +} + + +class video_opengl : public osd_module, public render_module +{ +public: + video_opengl() + : osd_module(OSD_RENDERER_PROVIDER, "opengl") +#if defined(USE_DISPATCH_GL) + , m_dll_loaded(false) +#endif + { + } + ~video_opengl() { exit(); } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE | FLAG_SDL_NEEDS_OPENGL; } + +private: + ogl_video_config m_ogl_config; +#if defined(USE_DISPATCH_GL) + bool m_dll_loaded; +#endif +}; + +int video_opengl::init(osd_interface &osd, osd_options const &options) +{ + m_ogl_config.vbo = options.gl_vbo(); + m_ogl_config.pbo = options.gl_pbo(); + m_ogl_config.allowtexturerect = !options.gl_no_texture_rect(); + m_ogl_config.forcepow2texture = options.gl_force_pow2_texture(); + m_ogl_config.glsl = options.gl_glsl(); + if (m_ogl_config.glsl) + { + m_ogl_config.glsl_filter = options.glsl_filter(); + + m_ogl_config.glsl_shader_mamebm_num = 0; + for (int i = 0; i < GLSL_SHADER_MAX; i++) + { + char const *const stemp = options.shader_mame(i); + if (stemp && *stemp && strcmp(stemp, OSDOPTVAL_NONE)) + m_ogl_config.glsl_shader_mamebm[m_ogl_config.glsl_shader_mamebm_num++] = stemp; + } + + m_ogl_config.glsl_shader_scrn_num = 0; + for (int i = 0; i < GLSL_SHADER_MAX; i++) + { + char const *const stemp = options.shader_screen(i); + if (stemp && *stemp && strcmp(stemp, OSDOPTVAL_NONE)) + m_ogl_config.glsl_shader_scrn[m_ogl_config.glsl_shader_scrn_num++] = stemp; + } + } + else + { + m_ogl_config.glsl_filter = 0; + + m_ogl_config.glsl_shader_mamebm_num = 0; + for (std::string &s : m_ogl_config.glsl_shader_mamebm) + s.clear(); + + m_ogl_config.glsl_shader_scrn_num = 0; + for (std::string &s : m_ogl_config.glsl_shader_scrn) + s.clear(); + } + +#if defined(USE_DISPATCH_GL) +#if defined(OSD_SDL) + if (!m_dll_loaded) + { + // directfb and and x11 use this env var: SDL_VIDEO_GL_DRIVER + char const *libname = dynamic_cast<sdl_options const &>(options).gl_lib(); + if (libname && (!*libname || !std::strcmp(libname, OSDOPTVAL_AUTO))) + libname = nullptr; + + if (SDL_GL_LoadLibrary(libname) != 0) + { + osd_printf_error("Unable to load OpenGL shared library: %s\n", libname ? libname : "<default>"); + return -1; + } + + osd_printf_verbose("Loaded OpenGL shared library: %s\n", libname ? libname : "<default>"); } +#endif // defined(OSD_SDL) + m_dll_loaded = true; +#endif // defined(USE_DISPATCH_GL) + +#if defined(OSD_WINDOWS) + osd_printf_verbose("Using Windows OpenGL driver\n"); +#else // defined(OSD_WINDOWS) + osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n"); +#endif // defined(OSD_WINDOWS) + + return 0; +} + +void video_opengl::exit() +{ +#if defined(USE_DISPATCH_GL) +#if defined(OSD_SDL) + if (m_dll_loaded) + SDL_GL_UnloadLibrary(); +#endif // defined(OSD_SDL) + m_dll_loaded = false; +#endif // defined(USE_DISPATCH_GL) + + m_ogl_config = ogl_video_config(); +} + +std::unique_ptr<osd_renderer> video_opengl::create(osd_window &window) +{ + return std::make_unique<renderer_ogl>(window, m_ogl_config); } + +} // anonymous namespace + +} // namespace osd + + +#else // USE_OPENGL + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_opengl, OSD_RENDERER_PROVIDER, "opengl") } } + +#endif // USE_OPENGL + + +MODULE_DEFINITION(RENDERER_OPENGL, osd::video_opengl) diff --git a/src/osd/modules/render/drawogl.h b/src/osd/modules/render/drawogl.h deleted file mode 100644 index 61b9794353c..00000000000 --- a/src/osd/modules/render/drawogl.h +++ /dev/null @@ -1,244 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert, R. Belmont -//============================================================ -// -// drawogl.h - SDL software and OpenGL implementation -// -// SDLMAME by Olivier Galibert and R. Belmont -// -//============================================================ -#ifndef MAME_OSD_MODULES_RENDER_DRAWOGL_H -#define MAME_OSD_MODULES_RENDER_DRAWOGL_H - -#pragma once - -// OSD headers -#ifndef OSD_WINDOWS -#ifdef OSD_MAC -#include "osdmac.h" -#else -#include "osdsdl.h" -#endif -#include "window.h" -#else -#include "../windows/window.h" -typedef uint64_t HashT; -#endif - -#if defined(OSD_WINDOWS) -#include "winglcontext.h" -#elif defined (OSD_MAC) -#else -#include "sdlglcontext.h" -#endif - -#include "modules/opengl/gl_shader_mgr.h" - -#include "emucore.h" -#include "render.h" - -//============================================================ -// Textures -//============================================================ - -/* ogl_texture_info holds information about a texture */ -class ogl_texture_info -{ -public: - ogl_texture_info() - : hash(0), flags(0), rawwidth(0), rawheight(0), - rawwidth_create(0), rawheight_create(0), - type(0), format(0), borderpix(0), xprescale(0), yprescale(0), nocopy(0), - texture(0), texTarget(0), texpow2(0), mpass_dest_idx(0), pbo(0), data(nullptr), - data_own(0), texCoordBufferName(0) - { - for (int i=0; i<2; i++) - { - mpass_textureunit[i] = 0; - mpass_texture_mamebm[i] = 0; - mpass_fbo_mamebm[i] = 0; - mpass_texture_scrn[i] = 0; - mpass_fbo_scrn[i] = 0; - } - for (int i=0; i<8; i++) - texCoord[i] = 0.0f; - } - - HashT hash; // hash value for the texture (must be >= pointer size) - uint32_t flags; // rendering flags - render_texinfo texinfo; // copy of the texture info - int rawwidth, rawheight; // raw width/height of the texture - int rawwidth_create; // raw width/height, pow2 compatible, if needed - int rawheight_create; // (create and initial set the texture, not for copy!) - int type; // what type of texture are we? - int format; // texture format - int borderpix; // do we have a 1 pixel border? - int xprescale; // what is our X prescale factor? - int yprescale; // what is our Y prescale factor? - int nocopy; // must the texture date be copied? - - uint32_t texture; // OpenGL texture "name"/ID - - GLenum texTarget; // OpenGL texture target - int texpow2; // Is this texture pow2 - - uint32_t mpass_dest_idx; // Multipass dest idx [0..1] - uint32_t mpass_textureunit[2]; // texture unit names for GLSL - - uint32_t mpass_texture_mamebm[2];// Multipass OpenGL texture "name"/ID for the shader - uint32_t mpass_fbo_mamebm[2]; // framebuffer object for this texture, multipass - uint32_t mpass_texture_scrn[2]; // Multipass OpenGL texture "name"/ID for the shader - uint32_t mpass_fbo_scrn[2]; // framebuffer object for this texture, multipass - - uint32_t pbo; // pixel buffer object for this texture (DYNAMIC only!) - uint32_t *data; // pixels for the texture - int data_own; // do we own / allocated it ? - GLfloat texCoord[8]; - GLuint texCoordBufferName; - -}; - -/* renderer_ogl is the information about OpenGL for the current screen */ -class renderer_ogl : public osd_renderer -{ -public: - renderer_ogl(std::shared_ptr<osd_window> window) - : osd_renderer(window, FLAG_NEEDS_OPENGL) - , m_blittimer(0) - , m_width(0) - , m_height(0) - , m_blit_dim(0, 0) - , m_gl_context(nullptr) - , m_initialized(0) - , m_last_blendmode(0) - , m_texture_max_width(0) - , m_texture_max_height(0) - , m_texpoweroftwo(0) - , m_usevbo(0) - , m_usepbo(0) - , m_usefbo(0) - , m_useglsl(0) - , m_glsl(nullptr) - , m_glsl_program_num(0) - , m_glsl_program_mb2sc(0) - , m_usetexturerect(0) - , m_init_context(0) - , m_last_hofs(0.0f) - , m_last_vofs(0.0f) - , m_surf_w(0) - , m_surf_h(0) - { - for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++) - m_texhash[i] = nullptr; - for (int i=0; i < 2*GLSL_SHADER_MAX; i++) - m_glsl_program[i] = 0; - for (int i=0; i < 8; i++) - m_texVerticex[i] = 0.0f; - } - virtual ~renderer_ogl(); - - static void init(running_machine &machine); - static void exit(); - - virtual int create() override; - virtual int draw(const int update) override; - -#ifndef OSD_WINDOWS - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; -#endif - virtual render_primitive_list *get_primitives() override - { - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - - osd_dim nd = win->get_size(); - if (nd != m_blit_dim) - { - m_blit_dim = nd; - notify_changed(); - } - if ((m_blit_dim.width() == 0) || (m_blit_dim.height() == 0)) - return nullptr; - win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect()); - return &win->target()->get_primitives(); - } - -#ifdef OSD_WINDOWS - virtual void save() override { } - virtual void record() override { } - virtual void toggle_fsfx() override { } -#endif - -private: - static const uint32_t HASH_SIZE = ((1 << 10) + 1); - static const uint32_t OVERFLOW_SIZE = (1 << 10); - - void destroy_all_textures(); - - static void load_gl_lib(running_machine &machine); - void loadGLExtensions(); - void initialize_gl(); - void set_blendmode(int blendmode); - HashT texture_compute_hash(const render_texinfo *texture, uint32_t flags); - void texture_compute_type_subroutine(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); - void texture_compute_size_subroutine(ogl_texture_info *texture, uint32_t flags, - uint32_t width, uint32_t height, - int* p_width, int* p_height, int* p_width_create, int* p_height_create); - void texture_compute_size_type(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); - ogl_texture_info *texture_create(const render_texinfo *texsource, uint32_t flags); - int texture_shader_create(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags); - ogl_texture_info *texture_find(const render_primitive *prim); - void texture_coord_update(ogl_texture_info *texture, const render_primitive *prim, int shaderIdx); - void texture_mpass_flip(ogl_texture_info *texture, int shaderIdx); - void texture_shader_update(ogl_texture_info *texture, render_container *container, int shaderIdx); - ogl_texture_info * texture_update(const render_primitive *prim, int shaderIdx); - void texture_disable(ogl_texture_info * texture); - void texture_all_disable(); - - int32_t m_blittimer; - int m_width; - int m_height; - osd_dim m_blit_dim; - - osd_gl_context *m_gl_context; - - int m_initialized; // is everything well initialized, i.e. all GL stuff etc. - // 3D info (GL mode only) - ogl_texture_info * m_texhash[HASH_SIZE + OVERFLOW_SIZE]; - int m_last_blendmode; // previous blendmode - int32_t m_texture_max_width; // texture maximum width - int32_t m_texture_max_height; // texture maximum height - int m_texpoweroftwo; // must textures be power-of-2 sized? - int m_usevbo; // runtime check if VBO is available - int m_usepbo; // runtime check if PBO is available - int m_usefbo; // runtime check if FBO is available - int m_useglsl; // runtime check if GLSL is available - - glsl_shader_info *m_glsl; // glsl_shader_info - - GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0 - int m_glsl_program_num; // number of GLSL programs - int m_glsl_program_mb2sc; // GLSL program idx, which transforms - // the mame-bitmap. screen-bitmap (size/rotation/..) - // All progs <= glsl_program_mb2sc using the mame bitmap - // as input, otherwise the screen bitmap. - // All progs >= glsl_program_mb2sc using the screen bitmap - // as output, otherwise the mame bitmap. - int m_usetexturerect; // use ARB_texture_rectangle for non-power-of-2, general use - - int m_init_context; // initialize context before next draw - - float m_last_hofs; - float m_last_vofs; - - // Static vars from draogl_window_dra - int32_t m_surf_w; - int32_t m_surf_h; - GLfloat m_texVerticex[8]; - - static bool s_shown_video_info; - static bool s_dll_loaded; -}; - -#endif // MAME_OSD_MODULES_RENDER_DRAWOGL_H diff --git a/src/osd/modules/render/drawsdl.cpp b/src/osd/modules/render/drawsdl.cpp index 9e5de59c412..b1a9e93f42e 100644 --- a/src/osd/modules/render/drawsdl.cpp +++ b/src/osd/modules/render/drawsdl.cpp @@ -2,7 +2,7 @@ // copyright-holders:Couriersud, Olivier Galibert, R. Belmont //============================================================ // -// drawsdl.c - SDL software and OpenGL implementation +// drawsdl.cpp - SDL software and OpenGL implementation // // SDLMAME by Olivier Galibert and R. Belmont // @@ -10,28 +10,37 @@ // //============================================================ -// standard C headers -#include <cmath> -#include <cstdio> +#include "render_module.h" + +#include "modules/osdmodule.h" + +#if defined(OSD_SDL) + +// from specific OSD implementation +#include "sdlopts.h" +#include "window.h" + +// general OSD headers +#include "modules/monitor/monitor_module.h" // MAME headers #include "emucore.h" -#include "ui/uimain.h" +#include "render.h" #include "rendersw.hxx" -// standard SDL headers +//#include "ui/uimain.h" + #include <SDL2/SDL.h> -// OSD headers -#include "osdsdl.h" -#include "window.h" +// standard C headers +#include <cmath> +#include <cstdio> +#include <memory> -#include "drawsdl.h" -#include "modules/monitor/monitor_module.h" -//============================================================ -// DEBUGGING -//============================================================ +namespace osd { + +namespace { //============================================================ // CONSTANTS @@ -41,60 +50,90 @@ #define DRAW2_SCALEMODE_LINEAR "1" #define DRAW2_SCALEMODE_BEST "2" -//============================================================ -// PROTOTYPES -//============================================================ - -// YUV overlays - -static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ - const uint32_t *lookup, const int width, const int height); -static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ - const uint32_t *lookup, const int width, const int height); -static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ - const uint32_t *lookup, const int width, const int height); -static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ - const uint32_t *lookup, const int width, const int height); - -// Static declarations -static const sdl_scale_mode scale_modes[] = +struct sdl_scale_mode { - { "none", 0, 0, 1, 1, DRAW2_SCALEMODE_NEAREST, 0, nullptr }, - { "hwblit", 1, 0, 1, 1, DRAW2_SCALEMODE_LINEAR, 0, nullptr }, - { "hwbest", 1, 0, 1, 1, DRAW2_SCALEMODE_BEST, 0, nullptr }, - /* SDL1.2 uses interpolation as well */ - { "yv12", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12 }, - { "yv12x2", 1, 1, 2, 2, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12X2 }, - { "yuy2", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2 }, - { "yuy2x2", 1, 1, 2, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2X2 }, - { nullptr } + const char *name; + int is_scale; /* Scale mode? */ + int is_yuv; /* Yuv mode? */ + int mult_w; /* Width multiplier */ + int mult_h; /* Height multiplier */ + const char *sdl_scale_mode_hint; /* what to use as a hint ? */ + int pixel_format; /* Pixel/Overlay format */ + void (*yuv_blit)(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height); }; -int drawsdl_scale_mode(const char *s) -{ - const sdl_scale_mode *sm = scale_modes; - int index; - index = 0; - while (sm->name != nullptr) +// renderer_sdl1 is the information about SDL for the current screen +class renderer_sdl1 : public osd_renderer +{ +public: + + renderer_sdl1(osd_window &w, sdl_scale_mode const &scale_mode) + : osd_renderer(w) + , m_scale_mode(scale_mode) + , m_sdl_renderer(nullptr) + , m_texture_id(nullptr) + , m_yuv_lookup() + , m_yuv_bitmap() + //, m_hw_scale_width(0) + //, m_hw_scale_height(0) + , m_last_hofs(0) + , m_last_vofs(0) + , m_blit_dim(0, 0) + , m_last_dim(0, 0) { - if (strcmp(sm->name, s) == 0) - return index; - index++; - sm++; } - return -1; -} + virtual ~renderer_sdl1(); + + virtual int create() override; + virtual int draw(const int update) override; + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; + virtual render_primitive_list *get_primitives() override; + +private: + void show_info(struct SDL_RendererInfo *render_info); + + void destroy_all_textures(); + void yuv_init(); + void setup_texture(const osd_dim &size); + void yuv_lookup_set(unsigned int pen, unsigned char red, + unsigned char green, unsigned char blue); + + int32_t m_blittimer; + + sdl_scale_mode const &m_scale_mode; + SDL_Renderer *m_sdl_renderer; + SDL_Texture *m_texture_id; + + // YUV overlay + std::unique_ptr<uint32_t []> m_yuv_lookup; + std::unique_ptr<uint16_t []> m_yuv_bitmap; + + // if we leave scaling to SDL and the underlying driver, this + // is the render_target_width/height to use + + int m_last_hofs; + int m_last_vofs; + osd_dim m_blit_dim; + osd_dim m_last_dim; +}; + //============================================================ -// drawsdl_init +// PROTOTYPES //============================================================ -void renderer_sdl1::init(running_machine &machine) -{ - osd_printf_verbose("Using SDL multi-window soft driver (SDL 2.0+)\n"); -} +// YUV overlays + +static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitch, + const uint32_t *lookup, const int width, const int height); +static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, + const uint32_t *lookup, const int width, const int height); +static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, + const uint32_t *lookup, const int width, const int height); +static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, + const uint32_t *lookup, const int width, const int height); //============================================================ // setup_texture for window @@ -102,38 +141,35 @@ void renderer_sdl1::init(running_machine &machine) void renderer_sdl1::setup_texture(const osd_dim &size) { - const sdl_scale_mode *sdl_sm = &scale_modes[video_config.scale_mode]; SDL_DisplayMode mode; uint32_t fmt; - auto win = assert_window(); - // Determine preferred pixelformat and set up yuv if necessary - SDL_GetCurrentDisplayMode(win->monitor()->oshandle(), &mode); + SDL_GetCurrentDisplayMode(window().monitor()->oshandle(), &mode); m_yuv_bitmap.reset(); - fmt = (sdl_sm->pixel_format ? sdl_sm->pixel_format : mode.format); + fmt = (m_scale_mode.pixel_format ? m_scale_mode.pixel_format : mode.format); - if (sdl_sm->is_scale) + if (m_scale_mode.is_scale) { int m_hw_scale_width = 0; int m_hw_scale_height = 0; - win->target()->compute_minimum_size(m_hw_scale_width, m_hw_scale_height); - if (win->prescale()) + window().target()->compute_minimum_size(m_hw_scale_width, m_hw_scale_height); + if (window().prescale()) { - m_hw_scale_width *= win->prescale(); - m_hw_scale_height *= win->prescale(); + m_hw_scale_width *= window().prescale(); + m_hw_scale_height *= window().prescale(); /* This must be a multiple of 2 */ m_hw_scale_width = (m_hw_scale_width + 1) & ~1; } - if (sdl_sm->is_yuv) + if (m_scale_mode.is_yuv) m_yuv_bitmap = std::make_unique<uint16_t []>(m_hw_scale_width * m_hw_scale_height); - int w = m_hw_scale_width * sdl_sm->mult_w; - int h = m_hw_scale_height * sdl_sm->mult_h; + int w = m_hw_scale_width * m_scale_mode.mult_w; + int h = m_hw_scale_height * m_scale_mode.mult_h; m_texture_id = SDL_CreateTexture(m_sdl_renderer, fmt, SDL_TEXTUREACCESS_STREAMING, w, h); @@ -182,26 +218,23 @@ void renderer_sdl1::show_info(struct SDL_RendererInfo *render_info) int renderer_sdl1::create() { - const sdl_scale_mode *sm = &scale_modes[video_config.scale_mode]; - - auto win = assert_window(); // create renderer /* set hints ... */ - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, sm->sdl_scale_mode_hint); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, m_scale_mode.sdl_scale_mode_hint); if (video_config.waitvsync) - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); else - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_ACCELERATED); if (!m_sdl_renderer) { if (video_config.waitvsync) - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_SOFTWARE); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_SOFTWARE); else - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_SOFTWARE); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_SOFTWARE); } if (!m_sdl_renderer) @@ -216,18 +249,18 @@ int renderer_sdl1::create() // Check scale mode - if (sm->pixel_format) + if (m_scale_mode.pixel_format) { int i; int found = 0; for (i=0; i < render_info.num_texture_formats; i++) - if (sm->pixel_format == render_info.texture_formats[i]) + if (m_scale_mode.pixel_format == render_info.texture_formats[i]) found = 1; if (!found) { - fatalerror("window: Scale mode %s not supported!", sm->name); + fatalerror("window: Scale mode %s not supported!", m_scale_mode.name); } } @@ -288,7 +321,6 @@ void renderer_sdl1::destroy_all_textures() int renderer_sdl1::draw(int update) { - const sdl_scale_mode *sm = &scale_modes[video_config.scale_mode]; uint8_t *surfptr; int32_t pitch; Uint32 rmask, gmask, bmask; @@ -296,14 +328,7 @@ int renderer_sdl1::draw(int update) int32_t vofs, hofs, blitwidth, blitheight, ch, cw; int bpp; - if (video_config.novideo) - { - return 0; - } - - auto win = assert_window(); - - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (has_flags(FI_CHANGED) || (wdim != m_last_dim)) { destroy_all_textures(); @@ -370,15 +395,15 @@ int renderer_sdl1::draw(int update) m_last_hofs = hofs; m_last_vofs = vofs; - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); int mamewidth, mameheight; Uint32 fmt = 0; int access = 0; SDL_QueryTexture(m_texture_id, &fmt, &access, &mamewidth, &mameheight); - mamewidth /= sm->mult_w; - mameheight /= sm->mult_h; + mamewidth /= m_scale_mode.mult_w; + mameheight /= m_scale_mode.mult_h; //printf("w h %d %d %d %d\n", mamewidth, mameheight, blitwidth, blitheight); // rescale bounds @@ -388,7 +413,7 @@ int renderer_sdl1::draw(int update) // FIXME: this could be a lot easier if we get the primlist here! // Bounds would be set fit for purpose and done! - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { prim.bounds.x0 = floor(fw * prim.bounds.x0 + 0.5f); prim.bounds.x1 = floor(fw * prim.bounds.x1 + 0.5f); @@ -397,32 +422,32 @@ int renderer_sdl1::draw(int update) } // render to it - if (!sm->is_yuv) + if (!m_scale_mode.is_yuv) { switch (rmask) { case 0xff000000: - software_renderer<uint32_t, 0,0,0, 24,16,8>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4); + software_renderer<uint32_t, 0,0,0, 24,16,8>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4); break; case 0x0000ff00: - software_renderer<uint32_t, 0,0,0, 8,16,24>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4); + software_renderer<uint32_t, 0,0,0, 8,16,24>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4); break; case 0x00ff0000: - software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4); + software_renderer<uint32_t, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4); break; case 0x000000ff: - software_renderer<uint32_t, 0,0,0, 0,8,16>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 4); + software_renderer<uint32_t, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 4); break; case 0xf800: - software_renderer<uint16_t, 3,2,3, 11,5,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 2); + software_renderer<uint16_t, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 2); break; case 0x7c00: - software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*win->m_primlist, surfptr, mamewidth, mameheight, pitch / 2); + software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, surfptr, mamewidth, mameheight, pitch / 2); break; default: @@ -434,11 +459,11 @@ int renderer_sdl1::draw(int update) { assert (m_yuv_bitmap != nullptr); assert (surfptr != nullptr); - software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*win->m_primlist, m_yuv_bitmap.get(), mamewidth, mameheight, mamewidth); - sm->yuv_blit(m_yuv_bitmap.get(), surfptr, pitch, m_yuv_lookup.get(), mamewidth, mameheight); + software_renderer<uint16_t, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, m_yuv_bitmap.get(), mamewidth, mameheight, mamewidth); + m_scale_mode.yuv_blit(m_yuv_bitmap.get(), surfptr, pitch, m_yuv_lookup.get(), mamewidth, mameheight); } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); // unlock and flip SDL_UnlockTexture(m_texture_id); @@ -527,7 +552,7 @@ void renderer_sdl1::yuv_init() //uint32_t *lookup = sdl->m_yuv_lookup; -static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ +static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height) { int x, y; @@ -581,7 +606,7 @@ static void yuv_RGB_to_YV12(const uint16_t *bitmap, uint8_t *ptr, const int pitc } } -static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ +static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height) { /* this one is used when scale==2 */ @@ -616,7 +641,7 @@ static void yuv_RGB_to_YV12X2(const uint16_t *bitmap, uint8_t *ptr, const int pi } } -static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ +static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height) { /* this one is used when scale==2 */ @@ -642,7 +667,7 @@ static void yuv_RGB_to_YUY2(const uint16_t *bitmap, uint8_t *ptr, const int pitc } } -static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, \ +static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height) { /* this one is used when scale==2 */ @@ -666,16 +691,98 @@ static void yuv_RGB_to_YUY2X2(const uint16_t *bitmap, uint8_t *ptr, const int pi render_primitive_list *renderer_sdl1::get_primitives() { - auto win = try_getwindow(); - if (win == nullptr) - return nullptr; - - osd_dim nd = win->get_size(); + osd_dim nd = window().get_size(); if (nd != m_blit_dim) { m_blit_dim = nd; notify_changed(); } - win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); +} + + +class video_sdl1 : public osd_module, public render_module +{ +public: + video_sdl1() + : osd_module(OSD_RENDERER_PROVIDER, "soft") + , m_scale_mode(-1) + { + } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override { } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE; } + +private: + static int get_scale_mode(char const *modestr); + + int m_scale_mode; + + static sdl_scale_mode const s_scale_modes[]; +}; + +int video_sdl1::init(osd_interface &osd, osd_options const &options) +{ + osd_printf_verbose("Using SDL multi-window soft driver (SDL 2.0+)\n"); + + // yuv settings ... + char const *const modestr = dynamic_cast<sdl_options const &>(options).scale_mode(); + m_scale_mode = get_scale_mode(modestr); + if (m_scale_mode < 0) + { + osd_printf_warning("Invalid yuvmode value %s; reverting to none\n", modestr); + m_scale_mode = 0; + } + + return 0; +} + +std::unique_ptr<osd_renderer> video_sdl1::create(osd_window &window) +{ + return std::make_unique<renderer_sdl1>(window, s_scale_modes[m_scale_mode]); } + +int video_sdl1::get_scale_mode(char const *modestr) +{ + const sdl_scale_mode *sm = s_scale_modes; + int index = 0; + while (sm->name) + { + if (!strcmp(sm->name, modestr)) + return index; + index++; + sm++; + } + return -1; +} + +sdl_scale_mode const video_sdl1::s_scale_modes[] = { + { "none", 0, 0, 1, 1, DRAW2_SCALEMODE_NEAREST, 0, nullptr }, + { "hwblit", 1, 0, 1, 1, DRAW2_SCALEMODE_LINEAR, 0, nullptr }, + { "hwbest", 1, 0, 1, 1, DRAW2_SCALEMODE_BEST, 0, nullptr }, + /* SDL1.2 uses interpolation as well */ + { "yv12", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12 }, + { "yv12x2", 1, 1, 2, 2, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YV12, yuv_RGB_to_YV12X2 }, + { "yuy2", 1, 1, 1, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2 }, + { "yuy2x2", 1, 1, 2, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2X2 }, + { nullptr } }; + +} // anonymous namespace + +} // namespace osd + + +#else // defined(OSD_SDL) + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_sdl1, OSD_RENDERER_PROVIDER, "soft") } } + +#endif // defined(OSD_SDL) + + +MODULE_DEFINITION(RENDERER_SDL1, osd::video_sdl1) diff --git a/src/osd/modules/render/drawsdl.h b/src/osd/modules/render/drawsdl.h deleted file mode 100644 index bc8246a632d..00000000000 --- a/src/osd/modules/render/drawsdl.h +++ /dev/null @@ -1,88 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Couriersud, Olivier Galibert, R. Belmont -//============================================================ -// -// drawsdl.h - SDL software and OpenGL implementation -// -// SDLMAME by Olivier Galibert and R. Belmont -// -// yuvmodes by Couriersud -// -//============================================================ - -#ifndef MAME_OSD_MODULES_RENDER_DRAWSDL_H -#define MAME_OSD_MODULES_RENDER_DRAWSDL_H - -#pragma once - -#include <SDL2/SDL.h> - -/* renderer_sdl1 is the information about SDL for the current screen */ -class renderer_sdl1 : public osd_renderer -{ -public: - - renderer_sdl1(std::shared_ptr<osd_window> w, int extra_flags) - : osd_renderer(w, FLAG_NEEDS_OPENGL | extra_flags) - , m_sdl_renderer(nullptr) - , m_texture_id(nullptr) - , m_yuv_lookup() - , m_yuv_bitmap() - //, m_hw_scale_width(0) - //, m_hw_scale_height(0) - , m_last_hofs(0) - , m_last_vofs(0) - , m_blit_dim(0, 0) - , m_last_dim(0, 0) - { - } - virtual ~renderer_sdl1(); - - static void init(running_machine &machine); - static void exit() { } - - virtual int create() override; - virtual int draw(const int update) override; - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; - virtual render_primitive_list *get_primitives() override; - -private: - void show_info(struct SDL_RendererInfo *render_info); - - void destroy_all_textures(); - void yuv_init(); - void setup_texture(const osd_dim &size); - void yuv_lookup_set(unsigned int pen, unsigned char red, - unsigned char green, unsigned char blue); - - int32_t m_blittimer; - - SDL_Renderer *m_sdl_renderer; - SDL_Texture *m_texture_id; - - // YUV overlay - std::unique_ptr<uint32_t []> m_yuv_lookup; - std::unique_ptr<uint16_t []> m_yuv_bitmap; - - // if we leave scaling to SDL and the underlying driver, this - // is the render_target_width/height to use - - int m_last_hofs; - int m_last_vofs; - osd_dim m_blit_dim; - osd_dim m_last_dim; -}; - -struct sdl_scale_mode -{ - const char *name; - int is_scale; /* Scale mode? */ - int is_yuv; /* Yuv mode? */ - int mult_w; /* Width multiplier */ - int mult_h; /* Height multiplier */ - const char *sdl_scale_mode_hint; /* what to use as a hint ? */ - int pixel_format; /* Pixel/Overlay format */ - void (*yuv_blit)(const uint16_t *bitmap, uint8_t *ptr, const int pitch, const uint32_t *lookup, const int width, const int height); -}; - -#endif // MAME_OSD_MODULES_RENDER_DRAWSDL_H diff --git a/src/osd/modules/render/render_module.h b/src/osd/modules/render/render_module.h new file mode 100644 index 00000000000..b22f35fdb3c --- /dev/null +++ b/src/osd/modules/render/render_module.h @@ -0,0 +1,38 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +#ifndef MAME_OSD_MODULES_RENDER_RENDER_MODULE_H +#define MAME_OSD_MODULES_RENDER_RENDER_MODULE_H + +#pragma once + +#include "osdepend.h" +#include "modules/osdmodule.h" + +#include <memory> + + +#define OSD_RENDERER_PROVIDER "video" + + +class osd_renderer; +class osd_window; + + +class render_module +{ +public: + virtual ~render_module() = default; + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) = 0; + + bool is_interactive() const { return flags() & FLAG_INTERACTIVE; } + bool sdl_needs_opengl() const { return flags() & FLAG_SDL_NEEDS_OPENGL; } + +protected: + static inline constexpr unsigned FLAG_INTERACTIVE = 1; + static inline constexpr unsigned FLAG_SDL_NEEDS_OPENGL = 2; + + virtual unsigned flags() const = 0; +}; + +#endif // MAME_OSD_MODULES_RENDER_RENDER_MODULE_H diff --git a/src/osd/modules/render/sdlglcontext.h b/src/osd/modules/render/sdlglcontext.h index b8ff4d72aa2..d2055060bd6 100644 --- a/src/osd/modules/render/sdlglcontext.h +++ b/src/osd/modules/render/sdlglcontext.h @@ -8,61 +8,76 @@ // //============================================================ +#ifndef MAME_RENDER_SDLGLCONTEXT_H +#define MAME_RENDER_SDLGLCONTEXT_H + #pragma once -#ifndef __SDL_GL_CONTEXT__ -#define __SDL_GL_CONTEXT__ +#include "modules/opengl/osd_opengl.h" + +#include "strformat.h" #include <SDL2/SDL.h> -#include "modules/opengl/osd_opengl.h" + +#include <string> + class sdl_gl_context : public osd_gl_context { public: - sdl_gl_context(SDL_Window *window) : osd_gl_context(), m_context(0), m_window(window) + sdl_gl_context(SDL_Window *window) : m_context(0), m_window(window) { - m_error[0] = 0; m_context = SDL_GL_CreateContext(window); - if (!m_context) + if (!m_context) { - snprintf(m_error,255, "OpenGL not supported on this driver: %s", SDL_GetError()); + try { m_error = util::string_format("OpenGL not supported on this driver: %s", SDL_GetError()); } + catch (...) { m_error.clear(); } } } + virtual ~sdl_gl_context() { - SDL_GL_DeleteContext(m_context); + if (m_context) + SDL_GL_DeleteContext(m_context); } - virtual void MakeCurrent() override + + virtual explicit operator bool() const override + { + return bool(m_context); + } + + virtual void make_current() override { SDL_GL_MakeCurrent(m_window, m_context); } - virtual int SetSwapInterval(const int swap) override + virtual bool set_swap_interval(const int swap) override { - return SDL_GL_SetSwapInterval(swap); + return 0 == SDL_GL_SetSwapInterval(swap); } - virtual const char *LastErrorMsg() override + virtual const char *last_error_message() override { - if (m_error[0] == 0) - return nullptr; + if (!m_error.empty()) + return m_error.c_str(); else - return m_error; + return nullptr; } - virtual void *getProcAddress(const char *proc) override + + virtual void *get_proc_address(const char *proc) override { return SDL_GL_GetProcAddress(proc); } - virtual void SwapBuffer() override + virtual void swap_buffer() override { SDL_GL_SwapWindow(m_window); } private: SDL_GLContext m_context; - SDL_Window *m_window; - char m_error[256]; + SDL_Window *const m_window; + std::string m_error; }; -#endif // __SDL_GL_CONTEXT__ +#endif // MAME_RENDER_SDLGLCONTEXT_H diff --git a/src/osd/modules/render/winglcontext.h b/src/osd/modules/render/winglcontext.h index f0cb1b6af77..48d1462d2f6 100644 --- a/src/osd/modules/render/winglcontext.h +++ b/src/osd/modules/render/winglcontext.h @@ -7,168 +7,197 @@ // SDLMAME by Olivier Galibert and R. Belmont // //============================================================ +#ifndef MAME_RENDER_WINGLCONTEXT_H +#define MAME_RENDER_WINGLCONTEXT_H #pragma once -#ifndef __WIN_GL_CONTEXT__ -#define __WIN_GL_CONTEXT__ - #include "modules/opengl/osd_opengl.h" #include "modules/lib/osdlib.h" -// Typedefs for dynamically loaded functions -typedef PROC (WINAPI *wglGetProcAddress_fn)(LPCSTR); -typedef HGLRC (WINAPI *wglCreateContext_fn)(HDC); -typedef BOOL (WINAPI *wglDeleteContext_fn)(HGLRC); -typedef BOOL (WINAPI *wglMakeCurrent_fn)(HDC, HGLRC); +#include "strconv.h" + +#include <cstring> +#include <string> -typedef const char * (WINAPI *wglGetExtensionsStringEXT_fn)(void); -typedef BOOL (WINAPI *wglSwapIntervalEXT_fn)(int); -typedef int (WINAPI *wglGetSwapIntervalEXT_fn)(void); class win_gl_context : public osd_gl_context { public: - win_gl_context(HWND window) : osd_gl_context(), m_context(0), m_window(nullptr), m_hdc(0) - { - m_error[0] = 0; + using osd_gl_context::get_proc_address; + win_gl_context(HWND window) : m_context(nullptr), m_window(window), m_hdc(nullptr) + { + // open DLL and bind required functions opengl32_dll = osd::dynamic_module::open({ "opengl32.dll" }); - pfn_wglGetProcAddress = opengl32_dll->bind<wglGetProcAddress_fn>("wglGetProcAddress"); pfn_wglCreateContext = opengl32_dll->bind<wglCreateContext_fn>("wglCreateContext"); pfn_wglDeleteContext = opengl32_dll->bind<wglDeleteContext_fn>("wglDeleteContext"); pfn_wglMakeCurrent = opengl32_dll->bind<wglMakeCurrent_fn>("wglMakeCurrent"); + if (!pfn_wglGetProcAddress || !pfn_wglCreateContext || !pfn_wglDeleteContext || !pfn_wglMakeCurrent) + return; - if (pfn_wglGetProcAddress == nullptr || pfn_wglCreateContext == nullptr || - pfn_wglDeleteContext == nullptr || pfn_wglMakeCurrent == nullptr) + m_hdc = GetDC(window); + if (!m_hdc) { + get_last_error_string(); return; } - pfn_wglGetExtensionsStringEXT = (wglGetExtensionsStringEXT_fn)(*pfn_wglGetProcAddress)("wglGetExtensionsStringEXT"); + if (setupPixelFormat()) + { + m_context = (*pfn_wglCreateContext)(m_hdc); + if (!m_context) + get_last_error_string(); + } + if (!m_context) + return; + + (*pfn_wglMakeCurrent)(m_hdc, m_context); + get_proc_address(pfn_wglGetExtensionsStringEXT, "wglGetExtensionsStringEXT"); if (WGLExtensionSupported("WGL_EXT_swap_control")) { - pfn_wglSwapIntervalEXT = (BOOL (WINAPI *) (int)) getProcAddress("wglSwapIntervalEXT"); - pfn_wglGetSwapIntervalEXT = (int (WINAPI *) (void)) getProcAddress("wglGetSwapIntervalEXT"); + get_proc_address(pfn_wglSwapIntervalEXT, "wglSwapIntervalEXT"); + get_proc_address(pfn_wglGetSwapIntervalEXT, "wglGetSwapIntervalEXT"); } else { pfn_wglSwapIntervalEXT = nullptr; pfn_wglGetSwapIntervalEXT = nullptr; } - - m_hdc = GetDC(window); - if (!setupPixelFormat(m_hdc)) - { - m_context = (*pfn_wglCreateContext)(m_hdc); - if (!m_context) - { - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, GetLastError(), 0, m_error, 255, nullptr); - return; - } - (*pfn_wglMakeCurrent)(m_hdc, m_context); - } } virtual ~win_gl_context() { - (*pfn_wglDeleteContext)(m_context); - ReleaseDC(m_window, m_hdc); + if (m_context) + (*pfn_wglDeleteContext)(m_context); + + if (m_hdc) + ReleaseDC(m_window, m_hdc); + } + + virtual explicit operator bool() const override + { + return bool(m_context); } - virtual void MakeCurrent() override + virtual void make_current() override { (*pfn_wglMakeCurrent)(m_hdc, m_context); } - virtual const char *LastErrorMsg() override + virtual const char *last_error_message() override { - if (m_error[0] == 0) - return nullptr; + if (!m_error.empty()) + return m_error.c_str(); else - return m_error; + return nullptr; } - virtual void *getProcAddress(const char *proc) override + virtual void *get_proc_address(const char *proc) override { - return (void *)(*pfn_wglGetProcAddress)(proc); + return reinterpret_cast<void *>(uintptr_t((*pfn_wglGetProcAddress)(proc))); } - virtual int SetSwapInterval(const int swap) override + virtual bool set_swap_interval(const int swap) override { - if (pfn_wglSwapIntervalEXT != nullptr) - { - pfn_wglSwapIntervalEXT(swap ? 1 : 0); - } - return 0; + if (!pfn_wglSwapIntervalEXT) + return false; + + pfn_wglSwapIntervalEXT(swap ? 1 : 0); + return true; } - virtual void SwapBuffer() override + virtual void swap_buffer() override { SwapBuffers(m_hdc); //wglSwapLayerBuffers(GetDC(window().m_hwnd), WGL_SWAP_MAIN_PLANE); } private: + // Typedefs for dynamically loaded functions + typedef PROC (WINAPI *wglGetProcAddress_fn)(LPCSTR); + typedef HGLRC (WINAPI *wglCreateContext_fn)(HDC); + typedef BOOL (WINAPI *wglDeleteContext_fn)(HGLRC); + typedef BOOL (WINAPI *wglMakeCurrent_fn)(HDC, HGLRC); - int setupPixelFormat(HDC hDC) + typedef const char * (WINAPI *wglGetExtensionsStringEXT_fn)(); + typedef BOOL (WINAPI *wglSwapIntervalEXT_fn)(int); + typedef int (WINAPI *wglGetSwapIntervalEXT_fn)(); + + bool setupPixelFormat() { PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), /* size */ - 1, /* version */ - PFD_SUPPORT_OPENGL | - PFD_DRAW_TO_WINDOW | - PFD_DOUBLEBUFFER, /* support double-buffering */ - PFD_TYPE_RGBA, /* color type */ - 32, /* prefered color depth */ - 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ - 0, /* no alpha buffer */ - 0, /* alpha bits (ignored) */ - 0, /* no accumulation buffer */ - 0, 0, 0, 0, /* accum bits (ignored) */ - 16, /* depth buffer */ - 0, /* no stencil buffer */ - 0, /* no auxiliary buffers */ - PFD_MAIN_PLANE, /* main layer */ - 0, /* reserved */ - 0, 0, 0, /* no layer, visible, damage masks */ - }; - - int pixelFormat = ChoosePixelFormat(hDC, &pfd); - + sizeof(PIXELFORMATDESCRIPTOR), // size + 1, // version + PFD_SUPPORT_OPENGL | + PFD_DRAW_TO_WINDOW | + PFD_DOUBLEBUFFER, // support double-buffering + PFD_TYPE_RGBA, // color type + 32, // prefered color depth + 0, 0, 0, 0, 0, 0, // color bits (ignored) + 0, // no alpha buffer + 0, // alpha bits (ignored) + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits (ignored) + 16, // depth buffer + 0, // no stencil buffer + 0, // no auxiliary buffers + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0, // no layer, visible, damage masks + }; + + const int pixelFormat = ChoosePixelFormat(m_hdc, &pfd); if (pixelFormat == 0) { - strcpy(m_error, "ChoosePixelFormat failed."); - return 1; + get_last_error_string(); + return false; } - if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) + if (SetPixelFormat(m_hdc, pixelFormat, &pfd) != TRUE) { - strcpy(m_error, "SetPixelFormat failed."); - return 1; + get_last_error_string(); + return false; } - return 0; + + return true; } bool WGLExtensionSupported(const char *extension_name) { - if (pfn_wglGetExtensionsStringEXT == nullptr) + if (!pfn_wglGetExtensionsStringEXT) return false; - // printf("%s\n", pfn_wglGetExtensionsStringEXT()); + return strstr(pfn_wglGetExtensionsStringEXT(), extension_name) != nullptr; + } - if (strstr(pfn_wglGetExtensionsStringEXT(), extension_name) != nullptr) - return true; - else - return false; + void get_last_error_string() + { + LPTSTR buffer = nullptr; + const auto result = FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, + nullptr, + GetLastError(), + 0, + LPTSTR(&buffer), + 0, + nullptr); + if (!result || !buffer) + { + m_error.clear(); + return; + } + try { m_error = osd::text::from_tstring(buffer); } + catch (...) { m_error.clear(); } + LocalFree(buffer); } HGLRC m_context; - HWND m_window; + HWND const m_window; HDC m_hdc; - char m_error[256]; + std::string m_error; osd::dynamic_module::ptr opengl32_dll; wglGetProcAddress_fn pfn_wglGetProcAddress; @@ -181,4 +210,4 @@ private: wglGetSwapIntervalEXT_fn pfn_wglGetSwapIntervalEXT; }; -#endif // __WIN_GL_CONTEXT__ +#endif // MAME_RENDER_WINGLCONTEXT_H |