|
@@ -921,124 +921,135 @@ static void uninit_winrt_state(struct winrt_state *winrt)
|
|
|
static const char *tick_sources_name = "tick_sources";
|
|
|
static const char *render_displays_name = "render_displays";
|
|
|
static const char *output_frame_name = "output_frame";
|
|
|
-void *obs_graphics_thread(void *param)
|
|
|
+bool obs_graphics_thread_loop(struct obs_graphics_context *context)
|
|
|
{
|
|
|
-#ifdef _WIN32
|
|
|
- struct winrt_state winrt;
|
|
|
- init_winrt_state(&winrt);
|
|
|
-#endif // #ifdef _WIN32
|
|
|
+ /* defer loop break to clean up sources */
|
|
|
+ const bool stop_requested = video_output_stopped(obs->video.video);
|
|
|
|
|
|
- uint64_t last_time = 0;
|
|
|
- uint64_t interval = video_output_get_frame_time(obs->video.video);
|
|
|
- uint64_t frame_time_total_ns = 0;
|
|
|
- uint64_t fps_total_ns = 0;
|
|
|
- uint32_t fps_total_frames = 0;
|
|
|
+ uint64_t frame_start = os_gettime_ns();
|
|
|
+ uint64_t frame_time_ns;
|
|
|
+ bool raw_active = obs->video.raw_active > 0;
|
|
|
#ifdef _WIN32
|
|
|
- bool gpu_was_active = false;
|
|
|
+ const bool gpu_active = obs->video.gpu_encoder_active > 0;
|
|
|
+ const bool active = raw_active || gpu_active;
|
|
|
+#else
|
|
|
+ const bool gpu_active = 0;
|
|
|
+ const bool active = raw_active;
|
|
|
#endif
|
|
|
- bool raw_was_active = false;
|
|
|
- bool was_active = false;
|
|
|
|
|
|
- is_graphics_thread = true;
|
|
|
+ if (!context->was_active && active)
|
|
|
+ clear_base_frame_data();
|
|
|
+ if (!context->raw_was_active && raw_active)
|
|
|
+ clear_raw_frame_data();
|
|
|
+#ifdef _WIN32
|
|
|
+ if (!context->gpu_was_active && gpu_active)
|
|
|
+ clear_gpu_frame_data();
|
|
|
|
|
|
- obs->video.video_time = os_gettime_ns();
|
|
|
- obs->video.video_frame_interval_ns = interval;
|
|
|
+ context->gpu_was_active = gpu_active;
|
|
|
+#endif
|
|
|
+ context->raw_was_active = raw_active;
|
|
|
+ context->was_active = active;
|
|
|
|
|
|
- os_set_thread_name("libobs: graphics thread");
|
|
|
+ profile_start(context->video_thread_name);
|
|
|
|
|
|
- const char *video_thread_name = profile_store_name(
|
|
|
- obs_get_profiler_name_store(),
|
|
|
- "obs_graphics_thread(%g" NBSP "ms)", interval / 1000000.);
|
|
|
- profile_register_root(video_thread_name, interval);
|
|
|
+ gs_enter_context(obs->video.graphics);
|
|
|
+ gs_begin_frame();
|
|
|
+ gs_leave_context();
|
|
|
|
|
|
- srand((unsigned int)time(NULL));
|
|
|
+ profile_start(tick_sources_name);
|
|
|
+ context->last_time =
|
|
|
+ tick_sources(obs->video.video_time, context->last_time);
|
|
|
+ profile_end(tick_sources_name);
|
|
|
|
|
|
- for (;;) {
|
|
|
- /* defer loop break to clean up sources */
|
|
|
- const bool stop_requested =
|
|
|
- video_output_stopped(obs->video.video);
|
|
|
+ execute_graphics_tasks();
|
|
|
|
|
|
- uint64_t frame_start = os_gettime_ns();
|
|
|
- uint64_t frame_time_ns;
|
|
|
- bool raw_active = obs->video.raw_active > 0;
|
|
|
#ifdef _WIN32
|
|
|
- const bool gpu_active = obs->video.gpu_encoder_active > 0;
|
|
|
- const bool active = raw_active || gpu_active;
|
|
|
-#else
|
|
|
- const bool gpu_active = 0;
|
|
|
- const bool active = raw_active;
|
|
|
+ MSG msg;
|
|
|
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
|
|
+ TranslateMessage(&msg);
|
|
|
+ DispatchMessage(&msg);
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
- if (!was_active && active)
|
|
|
- clear_base_frame_data();
|
|
|
- if (!raw_was_active && raw_active)
|
|
|
- clear_raw_frame_data();
|
|
|
-#ifdef _WIN32
|
|
|
- if (!gpu_was_active && gpu_active)
|
|
|
- clear_gpu_frame_data();
|
|
|
+ profile_start(output_frame_name);
|
|
|
+ output_frame(raw_active, gpu_active);
|
|
|
+ profile_end(output_frame_name);
|
|
|
|
|
|
- gpu_was_active = gpu_active;
|
|
|
-#endif
|
|
|
- raw_was_active = raw_active;
|
|
|
- was_active = active;
|
|
|
+ profile_start(render_displays_name);
|
|
|
+ render_displays();
|
|
|
+ profile_end(render_displays_name);
|
|
|
|
|
|
- profile_start(video_thread_name);
|
|
|
+ frame_time_ns = os_gettime_ns() - frame_start;
|
|
|
|
|
|
- gs_enter_context(obs->video.graphics);
|
|
|
- gs_begin_frame();
|
|
|
- gs_leave_context();
|
|
|
+ profile_end(context->video_thread_name);
|
|
|
|
|
|
- profile_start(tick_sources_name);
|
|
|
- last_time = tick_sources(obs->video.video_time, last_time);
|
|
|
- profile_end(tick_sources_name);
|
|
|
+ profile_reenable_thread();
|
|
|
|
|
|
- execute_graphics_tasks();
|
|
|
+ video_sleep(&obs->video, raw_active, gpu_active, &obs->video.video_time,
|
|
|
+ context->interval);
|
|
|
|
|
|
-#ifdef _WIN32
|
|
|
- MSG msg;
|
|
|
- while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
|
|
- TranslateMessage(&msg);
|
|
|
- DispatchMessage(&msg);
|
|
|
- }
|
|
|
-#endif
|
|
|
+ context->frame_time_total_ns += frame_time_ns;
|
|
|
+ context->fps_total_ns += (obs->video.video_time - context->last_time);
|
|
|
+ context->fps_total_frames++;
|
|
|
|
|
|
- profile_start(output_frame_name);
|
|
|
- output_frame(raw_active, gpu_active);
|
|
|
- profile_end(output_frame_name);
|
|
|
+ if (context->fps_total_ns >= 1000000000ULL) {
|
|
|
+ obs->video.video_fps =
|
|
|
+ (double)context->fps_total_frames /
|
|
|
+ ((double)context->fps_total_ns / 1000000000.0);
|
|
|
+ obs->video.video_avg_frame_time_ns =
|
|
|
+ context->frame_time_total_ns /
|
|
|
+ (uint64_t)context->fps_total_frames;
|
|
|
|
|
|
- profile_start(render_displays_name);
|
|
|
- render_displays();
|
|
|
- profile_end(render_displays_name);
|
|
|
+ context->frame_time_total_ns = 0;
|
|
|
+ context->fps_total_ns = 0;
|
|
|
+ context->fps_total_frames = 0;
|
|
|
+ }
|
|
|
|
|
|
- frame_time_ns = os_gettime_ns() - frame_start;
|
|
|
+ return !stop_requested;
|
|
|
+}
|
|
|
|
|
|
- profile_end(video_thread_name);
|
|
|
+void *obs_graphics_thread(void *param)
|
|
|
+{
|
|
|
+#ifdef _WIN32
|
|
|
+ struct winrt_state winrt;
|
|
|
+ init_winrt_state(&winrt);
|
|
|
+#endif // #ifdef _WIN32
|
|
|
|
|
|
- profile_reenable_thread();
|
|
|
+ is_graphics_thread = true;
|
|
|
|
|
|
- video_sleep(&obs->video, raw_active, gpu_active,
|
|
|
- &obs->video.video_time, interval);
|
|
|
+ const uint64_t interval = video_output_get_frame_time(obs->video.video);
|
|
|
|
|
|
- frame_time_total_ns += frame_time_ns;
|
|
|
- fps_total_ns += (obs->video.video_time - last_time);
|
|
|
- fps_total_frames++;
|
|
|
+ obs->video.video_time = os_gettime_ns();
|
|
|
+ obs->video.video_frame_interval_ns = interval;
|
|
|
|
|
|
- if (fps_total_ns >= 1000000000ULL) {
|
|
|
- obs->video.video_fps =
|
|
|
- (double)fps_total_frames /
|
|
|
- ((double)fps_total_ns / 1000000000.0);
|
|
|
- obs->video.video_avg_frame_time_ns =
|
|
|
- frame_time_total_ns /
|
|
|
- (uint64_t)fps_total_frames;
|
|
|
+ os_set_thread_name("libobs: graphics thread");
|
|
|
|
|
|
- frame_time_total_ns = 0;
|
|
|
- fps_total_ns = 0;
|
|
|
- fps_total_frames = 0;
|
|
|
- }
|
|
|
+ const char *video_thread_name = profile_store_name(
|
|
|
+ obs_get_profiler_name_store(),
|
|
|
+ "obs_graphics_thread(%g" NBSP "ms)", interval / 1000000.);
|
|
|
+ profile_register_root(video_thread_name, interval);
|
|
|
|
|
|
- if (stop_requested)
|
|
|
- break;
|
|
|
- }
|
|
|
+ srand((unsigned int)time(NULL));
|
|
|
+
|
|
|
+ struct obs_graphics_context context;
|
|
|
+ context.interval = video_output_get_frame_time(obs->video.video);
|
|
|
+ context.frame_time_total_ns = 0;
|
|
|
+ context.fps_total_ns = 0;
|
|
|
+ context.fps_total_frames = 0;
|
|
|
+ context.last_time = 0;
|
|
|
+#ifdef _WIN32
|
|
|
+ context.gpu_was_active = false;
|
|
|
+#endif
|
|
|
+ context.raw_was_active = false;
|
|
|
+ context.was_active = false;
|
|
|
+ context.video_thread_name = video_thread_name;
|
|
|
+
|
|
|
+#ifdef __APPLE__
|
|
|
+ while (obs_graphics_thread_loop_autorelease(&context))
|
|
|
+#else
|
|
|
+ while (obs_graphics_thread_loop(&context))
|
|
|
+#endif
|
|
|
+ ;
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
uninit_winrt_state(&winrt);
|