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 inline bool set_async_texture_size(struct obs_source *source, struct source_frame *frame) { enum convert_type prev, cur; prev = get_convert_type(source->async_format); cur = get_convert_type(frame->format); if (source->async_texture) { if (source->async_width == frame->width && source->async_height == frame->height && prev == cur) return true; } texture_destroy(source->async_texture); texrender_destroy(source->async_convert_texrender); source->async_convert_texrender = NULL; if (cur != CONVERT_NONE && init_gpu_conversion(source, frame)) { source->async_gpu_conversion = true; source->async_convert_texrender = texrender_create(GS_RGBA, GS_ZS_NONE); source->async_texture = gs_create_texture( source->async_convert_width, source->async_convert_height, GS_RGBA, 1, NULL, GS_DYNAMIC); } else { source->async_gpu_conversion = false; source->async_texture = gs_create_texture( frame->width, frame->height, GS_RGBA, 1, NULL, GS_DYNAMIC); } if (!source->async_texture) return false; source->async_width = frame->width; source->async_height = frame->height; return true; }
struct test_filter *test_create(const char *settings, obs_source_t source) { struct test_filter *tf = bmalloc(sizeof(struct test_filter)); char *effect_file; memset(tf, 0, sizeof(struct test_filter)); gs_entercontext(obs_graphics()); effect_file = obs_find_plugin_file("test-input/test.effect"); tf->source = source; tf->whatever = gs_create_effect_from_file(effect_file, NULL); bfree(effect_file); if (!tf->whatever) { test_destroy(tf); return NULL; } tf->texrender = texrender_create(GS_RGBA, GS_ZS_NONE); gs_leavecontext(); return tf; }