static inline void render_display_begin(struct obs_display *display) { struct vec4 clear_color; gs_load_swapchain(display ? display->swap : NULL); if (display->size_changed) { gs_resize(display->cx, display->cy); display->size_changed = false; } gs_beginscene(); vec4_set(&clear_color, 0.3f, 0.3f, 0.3f, 1.0f); gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL, &clear_color, 1.0f, 0); gs_enable_depthtest(false); /* gs_enable_blending(false); */ gs_setcullmode(GS_NEITHER); gs_ortho(0.0f, (float)display->cx, 0.0f, (float)display->cy, -100.0f, 100.0f); gs_setviewport(0, 0, display->cx, display->cy); }
void gs_set2dmode(void) { uint32_t cx, cy; gs_getsize(&cx, &cy); gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -1.0, -1024.0f); }
static inline void set_render_size(uint32_t width, uint32_t height) { gs_enable_depth_test(false); gs_set_cull_mode(GS_NEITHER); gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f, 100.0f); gs_set_viewport(0, 0, width, height); }
void gs_set2dmode(void) { uint32_t cx, cy; assert(thread_graphics != NULL); gs_getsize(&cx, &cy); gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -1.0, -1024.0f); }
static inline void startRegion(int vX, int vY, int vCX, int vCY, float oL, float oR, float oT, float oB) { gs_projection_push(); gs_viewport_push(); gs_set_viewport(vX, vY, vCX, vCY); gs_ortho(oL, oR, oT, oB, -100.0f, 100.0f); }
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; }
static inline void render_begin(struct obs_display *display) { struct vec4 clear_color; uint32_t width, height; gs_load_swapchain(display ? display->swap : NULL); gs_getsize(&width, &height); gs_beginscene(); vec4_set(&clear_color, 0.3f, 0.0f, 0.0f, 1.0f); gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL, &clear_color, 1.0f, 0); gs_enable_depthtest(false); /* gs_enable_blending(false); */ gs_setcullmode(GS_NEITHER); gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f, 100.0f); gs_setviewport(0, 0, width, height); }
void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy) { OBSProjector *window = reinterpret_cast<OBSProjector*>(data); uint32_t targetCX; uint32_t targetCY; int x, y; int newCX, newCY; float scale; if (window->source) { targetCX = std::max(obs_source_get_width(window->source), 1u); targetCY = std::max(obs_source_get_height(window->source), 1u); } else { struct obs_video_info ovi; obs_get_video_info(&ovi); targetCX = ovi.base_width; targetCY = ovi.base_height; } GetScaleAndCenterPos(targetCX, targetCY, cx, cy, x, y, scale); newCX = int(scale * float(targetCX)); newCY = int(scale * float(targetCY)); gs_viewport_push(); gs_projection_push(); gs_ortho(0.0f, float(targetCX), 0.0f, float(targetCY), -100.0f, 100.0f); gs_set_viewport(x, y, newCX, newCY); if (window->source) obs_source_video_render(window->source); else obs_render_main_view(); gs_projection_pop(); gs_viewport_pop(); }
static inline void render_item(struct obs_scene_item *item) { if (item->item_render) { uint32_t width = obs_source_get_width(item->source); uint32_t height = obs_source_get_height(item->source); uint32_t cx = calc_cx(item, width); uint32_t cy = calc_cy(item, height); if (cx && cy && gs_texrender_begin(item->item_render, cx, cy)) { float cx_scale = (float)width / (float)cx; float cy_scale = (float)height / (float)cy; struct vec4 clear_color; vec4_zero(&clear_color); gs_clear(GS_CLEAR_COLOR, &clear_color, 0.0f, 0); gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f, 100.0f); gs_matrix_scale3f(cx_scale, cy_scale, 1.0f); gs_matrix_translate3f( -(float)item->crop.left, -(float)item->crop.top, 0.0f); obs_source_video_render(item->source); gs_texrender_end(item->item_render); } } gs_matrix_push(); gs_matrix_mul(&item->draw_transform); if (item->item_render) { render_item_texture(item); } else { obs_source_video_render(item->source); } gs_matrix_pop(); }
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); }