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); }
static bool update_async_texrender(struct obs_source *source, const struct source_frame *frame) { texture_t tex = source->async_texture; texrender_t texrender = source->async_convert_texrender; texrender_reset(texrender); upload_raw_frame(tex, frame); uint32_t cx = source->async_width; uint32_t cy = source->async_height; effect_t conv = obs->video.conversion_effect; technique_t tech = effect_gettechnique(conv, select_conversion_technique(frame->format)); if (!texrender_begin(texrender, cx, cy)) return false; technique_begin(tech); technique_beginpass(tech, 0); effect_settexture(conv, effect_getparambyname(conv, "image"), tex); set_eparam(conv, "width", (float)cx); set_eparam(conv, "height", (float)cy); set_eparam(conv, "width_i", 1.0f / cx); set_eparam(conv, "height_i", 1.0f / cy); set_eparam(conv, "width_d2", cx * 0.5f); set_eparam(conv, "height_d2", cy * 0.5f); set_eparam(conv, "width_d2_i", 1.0f / (cx * 0.5f)); set_eparam(conv, "height_d2_i", 1.0f / (cy * 0.5f)); set_eparam(conv, "input_height", (float)cy); gs_ortho(0.f, (float)cx, 0.f, (float)cy, -100.f, 100.f); gs_draw_sprite(tex, 0, cx, cy); technique_endpass(tech); technique_end(tech); texrender_end(texrender); return true; }
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); }