diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 19f76e3ab..6f5ec2b8a 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -358,6 +358,7 @@ struct obs_source { DARRAY(struct obs_source*) filters; pthread_mutex_t filter_mutex; gs_texrender_t *filter_texrender; + enum obs_allow_direct_render allow_direct; bool rendering_filter; }; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 3d2a2889a..60e621b99 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -2025,8 +2025,8 @@ static inline bool can_bypass(obs_source_t *target, obs_source_t *parent, ((parent_flags & OBS_SOURCE_ASYNC) == 0); } -void obs_source_process_filter(obs_source_t *filter, gs_effect_t *effect, - uint32_t width, uint32_t height, enum gs_color_format format, +void obs_source_process_filter_begin(obs_source_t *filter, + enum gs_color_format format, enum obs_allow_direct_render allow_direct) { obs_source_t *target, *parent; @@ -2044,12 +2044,13 @@ void obs_source_process_filter(obs_source_t *filter, gs_effect_t *effect, cy = get_base_height(target); use_matrix = !!(target_flags & OBS_SOURCE_COLOR_MATRIX); + filter->allow_direct = allow_direct; + /* if the parent does not use any custom effects, and this is the last * filter in the chain for the parent, then render the parent directly * using the filter effect instead of rendering to texture to reduce * the total number of passes */ if (can_bypass(target, parent, parent_flags, allow_direct)) { - render_filter_bypass(target, effect, use_matrix); return; } @@ -2073,11 +2074,30 @@ void obs_source_process_filter(obs_source_t *filter, gs_effect_t *effect, gs_texrender_end(filter->filter_texrender); } +} - /* --------------------------- */ +void obs_source_process_filter_end(obs_source_t *filter, gs_effect_t *effect, + uint32_t width, uint32_t height) +{ + obs_source_t *target, *parent; + gs_texture_t *texture; + uint32_t target_flags, parent_flags; + bool use_matrix; - render_filter_tex(gs_texrender_get_texture(filter->filter_texrender), - effect, width, height, use_matrix); + if (!filter) return; + + target = obs_filter_get_target(filter); + parent = obs_filter_get_parent(filter); + target_flags = target->info.output_flags; + parent_flags = parent->info.output_flags; + use_matrix = !!(target_flags & OBS_SOURCE_COLOR_MATRIX); + + if (can_bypass(target, parent, parent_flags, filter->allow_direct)) { + render_filter_bypass(target, effect, use_matrix); + } else { + texture = gs_texrender_get_texture(filter->filter_texrender); + render_filter_tex(texture, effect, width, height, use_matrix); + } } void obs_source_skip_video_filter(obs_source_t *filter) diff --git a/libobs/obs.h b/libobs/obs.h index 8d5a9ffb2..cd96613f6 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -877,11 +877,28 @@ EXPORT struct obs_source_frame *obs_source_get_frame(obs_source_t *source); EXPORT void obs_source_release_frame(obs_source_t *source, struct obs_source_frame *frame); -/** Default RGB filter handler for generic effect filters */ -EXPORT void obs_source_process_filter(obs_source_t *filter, gs_effect_t *effect, - uint32_t width, uint32_t height, enum gs_color_format format, +/** + * Default RGB filter handler for generic effect filters. Processes the + * filter chain and renders them to texture if needed, then the filter is + * drawn with + * + * After calling this, set your parameters for the effect, then call + * obs_source_process_filter_end to draw the filter. + */ +EXPORT void obs_source_process_filter_begin(obs_source_t *filter, + enum gs_color_format format, enum obs_allow_direct_render allow_direct); +/** + * Draws the filter. + * + * Before calling this function, first call obs_source_process_filter_begin and + * then set the effect parameters, and then call this function to finalize the + * filter. + */ +EXPORT void obs_source_process_filter_end(obs_source_t *filter, + gs_effect_t *effect, uint32_t width, uint32_t height); + /** Skips the filter if the filter is invalid and cannot be rendered */ EXPORT void obs_source_skip_video_filter(obs_source_t *filter); diff --git a/test/test-input/test-filter.c b/test/test-input/test-filter.c index ffcc07657..264a7172d 100644 --- a/test/test-input/test-filter.c +++ b/test/test-input/test-filter.c @@ -50,8 +50,10 @@ static void *filter_create(obs_data_t *settings, obs_source_t *source) static void filter_render(void *data, gs_effect_t *effect) { struct test_filter *tf = data; - obs_source_process_filter(tf->source, tf->whatever, 0, 0, GS_RGBA, + + obs_source_process_filter_begin(tf->source, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING); + obs_source_process_filter_end(tf->source, tf->whatever, 0, 0); UNUSED_PARAMETER(effect); }