diff --git a/source/filter-displacement.cpp b/source/filter-displacement.cpp index 7ce4169c..27281382 100644 --- a/source/filter-displacement.cpp +++ b/source/filter-displacement.cpp @@ -140,14 +140,38 @@ void filter::DisplacementAddon::video_render(void* ptr, gs_effect_t* effect) reinterpret_cast(ptr)->video_render(effect); } -filter::Displacement::Displacement(obs_data_t* data, obs_source_t* context) - : m_self(context), m_active(true), m_effect(nullptr), m_distance(0), m_timer(0) +void filter::Displacement::validate_file_texture(std::string file) { - this->m_displacement_map.texture = nullptr; - this->m_displacement_map.createTime = 0; - this->m_displacement_map.modifiedTime = 0; - this->m_displacement_map.size = 0; + bool do_update = false; + // File name different + if (file != m_file_name) { + do_update = true; + m_file_name = file; + } + + // Timestamp verification + struct stat stats; + if (os_stat(m_file_name.c_str(), &stats) != 0) { + do_update = do_update || (stats.st_ctime != m_file_create_time); + do_update = do_update || (stats.st_mtime != m_file_modified_time); + do_update = do_update || (stats.st_size != m_file_size); + m_file_create_time = stats.st_ctime; + m_file_modified_time = stats.st_mtime; + m_file_size = stats.st_size; + } + + do_update = !m_file_texture || do_update; + + if (do_update) { + m_file_texture = std::make_shared(m_file_name); + } +} + +filter::Displacement::Displacement(obs_data_t* data, obs_source_t* context) + : m_self(context), m_active(true), m_timer(0), m_effect(nullptr), m_distance(0), m_file_create_time(0), + m_file_modified_time(0), m_file_size(0) +{ char* effectFile = obs_module_file("effects/displace.effect"); try { m_effect = std::make_shared(effectFile); @@ -162,15 +186,12 @@ filter::Displacement::Displacement(obs_data_t* data, obs_source_t* context) filter::Displacement::~Displacement() { m_effect.reset(); - - obs_enter_graphics(); - gs_texture_destroy(m_displacement_map.texture); - obs_leave_graphics(); + m_file_texture.reset(); } void filter::Displacement::update(obs_data_t* data) { - updateDisplacementMap(obs_data_get_string(data, S_FILTER_DISPLACEMENT_FILE)); + validate_file_texture(obs_data_get_string(data, S_FILTER_DISPLACEMENT_FILE)); m_distance = float_t(obs_data_get_double(data, S_FILTER_DISPLACEMENT_RATIO)); vec2_set(&m_displacement_scale, float_t(obs_data_get_double(data, S_FILTER_DISPLACEMENT_SCALE)), @@ -200,7 +221,7 @@ void filter::Displacement::video_tick(float time) m_timer += time; if (m_timer >= 1.0) { m_timer -= 1.0; - updateDisplacementMap(m_displacement_map.file); + validate_file_texture(m_file_name); } } @@ -216,27 +237,25 @@ void filter::Displacement::video_render(gs_effect_t*) uint32_t baseW = obs_source_get_base_width(target), baseH = obs_source_get_base_height(target); // Skip rendering if our target, parent or context is not valid. - if (!parent || !target || !baseW || !baseH || !m_displacement_map.texture) { + if (!parent || !target || !baseW || !baseH || !m_file_texture) { obs_source_skip_video_filter(m_self); return; } - if (!obs_source_process_filter_begin(m_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) + if (!obs_source_process_filter_begin(m_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) { + obs_source_skip_video_filter(m_self); return; - - gs_eparam_t* param; - - vec2 texelScale; - vec2_set(&texelScale, interp((1.0f / baseW), 1.0f, m_distance), interp((1.0f / baseH), 1.0f, m_distance)); + } if (m_effect->has_parameter("texelScale")) { - m_effect->get_parameter("texelScale").set_float2(texelScale); + m_effect->get_parameter("texelScale") + .set_float2(interp((1.0f / baseW), 1.0f, m_distance), interp((1.0f / baseH), 1.0f, m_distance)); } if (m_effect->has_parameter("displacementScale")) { - m_effect->get_parameter("displacmenetScale").set_float2(m_displacement_scale); + m_effect->get_parameter("displacementScale").set_float2(m_displacement_scale); } if (m_effect->has_parameter("displacementMap")) { - m_effect->get_parameter("displacementMap").set_texture(m_displacement_map.texture); + m_effect->get_parameter("displacementMap").set_texture(m_file_texture); } obs_source_process_filter_end(m_self, m_effect->get_object(), baseW, baseH); @@ -244,35 +263,5 @@ void filter::Displacement::video_render(gs_effect_t*) std::string filter::Displacement::get_file() { - return m_displacement_map.file; -} - -void filter::Displacement::updateDisplacementMap(std::string file) -{ - bool shouldUpdateTexture = false; - - // Different File - if (file != m_displacement_map.file) { - m_displacement_map.file = file; - shouldUpdateTexture = true; - } else { // Different Timestamps - struct stat stats; - if (os_stat(m_displacement_map.file.c_str(), &stats) != 0) { - shouldUpdateTexture = shouldUpdateTexture || (m_displacement_map.createTime != stats.st_ctime) - || (m_displacement_map.modifiedTime != stats.st_mtime); - m_displacement_map.createTime = stats.st_ctime; - m_displacement_map.modifiedTime = stats.st_mtime; - } - } - - if (shouldUpdateTexture) { - obs_enter_graphics(); - if (m_displacement_map.texture) { - gs_texture_destroy(m_displacement_map.texture); - m_displacement_map.texture = nullptr; - } - if (os_file_exists(file.c_str())) - m_displacement_map.texture = gs_texture_create_from_file(m_displacement_map.file.c_str()); - obs_leave_graphics(); - } + return m_file_name; } diff --git a/source/filter-displacement.hpp b/source/filter-displacement.hpp index 2133f7b0..5c8f41c3 100644 --- a/source/filter-displacement.hpp +++ b/source/filter-displacement.hpp @@ -68,21 +68,21 @@ namespace filter { class Displacement { obs_source_t* m_self; bool m_active; + float_t m_timer; // Rendering std::shared_ptr m_effect; float_t m_distance; vec2 m_displacement_scale; - struct { - std::string file; - gs_texture_t* texture; - time_t createTime, modifiedTime; - size_t size; - } m_displacement_map; - float_t m_timer; + // Displacement Map + std::string m_file_name; + std::shared_ptr m_file_texture; + time_t m_file_create_time; + time_t m_file_modified_time; + size_t m_file_size; - void updateDisplacementMap(std::string file); + void validate_file_texture(std::string file); public: Displacement(obs_data_t*, obs_source_t*);