diff --git a/docs/sphinx/reference-sources.rst b/docs/sphinx/reference-sources.rst index eebe3ad5a..d752039c1 100644 --- a/docs/sphinx/reference-sources.rst +++ b/docs/sphinx/reference-sources.rst @@ -1348,16 +1348,6 @@ Functions used by filters --------------------- -.. function:: void obs_source_process_filter_end_srgb(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height) - - Draws the filter using the effect's "Draw" technique, and use automatic SRGB conversion. - - 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. - ---------------------- - .. function:: void obs_source_process_filter_tech_end(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height, const char *tech_name) Draws the filter with a specific technique in the effect. @@ -1368,16 +1358,6 @@ Functions used by filters --------------------- -.. function:: void obs_source_process_filter_tech_end_srgb(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height, const char *tech_name) - - Draws the filter with a specific technique in the effect, and use automatic SRGB conversion. - - 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. - ---------------------- - .. function:: void obs_source_skip_video_filter(obs_source_t *filter) Skips the filter if the filter is invalid and cannot be rendered. diff --git a/libobs/obs-scene.c b/libobs/obs-scene.c index 6c92a6845..ec05ea21b 100644 --- a/libobs/obs-scene.c +++ b/libobs/obs-scene.c @@ -1261,7 +1261,8 @@ const struct obs_source_info scene_info = { .id = "scene", .type = OBS_SOURCE_TYPE_SCENE, .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | - OBS_SOURCE_COMPOSITE | OBS_SOURCE_DO_NOT_DUPLICATE, + OBS_SOURCE_COMPOSITE | OBS_SOURCE_DO_NOT_DUPLICATE | + OBS_SOURCE_SRGB, .get_name = scene_getname, .create = scene_create, .destroy = scene_destroy, @@ -1279,7 +1280,7 @@ const struct obs_source_info group_info = { .id = "group", .type = OBS_SOURCE_TYPE_SCENE, .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | - OBS_SOURCE_COMPOSITE, + OBS_SOURCE_COMPOSITE | OBS_SOURCE_SRGB, .get_name = group_getname, .create = scene_create, .destroy = scene_destroy, diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 79e21687e..20314a816 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -2221,14 +2221,24 @@ static inline void obs_source_main_render(obs_source_t *source) { uint32_t flags = source->info.output_flags; bool custom_draw = (flags & OBS_SOURCE_CUSTOM_DRAW) != 0; + bool srgb_aware = (flags & OBS_SOURCE_SRGB) != 0; bool default_effect = !source->filter_parent && source->filters.num == 0 && !custom_draw; + bool previous_srgb; + + if (!srgb_aware) { + previous_srgb = gs_get_linear_srgb(); + gs_set_linear_srgb(false); + } if (default_effect) obs_source_default_render(source); else if (source->context.data) source->info.video_render(source->context.data, custom_draw ? NULL : gs_get_effect()); + + if (!srgb_aware) + gs_set_linear_srgb(previous_srgb); } static bool ready_async_frame(obs_source_t *source, uint64_t sys_time); @@ -3666,13 +3676,15 @@ static inline void render_filter_tex(gs_texture_t *tex, gs_effect_t *effect, } static inline bool can_bypass(obs_source_t *target, obs_source_t *parent, - uint32_t parent_flags, + uint32_t filter_flags, uint32_t parent_flags, enum obs_allow_direct_render allow_direct) { return (target == parent) && (allow_direct == OBS_ALLOW_DIRECT_RENDERING) && ((parent_flags & OBS_SOURCE_CUSTOM_DRAW) == 0) && - ((parent_flags & OBS_SOURCE_ASYNC) == 0); + ((parent_flags & OBS_SOURCE_ASYNC) == 0) && + (((filter_flags & OBS_SOURCE_SRGB) == 0) || + ((parent_flags & OBS_SOURCE_SRGB) == 0)); } bool obs_source_process_filter_begin(obs_source_t *filter, @@ -3680,7 +3692,7 @@ bool obs_source_process_filter_begin(obs_source_t *filter, enum obs_allow_direct_render allow_direct) { obs_source_t *target, *parent; - uint32_t parent_flags; + uint32_t filter_flags, parent_flags; int cx, cy; if (!obs_ptr_valid(filter, "obs_source_process_filter_begin")) @@ -3700,6 +3712,7 @@ bool obs_source_process_filter_begin(obs_source_t *filter, return false; } + filter_flags = filter->info.output_flags; parent_flags = parent->info.output_flags; cx = get_base_width(target); cy = get_base_height(target); @@ -3710,7 +3723,8 @@ bool obs_source_process_filter_begin(obs_source_t *filter, * 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)) { + if (can_bypass(target, parent, filter_flags, parent_flags, + allow_direct)) { return true; } @@ -3748,13 +3762,13 @@ bool obs_source_process_filter_begin(obs_source_t *filter, return true; } -static void obs_source_process_filter_tech_end_internal( - obs_source_t *filter, gs_effect_t *effect, uint32_t width, - uint32_t height, const char *tech_name, bool linear_srgb) +void obs_source_process_filter_tech_end(obs_source_t *filter, + gs_effect_t *effect, uint32_t width, + uint32_t height, const char *tech_name) { obs_source_t *target, *parent; gs_texture_t *texture; - uint32_t parent_flags; + uint32_t filter_flags, parent_flags; if (!filter) return; @@ -3765,13 +3779,16 @@ static void obs_source_process_filter_tech_end_internal( if (!target || !parent) return; - const bool previous = gs_set_linear_srgb(linear_srgb); - + filter_flags = filter->info.output_flags; parent_flags = parent->info.output_flags; + const bool previous = + gs_set_linear_srgb((filter_flags & OBS_SOURCE_SRGB) != 0); + const char *tech = tech_name ? tech_name : "Draw"; - if (can_bypass(target, parent, parent_flags, filter->allow_direct)) { + if (can_bypass(target, parent, filter_flags, parent_flags, + filter->allow_direct)) { render_filter_bypass(target, effect, tech); } else { texture = gs_texrender_get_texture(filter->filter_texrender); @@ -3783,23 +3800,6 @@ static void obs_source_process_filter_tech_end_internal( gs_set_linear_srgb(previous); } -void obs_source_process_filter_tech_end(obs_source_t *filter, - gs_effect_t *effect, uint32_t width, - uint32_t height, const char *tech_name) -{ - obs_source_process_filter_tech_end_internal(filter, effect, width, - height, tech_name, false); -} - -void obs_source_process_filter_tech_end_srgb(obs_source_t *filter, - gs_effect_t *effect, - uint32_t width, uint32_t height, - const char *tech_name) -{ - obs_source_process_filter_tech_end_internal(filter, effect, width, - height, tech_name, true); -} - void obs_source_process_filter_end(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height) { @@ -3810,17 +3810,6 @@ void obs_source_process_filter_end(obs_source_t *filter, gs_effect_t *effect, "Draw"); } -void obs_source_process_filter_end_srgb(obs_source_t *filter, - gs_effect_t *effect, uint32_t width, - uint32_t height) -{ - if (!obs_ptr_valid(filter, "obs_source_process_filter_end_srgb")) - return; - - obs_source_process_filter_tech_end_srgb(filter, effect, width, height, - "Draw"); -} - void obs_source_skip_video_filter(obs_source_t *filter) { obs_source_t *target, *parent; diff --git a/libobs/obs-source.h b/libobs/obs-source.h index 2ae0b182f..fafb1c2dd 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -191,6 +191,11 @@ enum obs_media_state { */ #define OBS_SOURCE_CEA_708 (1 << 14) +/** + * Source understands SRGB rendering + */ +#define OBS_SOURCE_SRGB (1 << 15) + /** @} */ typedef void (*obs_source_enum_proc_t)(obs_source_t *parent, diff --git a/libobs/obs.h b/libobs/obs.h index dccba4dba..94461e8dd 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -1330,9 +1330,6 @@ obs_source_process_filter_begin(obs_source_t *filter, EXPORT void obs_source_process_filter_end(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height); -EXPORT void obs_source_process_filter_end_srgb(obs_source_t *filter, - gs_effect_t *effect, - uint32_t width, uint32_t height); /** * Draws the filter with a specific technique. @@ -1345,11 +1342,6 @@ EXPORT void obs_source_process_filter_tech_end(obs_source_t *filter, gs_effect_t *effect, uint32_t width, uint32_t height, const char *tech_name); -EXPORT void obs_source_process_filter_tech_end_srgb(obs_source_t *filter, - gs_effect_t *effect, - uint32_t width, - uint32_t height, - const char *tech_name); /** 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/plugins/obs-filters/chroma-key-filter.c b/plugins/obs-filters/chroma-key-filter.c index 64cab56df..0fac53041 100644 --- a/plugins/obs-filters/chroma-key-filter.c +++ b/plugins/obs-filters/chroma-key-filter.c @@ -390,8 +390,7 @@ static void chroma_key_render_v2(void *data, gs_effect_t *effect) gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); - obs_source_process_filter_end_srgb(filter->context, filter->effect, 0, - 0); + obs_source_process_filter_end(filter->context, filter->effect, 0, 0); gs_blend_state_pop(); @@ -526,7 +525,7 @@ struct obs_source_info chroma_key_filter_v2 = { .id = "chroma_key_filter", .version = 2, .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = chroma_key_name, .create = chroma_key_create_v2, .destroy = chroma_key_destroy_v2, diff --git a/plugins/obs-filters/color-correction-filter.c b/plugins/obs-filters/color-correction-filter.c index 41d7023b4..a49d11961 100644 --- a/plugins/obs-filters/color-correction-filter.c +++ b/plugins/obs-filters/color-correction-filter.c @@ -613,8 +613,7 @@ static void color_correction_filter_render_v2(void *data, gs_effect_t *effect) gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); - obs_source_process_filter_end_srgb(filter->context, filter->effect, 0, - 0); + obs_source_process_filter_end(filter->context, filter->effect, 0, 0); gs_blend_state_pop(); @@ -734,7 +733,7 @@ struct obs_source_info color_filter_v2 = { .id = "color_filter", .version = 2, .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = color_correction_filter_name, .create = color_correction_filter_create_v2, .destroy = color_correction_filter_destroy_v2, diff --git a/plugins/obs-filters/color-grade-filter.c b/plugins/obs-filters/color-grade-filter.c index 987b0c9d3..1c1788de2 100644 --- a/plugins/obs-filters/color-grade-filter.c +++ b/plugins/obs-filters/color-grade-filter.c @@ -452,8 +452,8 @@ static void color_grade_filter_render(void *data, gs_effect_t *effect) param = gs_effect_get_param_by_name(filter->effect, "cube_width_i"); gs_effect_set_float(param, 1.0f / filter->cube_width); - obs_source_process_filter_tech_end_srgb(filter->context, filter->effect, - 0, 0, tech_name); + obs_source_process_filter_tech_end(filter->context, filter->effect, 0, + 0, tech_name); UNUSED_PARAMETER(effect); } @@ -461,7 +461,7 @@ static void color_grade_filter_render(void *data, gs_effect_t *effect) struct obs_source_info color_grade_filter = { .id = "clut_filter", .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = color_grade_filter_get_name, .create = color_grade_filter_create, .destroy = color_grade_filter_destroy, diff --git a/plugins/obs-filters/color-key-filter.c b/plugins/obs-filters/color-key-filter.c index 79c1b3131..af46bd2a8 100644 --- a/plugins/obs-filters/color-key-filter.c +++ b/plugins/obs-filters/color-key-filter.c @@ -338,8 +338,7 @@ static void color_key_render_v2(void *data, gs_effect_t *effect) gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); - obs_source_process_filter_end_srgb(filter->context, filter->effect, 0, - 0); + obs_source_process_filter_end(filter->context, filter->effect, 0, 0); gs_blend_state_pop(); @@ -472,7 +471,7 @@ struct obs_source_info color_key_filter_v2 = { .id = "color_key_filter", .version = 2, .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = color_key_name, .create = color_key_create_v2, .destroy = color_key_destroy_v2, diff --git a/plugins/obs-filters/crop-filter.c b/plugins/obs-filters/crop-filter.c index e0701e00b..ded274db4 100644 --- a/plugins/obs-filters/crop-filter.c +++ b/plugins/obs-filters/crop-filter.c @@ -196,8 +196,8 @@ static void crop_filter_render(void *data, gs_effect_t *effect) gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); - obs_source_process_filter_end_srgb(filter->context, filter->effect, - filter->width, filter->height); + obs_source_process_filter_end(filter->context, filter->effect, + filter->width, filter->height); gs_blend_state_pop(); @@ -219,7 +219,7 @@ static uint32_t crop_filter_height(void *data) struct obs_source_info crop_filter = { .id = "crop_filter", .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = crop_filter_get_name, .create = crop_filter_create, .destroy = crop_filter_destroy, diff --git a/plugins/obs-filters/luma-key-filter.c b/plugins/obs-filters/luma-key-filter.c index a3a70b4ea..e597753ed 100644 --- a/plugins/obs-filters/luma-key-filter.c +++ b/plugins/obs-filters/luma-key-filter.c @@ -115,8 +115,10 @@ static void *luma_key_create_v2(obs_data_t *settings, obs_source_t *context) "luma_key_filter_v2.effect"); } -static void luma_key_render_internal(void *data, bool srgb) +static void luma_key_render(void *data, gs_effect_t *effect) { + UNUSED_PARAMETER(effect); + struct luma_key_filter_data *filter = data; if (!obs_source_process_filter_begin(filter->context, GS_RGBA, @@ -130,27 +132,7 @@ static void luma_key_render_internal(void *data, bool srgb) gs_effect_set_float(filter->luma_min_smooth_param, filter->luma_min_smooth); - if (srgb) { - obs_source_process_filter_end_srgb(filter->context, - filter->effect, 0, 0); - } else { - obs_source_process_filter_end(filter->context, filter->effect, - 0, 0); - } -} - -static void luma_key_render_v1(void *data, gs_effect_t *effect) -{ - UNUSED_PARAMETER(effect); - - luma_key_render_internal(data, false); -} - -static void luma_key_render_v2(void *data, gs_effect_t *effect) -{ - UNUSED_PARAMETER(effect); - - luma_key_render_internal(data, true); + obs_source_process_filter_end(filter->context, filter->effect, 0, 0); } static obs_properties_t *luma_key_properties(void *data) @@ -185,7 +167,7 @@ struct obs_source_info luma_key_filter = { .get_name = luma_key_name, .create = luma_key_create_v1, .destroy = luma_key_destroy, - .video_render = luma_key_render_v1, + .video_render = luma_key_render, .update = luma_key_update, .get_properties = luma_key_properties, .get_defaults = luma_key_defaults, @@ -195,11 +177,11 @@ struct obs_source_info luma_key_filter_v2 = { .id = "luma_key_filter", .version = 2, .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = luma_key_name, .create = luma_key_create_v2, .destroy = luma_key_destroy, - .video_render = luma_key_render_v2, + .video_render = luma_key_render, .update = luma_key_update, .get_properties = luma_key_properties, .get_defaults = luma_key_defaults, diff --git a/plugins/obs-filters/mask-filter.c b/plugins/obs-filters/mask-filter.c index 7dd14776d..9685d981a 100644 --- a/plugins/obs-filters/mask-filter.c +++ b/plugins/obs-filters/mask-filter.c @@ -262,7 +262,7 @@ static void mask_filter_tick(void *data, float seconds) } } -static void mask_filter_render_internal(void *data, bool srgb) +static void mask_filter_render(void *data, gs_effect_t *effect) { struct mask_filter_data *filter = data; obs_source_t *target = obs_filter_get_target(filter->context); @@ -324,27 +324,9 @@ static void mask_filter_render_internal(void *data, bool srgb) gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); - if (srgb) { - obs_source_process_filter_end_srgb(filter->context, - filter->effect, 0, 0); - } else { - obs_source_process_filter_end(filter->context, filter->effect, - 0, 0); - } + obs_source_process_filter_end(filter->context, filter->effect, 0, 0); gs_blend_state_pop(); -} - -static void mask_filter_render_v1(void *data, gs_effect_t *effect) -{ - mask_filter_render_internal(data, false); - - UNUSED_PARAMETER(effect); -} - -static void mask_filter_render_v2(void *data, gs_effect_t *effect) -{ - mask_filter_render_internal(data, true); UNUSED_PARAMETER(effect); } @@ -360,14 +342,14 @@ struct obs_source_info mask_filter = { .get_defaults = mask_filter_defaults_v1, .get_properties = mask_filter_properties_v1, .video_tick = mask_filter_tick, - .video_render = mask_filter_render_v1, + .video_render = mask_filter_render, }; struct obs_source_info mask_filter_v2 = { .id = "mask_filter", .version = 2, .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = mask_filter_get_name, .create = mask_filter_create, .destroy = mask_filter_destroy, @@ -375,5 +357,5 @@ struct obs_source_info mask_filter_v2 = { .get_defaults = mask_filter_defaults_v2, .get_properties = mask_filter_properties_v2, .video_tick = mask_filter_tick, - .video_render = mask_filter_render_v2, + .video_render = mask_filter_render, }; diff --git a/plugins/obs-filters/scale-filter.c b/plugins/obs-filters/scale-filter.c index 75559a2d8..dd31c1106 100644 --- a/plugins/obs-filters/scale-filter.c +++ b/plugins/obs-filters/scale-filter.c @@ -297,9 +297,9 @@ static void scale_filter_render(void *data, gs_effect_t *effect) gs_effect_set_next_sampler(filter->image_param, filter->point_sampler); - obs_source_process_filter_tech_end_srgb(filter->context, filter->effect, - filter->cx_out, filter->cy_out, - technique); + obs_source_process_filter_tech_end(filter->context, filter->effect, + filter->cx_out, filter->cy_out, + technique); UNUSED_PARAMETER(effect); } @@ -422,7 +422,7 @@ static uint32_t scale_filter_height(void *data) struct obs_source_info scale_filter = { .id = "scale_filter", .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = scale_filter_name, .create = scale_filter_create, .destroy = scale_filter_destroy, diff --git a/plugins/obs-filters/scroll-filter.c b/plugins/obs-filters/scroll-filter.c index ba044dd31..7e91688db 100644 --- a/plugins/obs-filters/scroll-filter.c +++ b/plugins/obs-filters/scroll-filter.c @@ -221,8 +221,7 @@ static void scroll_filter_render(void *data, gs_effect_t *effect) gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); - obs_source_process_filter_end_srgb(filter->context, filter->effect, cx, - cy); + obs_source_process_filter_end(filter->context, filter->effect, cx, cy); gs_blend_state_pop(); @@ -257,7 +256,7 @@ static void scroll_filter_show(void *data) struct obs_source_info scroll_filter = { .id = "scroll_filter", .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = scroll_filter_get_name, .create = scroll_filter_create, .destroy = scroll_filter_destroy, diff --git a/plugins/obs-filters/sharpness-filter.c b/plugins/obs-filters/sharpness-filter.c index ae4f22b38..3ae1713b4 100644 --- a/plugins/obs-filters/sharpness-filter.c +++ b/plugins/obs-filters/sharpness-filter.c @@ -73,7 +73,7 @@ static void *sharpness_create(obs_data_t *settings, obs_source_t *context) return filter; } -static void sharpness_render_internal(void *data, bool srgb) +static void sharpness_render(void *data, gs_effect_t *effect) { struct sharpness_data *filter = data; @@ -93,22 +93,9 @@ static void sharpness_render_internal(void *data, bool srgb) gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); - obs_source_process_filter_end_srgb(filter->context, filter->effect, 0, - 0); + obs_source_process_filter_end(filter->context, filter->effect, 0, 0); gs_blend_state_pop(); -} - -static void sharpness_render_v1(void *data, gs_effect_t *effect) -{ - sharpness_render_internal(data, false); - - UNUSED_PARAMETER(effect); -} - -static void sharpness_render_v2(void *data, gs_effect_t *effect) -{ - sharpness_render_internal(data, true); UNUSED_PARAMETER(effect); } @@ -138,7 +125,7 @@ struct obs_source_info sharpness_filter = { .create = sharpness_create, .destroy = sharpness_destroy, .update = sharpness_update, - .video_render = sharpness_render_v1, + .video_render = sharpness_render, .get_properties = sharpness_properties, .get_defaults = sharpness_defaults, }; @@ -147,12 +134,12 @@ struct obs_source_info sharpness_filter_v2 = { .id = "sharpness_filter", .version = 2, .type = OBS_SOURCE_TYPE_FILTER, - .output_flags = OBS_SOURCE_VIDEO, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = sharpness_getname, .create = sharpness_create, .destroy = sharpness_destroy, .update = sharpness_update, - .video_render = sharpness_render_v2, + .video_render = sharpness_render, .get_properties = sharpness_properties, .get_defaults = sharpness_defaults, };