filter-sdf-effects: Refactor onto obs::source_factory

Also replaces the global effect objects with per-source ones
This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2019-12-03 17:47:39 +01:00
parent 0b14b65ba8
commit 48e17ad562
2 changed files with 143 additions and 318 deletions

View file

@ -65,106 +65,49 @@
#define ST_SDF_SCALE "Filter.SDFEffects.SDF.Scale"
#define ST_SDF_THRESHOLD "Filter.SDFEffects.SDF.Threshold"
static std::shared_ptr<filter::sdf_effects::sdf_effects_factory> factory_instance = nullptr;
void filter::sdf_effects::sdf_effects_factory::initialize()
{
factory_instance = std::make_shared<filter::sdf_effects::sdf_effects_factory>();
}
void filter::sdf_effects::sdf_effects_factory::finalize()
{
factory_instance.reset();
}
std::shared_ptr<filter::sdf_effects::sdf_effects_factory> filter::sdf_effects::sdf_effects_factory::get()
{
return factory_instance;
}
std::shared_ptr<filter::sdf_effects::sdf_effects_factory> filter::sdf_effects::sdf_effects_factory::factory_instance =
nullptr;
filter::sdf_effects::sdf_effects_factory::sdf_effects_factory()
{
memset(&_source_info, 0, sizeof(obs_source_info));
_source_info.id = "obs-stream-effects-filter-sdf-effects";
_source_info.type = OBS_SOURCE_TYPE_FILTER;
_source_info.output_flags = OBS_SOURCE_VIDEO;
_source_info.get_name = get_name;
_source_info.get_defaults = get_defaults;
_source_info.get_properties = get_properties;
_info.id = "obs-stream-effects-filter-sdf-effects";
_info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW;
_source_info.create = create;
_source_info.destroy = destroy;
_source_info.update = update;
_source_info.activate = activate;
_source_info.deactivate = deactivate;
_source_info.video_tick = video_tick;
_source_info.video_render = video_render;
// Strip all unnecessary callbacks.
_info.get_width = nullptr;
_info.get_height = nullptr;
_info.activate = nullptr;
_info.deactivate = nullptr;
_info.show = nullptr;
_info.hide = nullptr;
_info.mouse_click = nullptr;
_info.mouse_move = nullptr;
_info.mouse_wheel = nullptr;
_info.key_click = nullptr;
_info.focus = nullptr;
_info.filter_remove = nullptr;
_info.enum_active_sources = nullptr;
_info.enum_all_sources = nullptr;
_info.transition_start = nullptr;
_info.transition_stop = nullptr;
_info.filter_audio = nullptr;
_info.filter_video = nullptr;
_info.audio_mix = nullptr;
_info.audio_render = nullptr;
obs_register_source(&_source_info);
obs_register_source(&_info);
}
filter::sdf_effects::sdf_effects_factory::~sdf_effects_factory() {}
void filter::sdf_effects::sdf_effects_factory::on_list_fill()
const char* filter::sdf_effects::sdf_effects_factory::get_name()
{
auto gctx = gs::context();
std::pair<const char*, std::shared_ptr<gs::effect>&> load_arr[] = {
{"effects/sdf/sdf-producer.effect", this->_sdf_producer_effect},
{"effects/sdf/sdf-consumer.effect", this->_sdf_consumer_effect},
};
for (auto& kv : load_arr) {
char* path = obs_module_file(kv.first);
if (!path) {
P_LOG_ERROR(LOG_PREFIX "Unable to load _effect '%s' as file is missing or locked.", kv.first);
continue;
}
try {
kv.second = gs::effect::create(path);
} catch (const std::exception& ex) {
P_LOG_ERROR(LOG_PREFIX "Failed to load _effect '%s' (located at '%s') with error(s): %s", kv.first, path,
ex.what());
}
bfree(path);
}
return D_TRANSLATE(ST);
}
void filter::sdf_effects::sdf_effects_factory::on_list_empty()
void filter::sdf_effects::sdf_effects_factory::get_defaults2(obs_data_t* data)
{
this->_sdf_producer_effect.reset();
this->_sdf_consumer_effect.reset();
}
void* filter::sdf_effects::sdf_effects_factory::create(obs_data_t* data, obs_source_t* parent) noexcept try {
if (get()->_sources.empty()) {
get()->on_list_fill();
}
filter::sdf_effects::sdf_effects_instance* ptr = new filter::sdf_effects::sdf_effects_instance(data, parent);
get()->_sources.push_back(ptr);
return ptr;
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
return nullptr;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return nullptr;
}
void filter::sdf_effects::sdf_effects_factory::destroy(void* inptr) noexcept try {
filter::sdf_effects::sdf_effects_instance* ptr =
reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr);
get()->_sources.remove(ptr);
if (get()->_sources.empty()) {
get()->on_list_empty();
}
delete ptr;
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
void filter::sdf_effects::sdf_effects_factory::get_defaults(obs_data_t* data) noexcept try {
obs_data_set_default_bool(data, ST_SHADOW_OUTER, false);
obs_data_set_default_int(data, ST_SHADOW_OUTER_COLOR, 0x00000000);
obs_data_set_default_double(data, ST_SHADOW_OUTER_ALPHA, 100.0);
@ -203,102 +146,10 @@ void filter::sdf_effects::sdf_effects_factory::get_defaults(obs_data_t* data) no
obs_data_set_default_bool(data, S_ADVANCED, false);
obs_data_set_default_double(data, ST_SDF_SCALE, 100.0);
obs_data_set_default_double(data, ST_SDF_THRESHOLD, 50.0);
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
obs_properties_t* filter::sdf_effects::sdf_effects_factory::get_properties(void* inptr) noexcept try {
return reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr)->get_properties();
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
return nullptr;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return nullptr;
}
void filter::sdf_effects::sdf_effects_factory::update(void* inptr, obs_data_t* settings) noexcept try {
reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr)->update(settings);
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
const char* filter::sdf_effects::sdf_effects_factory::get_name(void*) noexcept try {
return D_TRANSLATE(ST);
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
uint32_t filter::sdf_effects::sdf_effects_factory::get_width(void* inptr) noexcept try {
return reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr)->get_width();
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
return 0;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return 0;
}
uint32_t filter::sdf_effects::sdf_effects_factory::get_height(void* inptr) noexcept try {
return reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr)->get_height();
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
return 0;
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
return 0;
}
void filter::sdf_effects::sdf_effects_factory::activate(void* inptr) noexcept try {
reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr)->activate();
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
void filter::sdf_effects::sdf_effects_factory::deactivate(void* inptr) noexcept try {
reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr)->deactivate();
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
void filter::sdf_effects::sdf_effects_factory::video_tick(void* inptr, float delta) noexcept try {
reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr)->video_tick(delta);
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
void filter::sdf_effects::sdf_effects_factory::video_render(void* inptr, gs_effect_t* effect) noexcept try {
reinterpret_cast<filter::sdf_effects::sdf_effects_instance*>(inptr)->video_render(effect);
} catch (const std::exception& ex) {
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
} catch (...) {
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
std::shared_ptr<gs::effect> filter::sdf_effects::sdf_effects_factory::get_sdf_producer_effect()
{
return this->_sdf_producer_effect;
}
std::shared_ptr<gs::effect> filter::sdf_effects::sdf_effects_factory::get_sdf_consumer_effect()
{
return this->_sdf_consumer_effect;
}
bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_inside(void*, obs_properties_t* props, obs_property*,
obs_data_t* settings) noexcept try {
bool cb_modified_shadow_inside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
try {
bool v = obs_data_get_bool(settings, ST_SHADOW_INNER);
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_INNER_RANGE_MINIMUM), v);
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_INNER_RANGE_MAXIMUM), v);
@ -313,9 +164,8 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_inside(void*,
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_outside(void*, obs_properties_t* props,
obs_property*,
obs_data_t* settings) noexcept try {
bool cb_modified_shadow_outside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
try {
bool v = obs_data_get_bool(settings, ST_SHADOW_OUTER);
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_RANGE_MINIMUM), v);
obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_RANGE_MAXIMUM), v);
@ -330,8 +180,8 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_outside(void*
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
bool filter::sdf_effects::sdf_effects_instance::cb_modified_glow_inside(void*, obs_properties_t* props, obs_property*,
obs_data_t* settings) noexcept try {
bool cb_modified_glow_inside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
try {
bool v = obs_data_get_bool(settings, ST_GLOW_INNER);
obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_COLOR), v);
obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_ALPHA), v);
@ -344,8 +194,8 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_glow_inside(void*, o
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
bool filter::sdf_effects::sdf_effects_instance::cb_modified_glow_outside(void*, obs_properties_t* props, obs_property*,
obs_data_t* settings) noexcept try {
bool cb_modified_glow_outside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
try {
bool v = obs_data_get_bool(settings, ST_GLOW_OUTER);
obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_COLOR), v);
obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_ALPHA), v);
@ -358,8 +208,8 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_glow_outside(void*,
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
bool filter::sdf_effects::sdf_effects_instance::cb_modified_outline(void*, obs_properties_t* props, obs_property*,
obs_data_t* settings) noexcept try {
bool cb_modified_outline(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
try {
bool v = obs_data_get_bool(settings, ST_OUTLINE);
obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_COLOR), v);
obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_ALPHA), v);
@ -373,8 +223,8 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_outline(void*, obs_p
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
bool filter::sdf_effects::sdf_effects_instance::cb_modified_advanced(void*, obs_properties_t* props, obs_property*,
obs_data_t* settings) noexcept try {
bool cb_modified_advanced(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) noexcept
try {
bool show_advanced = obs_data_get_bool(settings, S_ADVANCED);
obs_property_set_visible(obs_properties_get(props, ST_SDF_SCALE), show_advanced);
obs_property_set_visible(obs_properties_get(props, ST_SDF_THRESHOLD), show_advanced);
@ -385,38 +235,8 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_advanced(void*, obs_
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
}
filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* settings, obs_source_t* self)
: _self(self), _source_rendered(false), _sdf_scale(1.0), _sdf_threshold(), _output_rendered(false),
_inner_shadow(false), _inner_shadow_color(), _inner_shadow_range_min(), _inner_shadow_range_max(),
_inner_shadow_offset_x(), _inner_shadow_offset_y(), _outer_shadow(false), _outer_shadow_color(),
_outer_shadow_range_min(), _outer_shadow_range_max(), _outer_shadow_offset_x(), _outer_shadow_offset_y(),
_inner_glow(false), _inner_glow_color(), _inner_glow_width(), _inner_glow_sharpness(),
_inner_glow_sharpness_inv(), _outer_glow(false), _outer_glow_color(), _outer_glow_width(),
_outer_glow_sharpness(), _outer_glow_sharpness_inv(), _outline(false), _outline_color(), _outline_width(),
_outline_offset(), _outline_sharpness(), _outline_sharpness_inv()
{
{
auto gctx = gs::context();
vec4 transparent = {0};
this->_source_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
this->_sdf_write = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE);
this->_sdf_read = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE);
this->_output_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
std::shared_ptr<gs::rendertarget> initialize_rts[] = {this->_source_rt, this->_sdf_write, this->_sdf_read,
this->_output_rt};
for (auto rt : initialize_rts) {
auto op = rt->render(1, 1);
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &transparent, 0, 0);
}
}
update(settings);
}
filter::sdf_effects::sdf_effects_instance::~sdf_effects_instance() {}
obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties()
obs_properties_t*
filter::sdf_effects::sdf_effects_factory::get_properties2(filter::sdf_effects::sdf_effects_instance* data)
{
obs_properties_t* props = obs_properties_create();
obs_property_t* p = nullptr;
@ -424,7 +244,7 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties()
{
p = obs_properties_add_bool(props, ST_SHADOW_OUTER, D_TRANSLATE(ST_SHADOW_OUTER));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SHADOW_OUTER)));
obs_property_set_modified_callback2(p, cb_modified_shadow_outside, this);
obs_property_set_modified_callback2(p, cb_modified_shadow_outside, data);
p = obs_properties_add_float_slider(props, ST_SHADOW_OUTER_RANGE_MINIMUM,
D_TRANSLATE(ST_SHADOW_OUTER_RANGE_MINIMUM), -16.0, 16.0, 0.01);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SHADOW_OUTER_RANGE_MINIMUM)));
@ -447,7 +267,7 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties()
{
p = obs_properties_add_bool(props, ST_SHADOW_INNER, D_TRANSLATE(ST_SHADOW_INNER));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SHADOW_INNER)));
obs_property_set_modified_callback2(p, cb_modified_shadow_inside, this);
obs_property_set_modified_callback2(p, cb_modified_shadow_inside, data);
p = obs_properties_add_float_slider(props, ST_SHADOW_INNER_RANGE_MINIMUM,
D_TRANSLATE(ST_SHADOW_INNER_RANGE_MINIMUM), -16.0, 16.0, 0.01);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SHADOW_INNER_RANGE_MINIMUM)));
@ -470,7 +290,7 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties()
{
p = obs_properties_add_bool(props, ST_GLOW_OUTER, D_TRANSLATE(ST_GLOW_OUTER));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_GLOW_OUTER)));
obs_property_set_modified_callback2(p, cb_modified_glow_outside, this);
obs_property_set_modified_callback2(p, cb_modified_glow_outside, data);
p = obs_properties_add_color(props, ST_GLOW_OUTER_COLOR, D_TRANSLATE(ST_GLOW_OUTER_COLOR));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_GLOW_OUTER_COLOR)));
@ -490,7 +310,7 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties()
{
p = obs_properties_add_bool(props, ST_GLOW_INNER, D_TRANSLATE(ST_GLOW_INNER));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_GLOW_INNER)));
obs_property_set_modified_callback2(p, cb_modified_glow_inside, this);
obs_property_set_modified_callback2(p, cb_modified_glow_inside, data);
p = obs_properties_add_color(props, ST_GLOW_INNER_COLOR, D_TRANSLATE(ST_GLOW_INNER_COLOR));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_GLOW_INNER_COLOR)));
@ -510,7 +330,7 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties()
{
p = obs_properties_add_bool(props, ST_OUTLINE, D_TRANSLATE(ST_OUTLINE));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OUTLINE)));
obs_property_set_modified_callback2(p, cb_modified_outline, this);
obs_property_set_modified_callback2(p, cb_modified_outline, data);
p = obs_properties_add_color(props, ST_OUTLINE_COLOR, D_TRANSLATE(ST_OUTLINE_COLOR));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_OUTLINE_COLOR)));
p = obs_properties_add_float_slider(props, ST_OUTLINE_ALPHA, D_TRANSLATE(ST_OUTLINE_ALPHA), 0.0, 100.0, 0.1);
@ -531,7 +351,7 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties()
{
p = obs_properties_add_bool(props, S_ADVANCED, D_TRANSLATE(S_ADVANCED));
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(S_ADVANCED)));
obs_property_set_modified_callback2(p, cb_modified_advanced, this);
obs_property_set_modified_callback2(p, cb_modified_advanced, data);
p = obs_properties_add_float_slider(props, ST_SDF_SCALE, D_TRANSLATE(ST_SDF_SCALE), 0.1, 500.0, 0.1);
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SDF_SCALE)));
@ -543,6 +363,56 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties()
return props;
}
filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* settings, obs_source_t* self)
: obs::source_instance(settings, self), _source_rendered(false), _sdf_scale(1.0), _sdf_threshold(),
_output_rendered(false), _inner_shadow(false), _inner_shadow_color(), _inner_shadow_range_min(),
_inner_shadow_range_max(), _inner_shadow_offset_x(), _inner_shadow_offset_y(), _outer_shadow(false),
_outer_shadow_color(), _outer_shadow_range_min(), _outer_shadow_range_max(), _outer_shadow_offset_x(),
_outer_shadow_offset_y(), _inner_glow(false), _inner_glow_color(), _inner_glow_width(), _inner_glow_sharpness(),
_inner_glow_sharpness_inv(), _outer_glow(false), _outer_glow_color(), _outer_glow_width(),
_outer_glow_sharpness(), _outer_glow_sharpness_inv(), _outline(false), _outline_color(), _outline_width(),
_outline_offset(), _outline_sharpness(), _outline_sharpness_inv()
{
{
auto gctx = gs::context();
vec4 transparent = {0};
this->_source_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
this->_sdf_write = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE);
this->_sdf_read = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE);
this->_output_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
std::shared_ptr<gs::rendertarget> initialize_rts[] = {this->_source_rt, this->_sdf_write, this->_sdf_read,
this->_output_rt};
for (auto rt : initialize_rts) {
auto op = rt->render(1, 1);
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &transparent, 0, 0);
}
std::pair<const char*, std::shared_ptr<gs::effect>&> load_arr[] = {
{"effects/sdf/sdf-producer.effect", this->_sdf_producer_effect},
{"effects/sdf/sdf-consumer.effect", this->_sdf_consumer_effect},
};
for (auto& kv : load_arr) {
char* path = obs_module_file(kv.first);
if (!path) {
P_LOG_ERROR(LOG_PREFIX "Unable to load _effect '%s' as file is missing or locked.", kv.first);
continue;
}
try {
kv.second = gs::effect::create(path);
} catch (const std::exception& ex) {
P_LOG_ERROR(LOG_PREFIX "Failed to load _effect '%s' (located at '%s') with error(s): %s", kv.first,
path, ex.what());
}
bfree(path);
}
}
update(settings);
}
filter::sdf_effects::sdf_effects_instance::~sdf_effects_instance() {}
void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
{
{
@ -680,20 +550,11 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
this->_sdf_threshold = float_t(obs_data_get_double(data, ST_SDF_THRESHOLD) / 100.0);
}
uint32_t filter::sdf_effects::sdf_effects_instance::get_width()
void filter::sdf_effects::sdf_effects_instance::load(obs_data_t* settings)
{
return uint32_t(0);
update(settings);
}
uint32_t filter::sdf_effects::sdf_effects_instance::get_height()
{
return uint32_t(0);
}
void filter::sdf_effects::sdf_effects_instance::activate() {}
void filter::sdf_effects::sdf_effects_instance::deactivate() {}
void filter::sdf_effects::sdf_effects_instance::video_tick(float)
{
uint32_t width = 1;
@ -773,8 +634,7 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
throw std::runtime_error("SDF Backbuffer empty");
}
std::shared_ptr<gs::effect> sdf_effect =
filter::sdf_effects::sdf_effects_factory::get()->get_sdf_producer_effect();
std::shared_ptr<gs::effect> sdf_effect = _sdf_producer_effect;
if (!sdf_effect) {
throw std::runtime_error("SDF Effect no loaded");
}
@ -824,8 +684,7 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
if (!this->_output_rendered) {
this->_output_texture = this->_source_texture;
std::shared_ptr<gs::effect> consumer_effect =
filter::sdf_effects::sdf_effects_factory::get()->get_sdf_consumer_effect();
std::shared_ptr<gs::effect> consumer_effect = _sdf_consumer_effect;
if (!consumer_effect) {
obs_source_skip_video_filter(this->_self);
return;

View file

@ -24,6 +24,7 @@
#include "obs/gs/gs-sampler.hpp"
#include "obs/gs/gs-texture.hpp"
#include "obs/gs/gs-vertexbuffer.hpp"
#include "obs/obs-source-factory.hpp"
#include "plugin.hpp"
// OBS
@ -38,53 +39,10 @@
namespace filter {
namespace sdf_effects {
class sdf_effects_instance;
class sdf_effects_factory {
obs_source_info _source_info;
std::list<sdf_effects_instance*> _sources;
class sdf_effects_instance : public obs::source_instance {
std::shared_ptr<gs::effect> _sdf_producer_effect;
std::shared_ptr<gs::effect> _sdf_consumer_effect;
public: // Singleton
static void initialize();
static void finalize();
static std::shared_ptr<sdf_effects_factory> get();
public:
sdf_effects_factory();
~sdf_effects_factory();
void on_list_fill();
void on_list_empty();
static void* create(obs_data_t* settings, obs_source_t* self) noexcept;
static void destroy(void* source) noexcept;
static void get_defaults(obs_data_t* settings) noexcept;
static obs_properties_t* get_properties(void* source) noexcept;
static void update(void* source, obs_data_t* settings) noexcept;
static const char* get_name(void* source) noexcept;
static uint32_t get_width(void* source) noexcept;
static uint32_t get_height(void* source) noexcept;
static void activate(void* source) noexcept;
static void deactivate(void* source) noexcept;
static void video_tick(void* source, float delta) noexcept;
static void video_render(void* source, gs_effect_t* effect) noexcept;
public:
std::shared_ptr<gs::effect> get_sdf_producer_effect();
std::shared_ptr<gs::effect> get_sdf_consumer_effect();
};
class sdf_effects_instance {
obs_source_t* _self;
// Input
std::shared_ptr<gs::rendertarget> _source_rt;
std::shared_ptr<gs::texture> _source_texture;
@ -135,39 +93,47 @@ namespace filter {
float_t _outline_sharpness;
float_t _outline_sharpness_inv;
static bool cb_modified_shadow_inside(void* ptr, obs_properties_t* props, obs_property* prop,
obs_data_t* settings) noexcept;
static bool cb_modified_shadow_outside(void* ptr, obs_properties_t* props, obs_property* prop,
obs_data_t* settings) noexcept;
static bool cb_modified_glow_inside(void* ptr, obs_properties_t* props, obs_property* prop,
obs_data_t* settings) noexcept;
static bool cb_modified_glow_outside(void* ptr, obs_properties_t* props, obs_property* prop,
obs_data_t* settings) noexcept;
static bool cb_modified_outline(void* ptr, obs_properties_t* props, obs_property* prop,
obs_data_t* settings) noexcept;
static bool cb_modified_advanced(void* ptr, obs_properties_t* props, obs_property* prop,
obs_data_t* settings) noexcept;
public:
sdf_effects_instance(obs_data_t* settings, obs_source_t* self);
~sdf_effects_instance();
virtual ~sdf_effects_instance();
obs_properties_t* get_properties();
void update(obs_data_t*);
virtual void update(obs_data_t* settings) override;
virtual void load(obs_data_t* settings) override;
uint32_t get_width();
uint32_t get_height();
void activate();
void deactivate();
void video_tick(float);
void video_render(gs_effect_t*);
virtual void video_tick(float) override;
virtual void video_render(gs_effect_t*) override;
};
class sdf_effects_factory : public obs::source_factory<filter::sdf_effects::sdf_effects_factory,
filter::sdf_effects::sdf_effects_instance> {
static std::shared_ptr<filter::sdf_effects::sdf_effects_factory> factory_instance;
public: // Singleton
static void initialize()
{
factory_instance = std::make_shared<filter::sdf_effects::sdf_effects_factory>();
}
static void finalize()
{
factory_instance.reset();
}
static std::shared_ptr<sdf_effects_factory> get()
{
return factory_instance;
}
public:
sdf_effects_factory();
virtual ~sdf_effects_factory();
virtual const char* get_name() override;
virtual void get_defaults2(obs_data_t* data) override;
virtual obs_properties_t* get_properties2(filter::sdf_effects::sdf_effects_instance* data) override;
};
} // namespace sdf_effects
} // namespace filter