static inline void obs_source_draw_texture(struct obs_source *source, effect_t effect, float *color_matrix, float const *color_range_min, float const *color_range_max) { texture_t tex = source->async_texture; eparam_t param; if (source->async_convert_texrender) tex = texrender_gettexture(source->async_convert_texrender); if (color_range_min) { size_t const size = sizeof(float) * 3; param = effect_getparambyname(effect, "color_range_min"); effect_setval(effect, param, color_range_min, size); } if (color_range_max) { size_t const size = sizeof(float) * 3; param = effect_getparambyname(effect, "color_range_max"); effect_setval(effect, param, color_range_max, size); } if (color_matrix) { param = effect_getparambyname(effect, "color_matrix"); effect_setval(effect, param, color_matrix, sizeof(float) * 16); } param = effect_getparambyname(effect, "image"); effect_settexture(effect, param, tex); gs_draw_sprite(tex, source->async_flip ? GS_FLIP_V : 0, 0, 0); }
void obs_source_process_filter(obs_source_t filter, effect_t effect, uint32_t width, uint32_t height, enum gs_color_format format, enum allow_direct_render allow_direct) { obs_source_t target, parent; uint32_t target_flags, parent_flags; int cx, cy; bool use_matrix, expects_def, can_directly; if (!filter) return; target = obs_filter_gettarget(filter); parent = obs_filter_getparent(filter); target_flags = target->info.output_flags; parent_flags = parent->info.output_flags; cx = obs_source_getwidth(target); cy = obs_source_getheight(target); use_matrix = !!(target_flags & OBS_SOURCE_COLOR_MATRIX); expects_def = !(parent_flags & OBS_SOURCE_CUSTOM_DRAW); can_directly = allow_direct == ALLOW_DIRECT_RENDERING; /* 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_directly && expects_def && target == parent) { render_filter_bypass(target, effect, use_matrix); return; } if (!filter->filter_texrender) filter->filter_texrender = texrender_create(format, GS_ZS_NONE); if (texrender_begin(filter->filter_texrender, cx, cy)) { gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -100.0f, 100.0f); if (expects_def && parent == target) obs_source_default_render(parent, use_matrix); else obs_source_video_render(target); texrender_end(filter->filter_texrender); } /* --------------------------- */ render_filter_tex(texrender_gettexture(filter->filter_texrender), effect, width, height, use_matrix); }
void obs_source_process_filter(obs_source_t filter, texrender_t texrender, effect_t effect, uint32_t width, uint32_t height, enum allow_direct_render allow_direct) { obs_source_t target = obs_filter_gettarget(filter); obs_source_t parent = obs_filter_getparent(filter); uint32_t target_flags = obs_source_get_output_flags(target); uint32_t parent_flags = obs_source_get_output_flags(parent); int cx = obs_source_getwidth(target); int cy = obs_source_getheight(target); bool yuv = (target_flags & SOURCE_YUV) != 0; bool expects_def = (parent_flags & SOURCE_DEFAULT_EFFECT) != 0; bool can_directly = allow_direct == ALLOW_DIRECT_RENDERING; /* 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_directly && expects_def && target == parent) { render_filter_bypass(target, effect, width, height, yuv); return; } if (texrender_begin(texrender, cx, cy)) { gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -100.0f, 100.0f); if (expects_def && parent == target) obs_source_default_render(parent, yuv); else obs_source_video_render(target); texrender_end(texrender); } /* --------------------------- */ render_filter_tex(texrender_gettexture(texrender), effect, width, height, yuv); }