source-shader: Update to new gfx::shader::shader
This commit is contained in:
		
							parent
							
								
									e6220b18f6
								
							
						
					
					
						commit
						47dba25052
					
				|  | @ -23,279 +23,97 @@ | ||||||
| #include "utility.hpp" | #include "utility.hpp" | ||||||
| 
 | 
 | ||||||
| #define ST "Source.Shader" | #define ST "Source.Shader" | ||||||
| #define ST_WIDTH ST ".Width" |  | ||||||
| #define ST_HEIGHT ST ".Height" |  | ||||||
| 
 |  | ||||||
| static std::shared_ptr<source::shader::shader_factory> factory_instance = nullptr; |  | ||||||
| 
 |  | ||||||
| void source::shader::shader_factory::initialize() |  | ||||||
| { |  | ||||||
| 	factory_instance = std::make_shared<source::shader::shader_factory>(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void source::shader::shader_factory::finalize() |  | ||||||
| { |  | ||||||
| 	factory_instance.reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::shared_ptr<source::shader::shader_factory> 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<void*>(new source::shader::shader_instance(data, self)); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to create source, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to create source."); |  | ||||||
| 		} |  | ||||||
| 		return static_cast<void*>(nullptr); |  | ||||||
| 	}; |  | ||||||
| 	_source_info.destroy = [](void* ptr) { |  | ||||||
| 		try { |  | ||||||
| 			delete reinterpret_cast<source::shader::shader_instance*>(ptr); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to delete source, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to delete source."); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	_source_info.get_properties = [](void* ptr) { |  | ||||||
| 		obs_properties_t* pr = obs_properties_create(); |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				reinterpret_cast<source::shader::shader_instance*>(ptr)->properties(pr); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to retrieve options, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to retrieve options."); |  | ||||||
| 		} |  | ||||||
| 		return pr; |  | ||||||
| 	}; |  | ||||||
| 	_source_info.get_width = [](void* ptr) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				return reinterpret_cast<source::shader::shader_instance*>(ptr)->width(); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to retrieve width, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to retrieve width."); |  | ||||||
| 		} |  | ||||||
| 		return uint32_t(0); |  | ||||||
| 	}; |  | ||||||
| 	_source_info.get_height = [](void* ptr) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				return reinterpret_cast<source::shader::shader_instance*>(ptr)->height(); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to retrieve height, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to retrieve height."); |  | ||||||
| 		} |  | ||||||
| 		return uint32_t(0); |  | ||||||
| 	}; |  | ||||||
| 	_source_info.load = [](void* ptr, obs_data_t* data) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				reinterpret_cast<source::shader::shader_instance*>(ptr)->load(data); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to load, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to load."); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	_source_info.update = [](void* ptr, obs_data_t* data) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				reinterpret_cast<source::shader::shader_instance*>(ptr)->update(data); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to update, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to update."); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	_source_info.activate = [](void* ptr) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				reinterpret_cast<source::shader::shader_instance*>(ptr)->activate(); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to activate, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to activate."); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	_source_info.deactivate = [](void* ptr) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				reinterpret_cast<source::shader::shader_instance*>(ptr)->deactivate(); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to deactivate, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to deactivate."); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	_source_info.video_tick = [](void* ptr, float_t time) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				reinterpret_cast<source::shader::shader_instance*>(ptr)->video_tick(time); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to tick, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to tick."); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	_source_info.video_render = [](void* ptr, gs_effect_t* effect) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				reinterpret_cast<source::shader::shader_instance*>(ptr)->video_render(effect); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to render, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to render."); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	_source_info.enum_active_sources = [](void* ptr, obs_source_enum_proc_t enum_callback, void* param) { |  | ||||||
| 		try { |  | ||||||
| 			if (ptr) |  | ||||||
| 				reinterpret_cast<source::shader::shader_instance*>(ptr)->enum_active_sources(enum_callback, param); |  | ||||||
| 		} catch (const std::exception& ex) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> Failed to enumerate sources, error: %s", ex.what()); |  | ||||||
| 		} catch (...) { |  | ||||||
| 			P_LOG_ERROR("<source-shader> 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) | 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<gfx::effect_source::effect_source>(self); | 	_fx = std::make_shared<gfx::shader::shader>(self, gfx::shader::shader_mode::Source); | ||||||
| 	_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::rendertarget>(GS_RGBA, GS_ZS_NONE); |  | ||||||
| 
 | 
 | ||||||
| 	update(data); | 	update(data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| source::shader::shader_instance::~shader_instance() {} | 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) | 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); | 	_fx->properties(props); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void source::shader::shader_instance::load(obs_data_t* data) | 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) | void source::shader::shader_instance::update(obs_data_t* data) | ||||||
| { | { | ||||||
| 	_width  = static_cast<uint32_t>(obs_data_get_int(data, ST_WIDTH)); |  | ||||||
| 	_height = static_cast<uint32_t>(obs_data_get_int(data, ST_HEIGHT)); |  | ||||||
| 
 |  | ||||||
| 	_fx->update(data); | 	_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<gs::effect_parameter> param) |  | ||||||
| { |  | ||||||
| 	return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void source::shader::shader_instance::override_param(std::shared_ptr<gs::effect> 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) | void source::shader::shader_instance::video_tick(float_t sec_since_last) | ||||||
| { | { | ||||||
| 	if (_fx->tick(sec_since_last)) { | 	if (_fx->tick(sec_since_last)) { | ||||||
| 		obs_data_t* data = obs_source_get_settings(_self); | 		obs_data_t* data = obs_source_get_settings(_self); | ||||||
| 		update(data); | 		_fx->update(data); | ||||||
| 		obs_data_release(data); | 		obs_data_release(data); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	_rt_updated = false; | 	_is_main = true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void source::shader::shader_instance::video_render(gs_effect_t* effect) | void source::shader::shader_instance::video_render(gs_effect_t* effect) | ||||||
| { | { | ||||||
| 	// Grab initial values.
 | 	if (!_fx) { | ||||||
| 	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); |  | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!_rt_updated) { | 	if (_is_main) { // Dirty hack to only take the value from the first render, which usually is the main view.
 | ||||||
| 		try { | 		gs_rect vect; | ||||||
| 			auto op = _rt->render(_width, _height); | 		gs_get_viewport(&vect); | ||||||
|  | 		_fx->set_size(static_cast<uint32_t>(vect.cx), static_cast<uint32_t>(vect.cy)); | ||||||
|  | 		_is_main = false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	_fx->render(); | 	_fx->render(); | ||||||
| 		} catch (...) { | } | ||||||
| 		} | 
 | ||||||
| 		_rt_tex     = _rt->get_texture(); | std::shared_ptr<source::shader::shader_factory> source::shader::shader_factory::factory_instance = nullptr; | ||||||
| 		_rt_updated = true; | 
 | ||||||
| 	} | source::shader::shader_factory::shader_factory() | ||||||
| 
 | { | ||||||
| 	if (!_rt_tex) | 	_info.id           = "obs-stream-effects-source-shader"; | ||||||
| 		return; | 	_info.type         = OBS_SOURCE_TYPE_INPUT; | ||||||
| 
 | 	_info.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW; | ||||||
| 	gs_effect_t* ef = effect ? effect : effect_default; | 
 | ||||||
| 	if (gs_eparam_t* prm = gs_effect_get_param_by_name(ef, "image")) | 	finish_setup(); | ||||||
| 		gs_effect_set_texture(prm, _rt_tex->get_object()); | } | ||||||
| 
 | 
 | ||||||
| 	while (gs_effect_loop(ef, "Draw")) { | source::shader::shader_factory::~shader_factory() {} | ||||||
| 		gs_draw_sprite(nullptr, 0, _width, _height); | 
 | ||||||
| 	} | 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<shader_instance*>(data)->properties(pr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return pr; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,8 +19,9 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "gfx/gfx-effect-source.hpp" | #include "gfx/shader/gfx-shader.hpp" | ||||||
| #include "obs/gs/gs-rendertarget.hpp" | #include "obs/gs/gs-rendertarget.hpp" | ||||||
|  | #include "obs/obs-source-factory.hpp" | ||||||
| #include "plugin.hpp" | #include "plugin.hpp" | ||||||
| 
 | 
 | ||||||
| extern "C" { | extern "C" { | ||||||
|  | @ -29,53 +30,56 @@ extern "C" { | ||||||
| 
 | 
 | ||||||
| namespace source { | namespace source { | ||||||
| 	namespace shader { | 	namespace shader { | ||||||
| 		class shader_factory { | 		class shader_instance : public obs::source_instance {			 | ||||||
| 			obs_source_info _source_info; | 			std::shared_ptr<gfx::shader::shader> _fx; | ||||||
| 
 | 
 | ||||||
| 			public: // Singleton
 | 			bool _is_main; | ||||||
| 			static void                            initialize(); |  | ||||||
| 			static void                            finalize(); |  | ||||||
| 			static std::shared_ptr<shader_factory> get(); |  | ||||||
| 
 |  | ||||||
| 			public: |  | ||||||
| 			shader_factory(); |  | ||||||
| 			~shader_factory(); |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		class shader_instance { |  | ||||||
| 			obs_source_t* _self; |  | ||||||
| 			bool          _active; |  | ||||||
| 
 |  | ||||||
| 			uint32_t _width, _height; |  | ||||||
| 
 |  | ||||||
| 			std::shared_ptr<gs::rendertarget> _rt; |  | ||||||
| 			bool                              _rt_updated; |  | ||||||
| 			std::shared_ptr<gs::texture>      _rt_tex; |  | ||||||
| 
 |  | ||||||
| 			std::shared_ptr<gfx::effect_source::effect_source> _fx; |  | ||||||
| 
 | 
 | ||||||
| 			public: | 			public: | ||||||
| 			shader_instance(obs_data_t* data, obs_source_t* self); | 			shader_instance(obs_data_t* data, obs_source_t* self); | ||||||
| 			~shader_instance(); | 			virtual ~shader_instance(); | ||||||
| 
 | 
 | ||||||
| 			uint32_t width(); | 			virtual uint32_t get_width() override; | ||||||
| 			uint32_t height(); | 			virtual uint32_t get_height() override; | ||||||
| 
 | 
 | ||||||
| 			void properties(obs_properties_t* props); | 			void properties(obs_properties_t* props); | ||||||
| 
 | 
 | ||||||
| 			void load(obs_data_t* data); | 			virtual void load(obs_data_t* data) override; | ||||||
| 			void update(obs_data_t* data); | 			virtual void update(obs_data_t* data) override; | ||||||
| 
 | 
 | ||||||
| 			void activate(); | 			virtual void video_tick(float_t sec_since_last) override; | ||||||
| 			void deactivate(); | 			virtual void video_render(gs_effect_t* effect) override; | ||||||
|  | 		}; | ||||||
| 
 | 
 | ||||||
| 			bool valid_param(std::shared_ptr<gs::effect_parameter> param); | 		class shader_factory | ||||||
| 			void override_param(std::shared_ptr<gs::effect> effect); | 			: public obs::source_factory<source::shader::shader_factory, source::shader::shader_instance> { | ||||||
|  | 			static std::shared_ptr<source::shader::shader_factory> factory_instance; | ||||||
| 
 | 
 | ||||||
| 			void enum_active_sources(obs_source_enum_proc_t, void*); | 			public: // Singleton
 | ||||||
|  | 			static void initialize() | ||||||
|  | 			{ | ||||||
|  | 				factory_instance = std::make_shared<source::shader::shader_factory>(); | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 			void video_tick(float_t sec_since_last); | 			static void finalize() | ||||||
| 			void video_render(gs_effect_t* effect); | 			{ | ||||||
|  | 				factory_instance.reset(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			static std::shared_ptr<shader_factory> 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 shader
 | ||||||
| } // namespace source
 | } // namespace source
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue