libobs: WinRT and dispatcher init on graphics thread

Suspected necessary for WGC stability.
This commit is contained in:
jpark37 2020-05-21 00:23:26 -07:00
parent 49bc89f2b2
commit 5734ab7a9b

View file

@ -539,7 +539,7 @@ static const uint8_t *set_gpu_converted_plane(uint32_t width, uint32_t height,
const uint8_t *in, uint8_t *out)
{
if ((width == linesize_input) && (width == linesize_output)) {
size_t total = width * height;
size_t total = (size_t)width * (size_t)height;
memcpy(out, in, total);
in += total;
} else {
@ -672,10 +672,12 @@ static inline void copy_rgbx_frame(struct video_frame *output,
/* if the line sizes match, do a single copy */
if (input->linesize[0] == output->linesize[0]) {
memcpy(out_ptr, in_ptr, input->linesize[0] * info->height);
memcpy(out_ptr, in_ptr,
(size_t)input->linesize[0] * (size_t)info->height);
} else {
const size_t copy_size = (size_t)info->width * 4;
for (size_t y = 0; y < info->height; y++) {
memcpy(out_ptr, in_ptr, info->width * 4);
memcpy(out_ptr, in_ptr, copy_size);
in_ptr += input->linesize[0];
out_ptr += output->linesize[0];
}
@ -835,11 +837,97 @@ static void execute_graphics_tasks(void)
}
}
#ifdef _WIN32
struct winrt_exports {
void (*winrt_initialize)();
void (*winrt_uninitialize)();
struct winrt_disaptcher *(*winrt_dispatcher_init)();
void (*winrt_dispatcher_free)(struct winrt_disaptcher *dispatcher);
void (*winrt_capture_thread_start)();
void (*winrt_capture_thread_stop)();
};
#define WINRT_IMPORT(func) \
do { \
exports->func = os_dlsym(module, #func); \
if (!exports->func) { \
success = false; \
blog(LOG_ERROR, \
"Could not load function '%s' from " \
"module '%s'", \
#func, module_name); \
} \
} while (false)
static bool load_winrt_imports(struct winrt_exports *exports, void *module,
const char *module_name)
{
bool success = true;
WINRT_IMPORT(winrt_initialize);
WINRT_IMPORT(winrt_uninitialize);
WINRT_IMPORT(winrt_dispatcher_init);
WINRT_IMPORT(winrt_dispatcher_free);
WINRT_IMPORT(winrt_capture_thread_start);
WINRT_IMPORT(winrt_capture_thread_stop);
return success;
}
struct winrt_state {
bool loaded;
void *winrt_module;
struct winrt_exports exports;
struct winrt_disaptcher *dispatcher;
};
static void init_winrt_state(struct winrt_state *winrt)
{
static const char *const module_name = "libobs-winrt";
winrt->winrt_module = os_dlopen(module_name);
winrt->loaded = winrt->winrt_module &&
load_winrt_imports(&winrt->exports, winrt->winrt_module,
module_name);
winrt->dispatcher = NULL;
if (winrt->loaded) {
winrt->exports.winrt_initialize();
winrt->dispatcher = winrt->exports.winrt_dispatcher_init();
gs_enter_context(obs->video.graphics);
winrt->exports.winrt_capture_thread_start();
gs_leave_context();
}
}
static void uninit_winrt_state(struct winrt_state *winrt)
{
if (winrt->winrt_module) {
if (winrt->loaded) {
winrt->exports.winrt_capture_thread_stop();
if (winrt->dispatcher)
winrt->exports.winrt_dispatcher_free(
winrt->dispatcher);
winrt->exports.winrt_uninitialize();
}
os_dlclose(winrt->winrt_module);
}
}
#endif // #ifdef _WIN32
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)
{
#ifdef _WIN32
struct winrt_state winrt;
init_winrt_state(&winrt);
#endif // #ifdef _WIN32
uint64_t last_time = 0;
uint64_t interval = video_output_get_frame_time(obs->video.video);
uint64_t frame_time_total_ns = 0;
@ -952,6 +1040,10 @@ void *obs_graphics_thread(void *param)
break;
}
#ifdef _WIN32
uninit_winrt_state(&winrt);
#endif
UNUSED_PARAMETER(param);
return NULL;
}