static inline void output_frame(uint64_t *cur_time, uint64_t interval) { struct obs_core_video *video = &obs->video; int cur_texture = video->cur_texture; int prev_texture = cur_texture == 0 ? NUM_TEXTURES-1 : cur_texture-1; struct video_data frame; bool frame_ready; memset(&frame, 0, sizeof(struct video_data)); gs_enter_context(video->graphics); render_video(video, cur_texture, prev_texture); frame_ready = download_frame(video, prev_texture, &frame); gs_flush(); gs_leave_context(); if (frame_ready) { struct obs_vframe_info vframe_info; circlebuf_pop_front(&video->vframe_info_buffer, &vframe_info, sizeof(vframe_info)); frame.timestamp = vframe_info.timestamp; output_video_data(video, &frame, vframe_info.count); } if (++video->cur_texture == NUM_TEXTURES) video->cur_texture = 0; video_sleep(video, cur_time, interval); }
static inline void render_video(struct obs_core_video *video, bool raw_active, const bool gpu_active, int cur_texture, int prev_texture) { gs_begin_scene(); gs_enable_depth_test(false); gs_set_cull_mode(GS_NEITHER); render_main_texture(video, cur_texture); if (raw_active || gpu_active) { render_output_texture(video, cur_texture, prev_texture); #ifdef _WIN32 if (gpu_active) { gs_flush(); } #endif } if (raw_active || gpu_active) { if (video->gpu_conversion) { if (video->using_nv12_tex) render_convert_texture_nv12(video, cur_texture, prev_texture); else render_convert_texture(video, cur_texture, prev_texture); } #ifdef _WIN32 if (gpu_active) { gs_flush(); output_gpu_encoders(video, raw_active, prev_texture); } #endif if (raw_active) stage_output_texture(video, cur_texture, prev_texture); } gs_set_render_target(NULL, NULL); gs_enable_blending(true); gs_end_scene(); }
static void gs_point(struct draw_geometry_shader *shader, int idx) { unsigned indices[1]; indices[0] = idx; draw_fetch_gs_input(shader, indices, 1, 0); ++shader->in_prim_idx; gs_flush(shader, 1); }
static void gs_line(struct draw_geometry_shader *shader, int i0, int i1) { unsigned indices[2]; indices[0] = i0; indices[1] = i1; draw_fetch_gs_input(shader, indices, 2, 0); ++shader->in_prim_idx; gs_flush(shader, 1); }
static void gs_tri(struct draw_geometry_shader *shader, int i0, int i1, int i2) { unsigned indices[3]; indices[0] = i0; indices[1] = i1; indices[2] = i2; draw_fetch_gs_input(shader, indices, 3, 0); ++shader->in_prim_idx; gs_flush(shader, 1); }
static void gs_point(struct draw_geometry_shader *shader, int idx) { unsigned indices[1]; indices[0] = idx; shader->fetch_inputs(shader, indices, 1, shader->fetched_prim_count); ++shader->in_prim_idx; ++shader->fetched_prim_count; if (draw_gs_should_flush(shader)) gs_flush(shader); }
static void gs_line_adj(struct draw_geometry_shader *shader, int i0, int i1, int i2, int i3) { unsigned indices[4]; indices[0] = i0; indices[1] = i1; indices[2] = i2; indices[3] = i3; draw_fetch_gs_input(shader, indices, 4, 0); ++shader->in_prim_idx; gs_flush(shader, 1); }
static void gs_line(struct draw_geometry_shader *shader, int i0, int i1) { unsigned indices[2]; indices[0] = i0; indices[1] = i1; shader->fetch_inputs(shader, indices, 2, shader->fetched_prim_count); ++shader->in_prim_idx; ++shader->fetched_prim_count; if (draw_gs_should_flush(shader)) gs_flush(shader); }
static inline void output_frame(bool raw_active, const bool gpu_active) { struct obs_core_video *video = &obs->video; int cur_texture = video->cur_texture; int prev_texture = cur_texture == 0 ? NUM_TEXTURES-1 : cur_texture-1; struct video_data frame; bool active = raw_active || gpu_active; bool frame_ready; memset(&frame, 0, sizeof(struct video_data)); profile_start(output_frame_gs_context_name); gs_enter_context(video->graphics); profile_start(output_frame_render_video_name); render_video(video, raw_active, gpu_active, cur_texture, prev_texture); profile_end(output_frame_render_video_name); if (raw_active) { profile_start(output_frame_download_frame_name); frame_ready = download_frame(video, prev_texture, &frame); profile_end(output_frame_download_frame_name); } profile_start(output_frame_gs_flush_name); gs_flush(); profile_end(output_frame_gs_flush_name); gs_leave_context(); profile_end(output_frame_gs_context_name); if (raw_active && frame_ready) { struct obs_vframe_info vframe_info; circlebuf_pop_front(&video->vframe_info_buffer, &vframe_info, sizeof(vframe_info)); frame.timestamp = vframe_info.timestamp; profile_start(output_frame_output_video_data_name); output_video_data(video, &frame, vframe_info.count); profile_end(output_frame_output_video_data_name); } if (++video->cur_texture == NUM_TEXTURES) video->cur_texture = 0; }
static void gs_line_adj(struct draw_geometry_shader *shader, int i0, int i1, int i2, int i3) { unsigned indices[4]; indices[0] = i0; indices[1] = i1; indices[2] = i2; indices[3] = i3; shader->fetch_inputs(shader, indices, 4, shader->fetched_prim_count); ++shader->in_prim_idx; ++shader->fetched_prim_count; if (draw_gs_should_flush(shader)) gs_flush(shader); }
static void gs_tri_adj(struct draw_geometry_shader *shader, int i0, int i1, int i2, int i3, int i4, int i5) { unsigned indices[6]; indices[0] = i0; indices[1] = i1; indices[2] = i2; indices[3] = i3; indices[4] = i4; indices[5] = i5; draw_fetch_gs_input(shader, indices, 6, 0); ++shader->in_prim_idx; gs_flush(shader, 1); }
/** * Execute geometry shader. */ int draw_geometry_shader_run(struct draw_geometry_shader *shader, const void *constants[PIPE_MAX_CONSTANT_BUFFERS], const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS], const struct draw_vertex_info *input_verts, const struct draw_prim_info *input_prim, const struct tgsi_shader_info *input_info, struct draw_vertex_info *output_verts, struct draw_prim_info *output_prims ) { const float (*input)[4] = (const float (*)[4])input_verts->verts->data; unsigned input_stride = input_verts->vertex_size; unsigned num_outputs = draw_total_gs_outputs(shader->draw); unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float); unsigned num_input_verts = input_prim->linear ? input_verts->count : input_prim->count; unsigned num_in_primitives = align( MAX2(u_decomposed_prims_for_vertices(input_prim->prim, num_input_verts), u_decomposed_prims_for_vertices(shader->input_primitive, num_input_verts)), shader->vector_length); unsigned max_out_prims = u_decomposed_prims_for_vertices(shader->output_primitive, shader->max_output_vertices) * num_in_primitives; //Assume at least one primitive max_out_prims = MAX2(max_out_prims, 1); output_verts->vertex_size = vertex_size; output_verts->stride = output_verts->vertex_size; /* we allocate exactly one extra vertex per primitive to allow the GS to emit * overflown vertices into some area where they won't harm anyone */ output_verts->verts = (struct vertex_header *)MALLOC(output_verts->vertex_size * max_out_prims * shader->primitive_boundary); #if 0 debug_printf("%s count = %d (in prims # = %d)\n", __FUNCTION__, num_input_verts, num_in_primitives); debug_printf("\tlinear = %d, prim_info->count = %d\n", input_prim->linear, input_prim->count); debug_printf("\tprim pipe = %s, shader in = %s, shader out = %s, max out = %d\n", u_prim_name(input_prim->prim), u_prim_name(shader->input_primitive), u_prim_name(shader->output_primitive), shader->max_output_vertices); #endif shader->emitted_vertices = 0; shader->emitted_primitives = 0; shader->vertex_size = vertex_size; shader->tmp_output = (float (*)[4])output_verts->verts->data; shader->fetched_prim_count = 0; shader->input_vertex_stride = input_stride; shader->input = input; shader->input_info = input_info; FREE(shader->primitive_lengths); shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned)); #ifdef HAVE_LLVM if (draw_get_option_use_llvm()) { shader->gs_output = output_verts->verts; if (max_out_prims > shader->max_out_prims) { unsigned i; if (shader->llvm_prim_lengths) { for (i = 0; i < shader->max_out_prims; ++i) { align_free(shader->llvm_prim_lengths[i]); } FREE(shader->llvm_prim_lengths); } shader->llvm_prim_lengths = MALLOC(max_out_prims * sizeof(unsigned*)); for (i = 0; i < max_out_prims; ++i) { int vector_size = shader->vector_length * sizeof(unsigned); shader->llvm_prim_lengths[i] = align_malloc(vector_size, vector_size); } shader->max_out_prims = max_out_prims; } shader->jit_context->prim_lengths = shader->llvm_prim_lengths; shader->jit_context->emitted_vertices = shader->llvm_emitted_vertices; shader->jit_context->emitted_prims = shader->llvm_emitted_primitives; } #endif shader->prepare(shader, constants, constants_size); if (input_prim->linear) gs_run(shader, input_prim, input_verts, output_prims, output_verts); else gs_run_elts(shader, input_prim, input_verts, output_prims, output_verts); /* Flush the remaining primitives. Will happen if * num_input_primitives % 4 != 0 */ if (shader->fetched_prim_count > 0) { gs_flush(shader); } debug_assert(shader->fetched_prim_count == 0); /* Update prim_info: */ output_prims->linear = TRUE; output_prims->elts = NULL; output_prims->start = 0; output_prims->count = shader->emitted_vertices; output_prims->prim = shader->output_primitive; output_prims->flags = 0x0; output_prims->primitive_lengths = shader->primitive_lengths; output_prims->primitive_count = shader->emitted_primitives; output_verts->count = shader->emitted_vertices; if (shader->draw->collect_statistics) { unsigned i; for (i = 0; i < shader->emitted_primitives; ++i) { shader->draw->statistics.gs_primitives += u_decomposed_prims_for_vertices(shader->output_primitive, shader->primitive_lengths[i]); } } #if 0 debug_printf("GS finished, prims = %d, verts = %d\n", output_prims->primitive_count, output_verts->count); #endif return shader->emitted_vertices; }