From 47dba250528529100d1bc3c9b7811fb5d9aada6d Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Wed, 18 Dec 2019 06:38:34 +0100 Subject: [PATCH] source-shader: Update to new gfx::shader::shader --- source/sources/source-shader.cpp | 278 ++++++------------------------- source/sources/source-shader.hpp | 76 +++++---- 2 files changed, 88 insertions(+), 266 deletions(-) diff --git a/source/sources/source-shader.cpp b/source/sources/source-shader.cpp index ab7a9aa0..dc7039e7 100644 --- a/source/sources/source-shader.cpp +++ b/source/sources/source-shader.cpp @@ -23,279 +23,97 @@ #include "utility.hpp" #define ST "Source.Shader" -#define ST_WIDTH ST ".Width" -#define ST_HEIGHT ST ".Height" - -static std::shared_ptr factory_instance = nullptr; - -void source::shader::shader_factory::initialize() -{ - factory_instance = std::make_shared(); -} - -void source::shader::shader_factory::finalize() -{ - factory_instance.reset(); -} - -std::shared_ptr source::shader::shader_factory::get() -{ - return factory_instance; -} - -static void get_defaults(obs_data_t* data) -{ - obs_data_set_default_int(data, ST_WIDTH, 1920); - obs_data_set_default_int(data, ST_HEIGHT, 1080); - obs_data_set_default_string(data, S_SHADER_FILE, obs_module_file("shaders/source/example.effect")); - obs_data_set_default_string(data, S_SHADER_TECHNIQUE, "Draw"); -} - -source::shader::shader_factory::shader_factory() -{ - memset(&_source_info, 0, sizeof(obs_source_info)); - _source_info.id = "obs-stream-effects-source-shader"; - _source_info.type = OBS_SOURCE_TYPE_INPUT; - _source_info.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW; - _source_info.get_name = [](void*) { return D_TRANSLATE(ST); }; - _source_info.get_defaults = get_defaults; - - _source_info.create = [](obs_data_t* data, obs_source_t* self) { - try { - return static_cast(new source::shader::shader_instance(data, self)); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to create source, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to create source."); - } - return static_cast(nullptr); - }; - _source_info.destroy = [](void* ptr) { - try { - delete reinterpret_cast(ptr); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to delete source, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to delete source."); - } - }; - _source_info.get_properties = [](void* ptr) { - obs_properties_t* pr = obs_properties_create(); - try { - if (ptr) - reinterpret_cast(ptr)->properties(pr); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to retrieve options, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to retrieve options."); - } - return pr; - }; - _source_info.get_width = [](void* ptr) { - try { - if (ptr) - return reinterpret_cast(ptr)->width(); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to retrieve width, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to retrieve width."); - } - return uint32_t(0); - }; - _source_info.get_height = [](void* ptr) { - try { - if (ptr) - return reinterpret_cast(ptr)->height(); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to retrieve height, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to retrieve height."); - } - return uint32_t(0); - }; - _source_info.load = [](void* ptr, obs_data_t* data) { - try { - if (ptr) - reinterpret_cast(ptr)->load(data); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to load, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to load."); - } - }; - _source_info.update = [](void* ptr, obs_data_t* data) { - try { - if (ptr) - reinterpret_cast(ptr)->update(data); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to update, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to update."); - } - }; - _source_info.activate = [](void* ptr) { - try { - if (ptr) - reinterpret_cast(ptr)->activate(); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to activate, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to activate."); - } - }; - _source_info.deactivate = [](void* ptr) { - try { - if (ptr) - reinterpret_cast(ptr)->deactivate(); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to deactivate, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to deactivate."); - } - }; - _source_info.video_tick = [](void* ptr, float_t time) { - try { - if (ptr) - reinterpret_cast(ptr)->video_tick(time); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to tick, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to tick."); - } - }; - _source_info.video_render = [](void* ptr, gs_effect_t* effect) { - try { - if (ptr) - reinterpret_cast(ptr)->video_render(effect); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to render, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to render."); - } - }; - _source_info.enum_active_sources = [](void* ptr, obs_source_enum_proc_t enum_callback, void* param) { - try { - if (ptr) - reinterpret_cast(ptr)->enum_active_sources(enum_callback, param); - } catch (const std::exception& ex) { - P_LOG_ERROR(" Failed to enumerate sources, error: %s", ex.what()); - } catch (...) { - P_LOG_ERROR(" Failed to enumerate sources."); - } - }; - - obs_register_source(&_source_info); -} - -source::shader::shader_factory::~shader_factory() {} source::shader::shader_instance::shader_instance(obs_data_t* data, obs_source_t* self) - : _self(self), _active(true), _width(0), _height(0) + : obs::source_instance(data, self), _is_main(false) { - _fx = std::make_shared(self); - _fx->set_valid_property_cb(std::bind(&source::shader::shader_instance::valid_param, this, std::placeholders::_1)); - _fx->set_override_cb(std::bind(&source::shader::shader_instance::override_param, this, std::placeholders::_1)); - - _rt = std::make_shared(GS_RGBA, GS_ZS_NONE); + _fx = std::make_shared(self, gfx::shader::shader_mode::Source); update(data); } source::shader::shader_instance::~shader_instance() {} -uint32_t source::shader::shader_instance::width() +uint32_t source::shader::shader_instance::get_width() { - return _width; + return _fx->width(); } -uint32_t source::shader::shader_instance::height() +uint32_t source::shader::shader_instance::get_height() { - return _height; + return _fx->height(); } void source::shader::shader_instance::properties(obs_properties_t* props) { - obs_properties_add_int(props, ST_WIDTH, D_TRANSLATE(ST_WIDTH), 1, 32768, 1); - obs_properties_add_int(props, ST_HEIGHT, D_TRANSLATE(ST_HEIGHT), 1, 32768, 1); - _fx->properties(props); } void source::shader::shader_instance::load(obs_data_t* data) { - update(data); + _fx->update(data); } void source::shader::shader_instance::update(obs_data_t* data) { - _width = static_cast(obs_data_get_int(data, ST_WIDTH)); - _height = static_cast(obs_data_get_int(data, ST_HEIGHT)); - _fx->update(data); } -void source::shader::shader_instance::activate() -{ - _active = true; -} - -void source::shader::shader_instance::deactivate() -{ - _active = false; -} - -bool source::shader::shader_instance::valid_param(std::shared_ptr param) -{ - return true; -} - -void source::shader::shader_instance::override_param(std::shared_ptr effect) {} - -void source::shader::shader_instance::enum_active_sources(obs_source_enum_proc_t r, void* p) -{ - _fx->enum_active_sources(r, p); -} - void source::shader::shader_instance::video_tick(float_t sec_since_last) { if (_fx->tick(sec_since_last)) { obs_data_t* data = obs_source_get_settings(_self); - update(data); + _fx->update(data); obs_data_release(data); } - _rt_updated = false; + _is_main = true; } void source::shader::shader_instance::video_render(gs_effect_t* effect) { - // Grab initial values. - gs_effect_t* effect_default = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT); - - // Skip filter if anything is wrong. - if (!_active || !_width || !_height || !effect_default) { - obs_source_skip_video_filter(_self); + if (!_fx) { return; } - if (!_rt_updated) { - try { - auto op = _rt->render(_width, _height); - _fx->render(); - } catch (...) { - } - _rt_tex = _rt->get_texture(); - _rt_updated = true; + if (_is_main) { // Dirty hack to only take the value from the first render, which usually is the main view. + gs_rect vect; + gs_get_viewport(&vect); + _fx->set_size(static_cast(vect.cx), static_cast(vect.cy)); + _is_main = false; } - if (!_rt_tex) - return; - - gs_effect_t* ef = effect ? effect : effect_default; - if (gs_eparam_t* prm = gs_effect_get_param_by_name(ef, "image")) - gs_effect_set_texture(prm, _rt_tex->get_object()); - - while (gs_effect_loop(ef, "Draw")) { - gs_draw_sprite(nullptr, 0, _width, _height); - } + _fx->render(); +} + +std::shared_ptr source::shader::shader_factory::factory_instance = nullptr; + +source::shader::shader_factory::shader_factory() +{ + _info.id = "obs-stream-effects-source-shader"; + _info.type = OBS_SOURCE_TYPE_INPUT; + _info.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW; + + finish_setup(); +} + +source::shader::shader_factory::~shader_factory() {} + +const char* source::shader::shader_factory::get_name() +{ + return D_TRANSLATE(ST); +} + +void source::shader::shader_factory::get_defaults2(obs_data_t* data) {} + +obs_properties_t* source::shader::shader_factory::get_properties2(source::shader::shader_instance* data) +{ + auto pr = obs_properties_create(); + obs_properties_set_param(pr, data, nullptr); + + if (data) { + reinterpret_cast(data)->properties(pr); + } + + return pr; } diff --git a/source/sources/source-shader.hpp b/source/sources/source-shader.hpp index 7c9316f8..40b9ea20 100644 --- a/source/sources/source-shader.hpp +++ b/source/sources/source-shader.hpp @@ -19,8 +19,9 @@ #pragma once -#include "gfx/gfx-effect-source.hpp" +#include "gfx/shader/gfx-shader.hpp" #include "obs/gs/gs-rendertarget.hpp" +#include "obs/obs-source-factory.hpp" #include "plugin.hpp" extern "C" { @@ -29,53 +30,56 @@ extern "C" { namespace source { namespace shader { - class shader_factory { - obs_source_info _source_info; + class shader_instance : public obs::source_instance { + std::shared_ptr _fx; - public: // Singleton - static void initialize(); - static void finalize(); - static std::shared_ptr get(); - - public: - shader_factory(); - ~shader_factory(); - }; - - class shader_instance { - obs_source_t* _self; - bool _active; - - uint32_t _width, _height; - - std::shared_ptr _rt; - bool _rt_updated; - std::shared_ptr _rt_tex; - - std::shared_ptr _fx; + bool _is_main; public: shader_instance(obs_data_t* data, obs_source_t* self); - ~shader_instance(); + virtual ~shader_instance(); - uint32_t width(); - uint32_t height(); + virtual uint32_t get_width() override; + virtual uint32_t get_height() override; void properties(obs_properties_t* props); - void load(obs_data_t* data); - void update(obs_data_t* data); + virtual void load(obs_data_t* data) override; + virtual void update(obs_data_t* data) override; - void activate(); - void deactivate(); + virtual void video_tick(float_t sec_since_last) override; + virtual void video_render(gs_effect_t* effect) override; + }; - bool valid_param(std::shared_ptr param); - void override_param(std::shared_ptr effect); + class shader_factory + : public obs::source_factory { + static std::shared_ptr factory_instance; - void enum_active_sources(obs_source_enum_proc_t, void*); + public: // Singleton + static void initialize() + { + factory_instance = std::make_shared(); + } - void video_tick(float_t sec_since_last); - void video_render(gs_effect_t* effect); + static void finalize() + { + factory_instance.reset(); + } + + static std::shared_ptr get() + { + return factory_instance; + } + + public: + shader_factory(); + virtual ~shader_factory(); + + virtual const char* get_name() override; + + virtual void get_defaults2(obs_data_t* data) override; + + virtual obs_properties_t* get_properties2(source::shader::shader_instance* data) override; }; } // namespace shader } // namespace source