diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt index c0132e6dd..3c98f4283 100644 --- a/libobs/CMakeLists.txt +++ b/libobs/CMakeLists.txt @@ -142,6 +142,7 @@ set(libobs_libobs_SOURCES obs-data.c obs-module.c obs-display.c + obs-viewport.c obs-scene.c obs-video.c) set(libobs_libobs_HEADERS diff --git a/libobs/obs-display.c b/libobs/obs-display.c index ba96f84e8..bec70665a 100644 --- a/libobs/obs-display.c +++ b/libobs/obs-display.c @@ -15,64 +15,156 @@ along with this program. If not, see . ******************************************************************************/ +#include "graphics/vec4.h" #include "obs.h" #include "obs-internal.h" +bool obs_display_init(struct obs_display *display, + struct gs_init_data *graphics_data) +{ + pthread_mutex_init_value(&display->draw_callbacks_mutex); + + if (graphics_data) { + display->swap = gs_create_swapchain(graphics_data); + if (!display->swap) { + blog(LOG_ERROR, "obs_display_init: Failed to " + "create swap chain"); + return false; + } + + display->cx = graphics_data->cx; + display->cy = graphics_data->cy; + } + + if (pthread_mutex_init(&display->draw_callbacks_mutex, NULL) != 0) { + blog(LOG_ERROR, "obs_display_init: Failed to create mutex"); + return false; + } + + return true; +} + obs_display_t obs_display_create(struct gs_init_data *graphics_data) { struct obs_display *display = bzalloc(sizeof(struct obs_display)); - if (graphics_data) { - display->swap = gs_create_swapchain(graphics_data); - if (!display->swap) { - obs_display_destroy(display); - return NULL; - } + if (!obs_display_init(display, graphics_data)) { + obs_display_destroy(display); + display = NULL; } return display; } +void obs_display_free(obs_display_t display) +{ + pthread_mutex_destroy(&display->draw_callbacks_mutex); + da_free(display->draw_callbacks); + + if (display->swap) { + swapchain_destroy(display->swap); + display->swap = NULL; + } +} + void obs_display_destroy(obs_display_t display) { if (display) { - size_t i; - pthread_mutex_lock(&obs->data.displays_mutex); da_erase_item(obs->data.displays, &display); pthread_mutex_unlock(&obs->data.displays_mutex); - for (i = 0; i < MAX_CHANNELS; i++) - obs_source_release(display->channels[i]); - - swapchain_destroy(display->swap); + obs_display_free(display); bfree(display); } } -obs_source_t obs_display_getsource(obs_display_t display, uint32_t channel) +void obs_display_resize(obs_display_t display, uint32_t cx, uint32_t cy) { - obs_source_t source; - assert(channel < MAX_CHANNELS); + if (!display) return; - source = display->channels[channel]; - if (source) - obs_source_addref(source); + pthread_mutex_lock(&display->draw_callbacks_mutex); - return source; + display->cx = cx; + display->cy = cy; + display->size_changed = true; + + pthread_mutex_unlock(&display->draw_callbacks_mutex); } -void obs_display_setsource(obs_display_t display, uint32_t channel, - obs_source_t source) +void obs_display_add_draw_callback(obs_display_t display, + void (*draw)(void *param, uint32_t cx, uint32_t cy), + void *param) { - struct obs_source *prev_source; - assert(channel < MAX_CHANNELS); + if (!display) return; - prev_source = display->channels[channel]; - display->channels[channel] = source; + struct draw_callback data = {draw, param}; - if (source) - obs_source_addref(source); - if (prev_source) - obs_source_release(prev_source); + pthread_mutex_lock(&display->draw_callbacks_mutex); + da_push_back(display->draw_callbacks, &data); + pthread_mutex_unlock(&display->draw_callbacks_mutex); +} + +void obs_display_remove_draw_callback(obs_display_t display, + void (*draw)(void *param, uint32_t cx, uint32_t cy), + void *param) +{ + if (!display) return; + + struct draw_callback data = {draw, param}; + + pthread_mutex_lock(&display->draw_callbacks_mutex); + da_erase_item(display->draw_callbacks, &data); + pthread_mutex_unlock(&display->draw_callbacks_mutex); +} + +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.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)obs->video.base_width, + 0.0f, (float)obs->video.base_height, -100.0f, 100.0f); + gs_setviewport(0, 0, display->cx, display->cy); +} + +static inline void render_display_end(struct obs_display *display) +{ + gs_endscene(); + gs_present(); +} + +void render_display(struct obs_display *display) +{ + if (!display) return; + + render_display_begin(display); + + pthread_mutex_lock(&display->draw_callbacks_mutex); + + for (size_t i = 0; i < display->draw_callbacks.num; i++) { + struct draw_callback *callback; + callback = display->draw_callbacks.array+i; + + callback->draw(callback->param, display->cx, display->cy); + } + + pthread_mutex_unlock(&display->draw_callbacks_mutex); + + render_display_end(display); } diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index d704bb789..883e84b1e 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -35,8 +35,13 @@ #define NUM_TEXTURES 2 +struct draw_callback { + void (*draw)(void *param, uint32_t cx, uint32_t cy); + void *param; +}; + /* ------------------------------------------------------------------------- */ -/* core */ +/* modules */ struct obs_module { char *name; @@ -46,51 +51,82 @@ struct obs_module { extern void free_module(struct obs_module *mod); +/* ------------------------------------------------------------------------- */ +/* viewports */ + +struct obs_viewport { + pthread_mutex_t channels_mutex; + obs_source_t channels[MAX_CHANNELS]; +}; + +extern bool obs_viewport_init(struct obs_viewport *viewport); +extern void obs_viewport_free(struct obs_viewport *viewport); + + +/* ------------------------------------------------------------------------- */ +/* displays */ + +struct obs_display { + bool size_changed; + uint32_t cx, cy; + swapchain_t swap; + pthread_mutex_t draw_callbacks_mutex; + DARRAY(struct draw_callback) draw_callbacks; +}; + +extern bool obs_display_init(struct obs_display *display, + struct gs_init_data *graphics_data); +extern void obs_display_free(struct obs_display *display); + + /* ------------------------------------------------------------------------- */ /* core */ struct obs_core_video { - graphics_t graphics; - stagesurf_t copy_surfaces[NUM_TEXTURES]; - texture_t render_textures[NUM_TEXTURES]; - texture_t output_textures[NUM_TEXTURES]; - bool textures_rendered[NUM_TEXTURES]; - bool textures_output[NUM_TEXTURES]; - bool textures_copied[NUM_TEXTURES]; - struct source_frame convert_frames[NUM_TEXTURES]; - effect_t default_effect; - stagesurf_t mapped_surface; - int cur_texture; + graphics_t graphics; + stagesurf_t copy_surfaces[NUM_TEXTURES]; + texture_t render_textures[NUM_TEXTURES]; + texture_t output_textures[NUM_TEXTURES]; + bool textures_rendered[NUM_TEXTURES]; + bool textures_output[NUM_TEXTURES]; + bool textures_copied[NUM_TEXTURES]; + struct source_frame convert_frames[NUM_TEXTURES]; + effect_t default_effect; + stagesurf_t mapped_surface; + int cur_texture; - video_t video; - pthread_t video_thread; - bool thread_initialized; + video_t video; + pthread_t video_thread; + bool thread_initialized; - uint32_t base_width; - uint32_t base_height; + uint32_t base_width; + uint32_t base_height; + + struct obs_display main_display; }; struct obs_core_audio { /* TODO: sound output subsystem */ - audio_t audio; + audio_t audio; }; /* user sources, output channels, and displays */ struct obs_core_data { /* arrays of pointers jim? you should really stop being lazy and use * linked lists. */ - DARRAY(struct obs_display*) displays; - DARRAY(struct obs_source*) sources; - DARRAY(struct obs_output*) outputs; - DARRAY(struct obs_encoder*) encoders; + DARRAY(struct obs_display*) displays; + DARRAY(struct obs_source*) sources; + DARRAY(struct obs_output*) outputs; + DARRAY(struct obs_encoder*) encoders; - obs_source_t channels[MAX_CHANNELS]; - pthread_mutex_t sources_mutex; - pthread_mutex_t displays_mutex; - pthread_mutex_t outputs_mutex; - pthread_mutex_t encoders_mutex; + pthread_mutex_t sources_mutex; + pthread_mutex_t displays_mutex; + pthread_mutex_t outputs_mutex; + pthread_mutex_t encoders_mutex; - volatile bool valid; + struct obs_viewport main_viewport; + + volatile bool valid; }; struct obs_core { @@ -119,68 +155,57 @@ extern struct obs_core *obs; extern void *obs_video_thread(void *param); -/* ------------------------------------------------------------------------- */ -/* displays */ - -struct obs_display { - swapchain_t swap; /* can be NULL if just sound */ - obs_source_t channels[MAX_CHANNELS]; - - /* TODO: sound output target */ -}; - - /* ------------------------------------------------------------------------- */ /* sources */ struct obs_source { - volatile int refs; - struct obs_source_info info; + volatile int refs; + struct obs_source_info info; /* source-specific data */ - char *name; /* user-defined name */ - enum obs_source_type type; - obs_data_t settings; - void *data; + char *name; /* user-defined name */ + enum obs_source_type type; + obs_data_t settings; + void *data; - signal_handler_t signals; - proc_handler_t procs; + signal_handler_t signals; + proc_handler_t procs; /* used to indicate that the source has been removed and all * references to it should be released (not exactly how I would prefer * to handle things but it's the best option) */ - bool removed; + bool removed; /* timing (if video is present, is based upon video) */ - volatile bool timing_set; - volatile uint64_t timing_adjust; - volatile int audio_reset_ref; - uint64_t next_audio_ts_min; - uint64_t last_frame_ts; - uint64_t last_sys_timestamp; + volatile bool timing_set; + volatile uint64_t timing_adjust; + volatile int audio_reset_ref; + uint64_t next_audio_ts_min; + uint64_t last_frame_ts; + uint64_t last_sys_timestamp; /* audio */ - bool audio_failed; - struct resample_info sample_info; - audio_resampler_t resampler; - audio_line_t audio_line; - pthread_mutex_t audio_mutex; - struct filtered_audio audio_data; - size_t audio_storage_size; - float volume; + bool audio_failed; + struct resample_info sample_info; + audio_resampler_t resampler; + audio_line_t audio_line; + pthread_mutex_t audio_mutex; + struct filtered_audio audio_data; + size_t audio_storage_size; + float volume; /* async video data */ - texture_t output_texture; - DARRAY(struct source_frame*) video_frames; - pthread_mutex_t video_mutex; + texture_t output_texture; + DARRAY(struct source_frame*) video_frames; + pthread_mutex_t video_mutex; /* filters */ - struct obs_source *filter_parent; - struct obs_source *filter_target; - DARRAY(struct obs_source*) filters; - pthread_mutex_t filter_mutex; - texrender_t filter_texrender; - bool rendering_filter; + struct obs_source *filter_parent; + struct obs_source *filter_target; + DARRAY(struct obs_source*) filters; + pthread_mutex_t filter_mutex; + texrender_t filter_texrender; + bool rendering_filter; }; bool obs_source_init_handlers(struct obs_source *source); @@ -196,27 +221,27 @@ extern void obs_source_video_tick(obs_source_t source, float seconds); /* outputs */ struct obs_output { - char *name; - void *data; - struct obs_output_info info; - obs_data_t settings; + char *name; + void *data; + struct obs_output_info info; + obs_data_t settings; }; /* ------------------------------------------------------------------------- */ /* encoders */ -struct obs_encoder_callback { +struct encoder_callback { void (*new_packet)(void *param, struct encoder_packet *packet); void *param; }; struct obs_encoder { - char *name; - void *data; - struct obs_encoder_info info; - obs_data_t settings; + char *name; + void *data; + struct obs_encoder_info info; + obs_data_t settings; - pthread_mutex_t data_callbacks_mutex; - DARRAY(struct obs_encoder_callback) data_callbacks; + pthread_mutex_t data_callbacks_mutex; + DARRAY(struct encoder_callback) data_callbacks; }; diff --git a/libobs/obs-video.c b/libobs/obs-video.c index dfd2f1cb2..b2d085e5f 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -1,5 +1,5 @@ /****************************************************************************** - Copyright (C) 2013 by Hugh Bailey + Copyright (C) 2013-2014 by Hugh Bailey This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,57 +37,8 @@ static void tick_sources(uint64_t cur_time, uint64_t *last_time) *last_time = cur_time; } -static inline void render_display_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)obs->video.base_width, - 0.0f, (float)obs->video.base_height, -100.0f, 100.0f); - gs_setviewport(0, 0, width, height); -} - -static inline void render_display_end(struct obs_display *display) -{ - gs_endscene(); - gs_present(); -} - -static void render_display(struct obs_display *display) -{ - render_display_begin(display); - - for (size_t i = 0; i < MAX_CHANNELS; i++) { - struct obs_source **p_source; - - p_source = (display) ? display->channels+i : - obs->data.channels+i; - - if (*p_source) { - if ((*p_source)->removed) { - obs_source_release(*p_source); - *p_source = NULL; - } else { - obs_source_video_render(*p_source); - } - } - } - - render_display_end(display); -} +/* in obs-display.c */ +extern void render_display(struct obs_display *display); static inline void render_displays(void) { @@ -105,7 +56,7 @@ static inline void render_displays(void) pthread_mutex_unlock(&obs->data.displays_mutex); /* render main display */ - render_display(NULL); + render_display(&obs->video.main_display); gs_leavecontext(); } @@ -119,17 +70,6 @@ static inline void set_render_size(uint32_t width, uint32_t height) gs_setviewport(0, 0, width, height); } -static inline void render_channels(void) -{ - struct obs_core_data *data = &obs->data; - - for (size_t i = 0; i < MAX_CHANNELS; i++) { - struct obs_source *source = data->channels[i]; - if (source) - obs_source_video_render(source); - } -} - static inline void unmap_last_surface(struct obs_core_video *video) { if (video->mapped_surface) { @@ -148,7 +88,7 @@ static inline void render_main_texture(struct obs_core_video *video, gs_clear(GS_CLEAR_COLOR, &clear_color, 1.0f, 0); set_render_size(video->base_width, video->base_height); - render_channels(); + obs_viewport_render(&obs->data.main_viewport); video->textures_rendered[cur_texture] = true; } diff --git a/libobs/obs-viewport.c b/libobs/obs-viewport.c new file mode 100644 index 000000000..f8714eae8 --- /dev/null +++ b/libobs/obs-viewport.c @@ -0,0 +1,126 @@ +/****************************************************************************** + Copyright (C) 2014 by Hugh Bailey + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#include "obs.h" +#include "obs-internal.h" + +bool obs_viewport_init(struct obs_viewport *viewport) +{ + pthread_mutex_init_value(&viewport->channels_mutex); + + if (pthread_mutex_init(&viewport->channels_mutex, NULL) != 0) { + blog(LOG_ERROR, "obs_viewport_init: Failed to create mutex"); + return false; + } + + return true; +} + +obs_viewport_t obs_viewport_create(void) +{ + struct obs_viewport *viewport = bzalloc(sizeof(struct obs_viewport)); + + if (!obs_viewport_init(viewport)) { + bfree(viewport); + viewport = NULL; + } + + return viewport; +} + +void obs_viewport_free(struct obs_viewport *viewport) +{ + for (size_t i = 0; i < MAX_CHANNELS; i++) + obs_source_release(viewport->channels[i]); + + memset(viewport->channels, 0, sizeof(viewport->channels)); + pthread_mutex_destroy(&viewport->channels_mutex); +} + +void obs_viewport_destroy(obs_viewport_t viewport) +{ + if (viewport) { + obs_viewport_free(viewport); + bfree(viewport); + } +} + +obs_source_t obs_viewport_getsource(obs_viewport_t viewport, uint32_t channel) +{ + obs_source_t source; + assert(channel < MAX_CHANNELS); + + if (!viewport) return NULL; + if (channel >= MAX_CHANNELS) return NULL; + + pthread_mutex_lock(&viewport->channels_mutex); + + source = viewport->channels[channel]; + if (source) + obs_source_addref(source); + + pthread_mutex_unlock(&viewport->channels_mutex); + + return source; +} + +void obs_viewport_setsource(obs_viewport_t viewport, uint32_t channel, + obs_source_t source) +{ + struct obs_source *prev_source; + + assert(channel < MAX_CHANNELS); + + if (!viewport) return; + if (channel >= MAX_CHANNELS) return; + + pthread_mutex_lock(&viewport->channels_mutex); + + prev_source = viewport->channels[channel]; + viewport->channels[channel] = source; + + if (source) + obs_source_addref(source); + if (prev_source) + obs_source_release(prev_source); + + pthread_mutex_unlock(&viewport->channels_mutex); +} + +void obs_viewport_render(obs_viewport_t viewport) +{ + if (!viewport) return; + + pthread_mutex_lock(&viewport->channels_mutex); + + for (size_t i = 0; i < MAX_CHANNELS; i++) { + struct obs_source *source; + + source = viewport->channels[i]; + + if (source) { + if (source->removed) { + obs_source_release(source); + viewport->channels[i] = NULL; + } else { + obs_source_video_render(source); + } + } + } + + pthread_mutex_unlock(&viewport->channels_mutex); +} diff --git a/libobs/obs.c b/libobs/obs.c index 3f51ab565..8a9ed95d4 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -1,5 +1,5 @@ /****************************************************************************** - Copyright (C) 2013 by Hugh Bailey + Copyright (C) 2013-2014 by Hugh Bailey This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -140,6 +140,12 @@ static bool obs_init_video(struct obs_video_info *ovi) return false; } + if (!obs_display_init(&video->main_display, NULL)) + return false; + + video->main_display.cx = ovi->window_width; + video->main_display.cy = ovi->window_height; + errorcode = pthread_create(&video->video_thread, NULL, obs_video_thread, obs); if (errorcode != 0) @@ -149,25 +155,33 @@ static bool obs_init_video(struct obs_video_info *ovi) return true; } -static void obs_free_video() +static void stop_video(void) { struct obs_core_video *video = &obs->video; + void *thread_retval; if (video->video) { - void *thread_retval; - video_output_stop(video->video); if (video->thread_initialized) { pthread_join(video->video_thread, &thread_retval); video->thread_initialized = false; } + } +} + +static void obs_free_video(void) +{ + struct obs_core_video *video = &obs->video; + + if (video->video) { + obs_display_free(&video->main_display); video_output_close(video->video); video->video = NULL; } } -static void obs_free_graphics() +static void obs_free_graphics(void) { struct obs_core_video *video = &obs->video; size_t i; @@ -248,6 +262,8 @@ static bool obs_init_data(void) goto fail; if (pthread_mutex_init(&data->encoders_mutex, &attr) != 0) goto fail; + if (!obs_viewport_init(&data->main_viewport)) + goto fail; data->valid = true; @@ -263,8 +279,7 @@ static void obs_free_data(void) data->valid = false; - for (i = 0; i < MAX_CHANNELS; i++) - obs_set_output_source(i, NULL); + obs_viewport_free(&data->main_viewport); while (data->outputs.num) obs_output_destroy(data->outputs.array[0]); @@ -303,7 +318,7 @@ static bool obs_init(void) return obs_init_handlers(); } -bool obs_startup() +bool obs_startup(void) { bool success; @@ -334,6 +349,8 @@ void obs_shutdown(void) da_free(obs->modal_ui_callbacks); da_free(obs->modeless_ui_callbacks); + stop_video(); + obs_free_data(); obs_free_video(); obs_free_graphics(); @@ -349,6 +366,11 @@ void obs_shutdown(void) obs = NULL; } +bool obs_initialized(void) +{ + return obs != NULL; +} + bool obs_reset_video(struct obs_video_info *ovi) { struct obs_core_video *video = &obs->video; @@ -535,21 +557,23 @@ bool obs_add_source(obs_source_t source) obs_source_t obs_get_output_source(uint32_t channel) { - struct obs_source *source; - assert(channel < MAX_CHANNELS); - source = obs->data.channels[channel]; - - obs_source_addref(source); - return source; + return obs_viewport_getsource(&obs->data.main_viewport, channel); } void obs_set_output_source(uint32_t channel, obs_source_t source) { - struct obs_source *prev_source; - struct calldata params = {0}; assert(channel < MAX_CHANNELS); - prev_source = obs->data.channels[channel]; + if (!obs) return; + if (channel >= MAX_CHANNELS) return; + + struct obs_source *prev_source; + struct obs_viewport *viewport = &obs->data.main_viewport; + struct calldata params = {0}; + + pthread_mutex_lock(&viewport->channels_mutex); + + prev_source = viewport->channels[channel]; calldata_setuint32(¶ms, "channel", channel); calldata_setptr(¶ms, "prev_source", prev_source); @@ -558,14 +582,14 @@ void obs_set_output_source(uint32_t channel, obs_source_t source) calldata_getptr(¶ms, "source", &source); calldata_free(¶ms); - obs->data.channels[channel] = source; + viewport->channels[channel] = source; - if (source != prev_source) { - if (source) - obs_source_addref(source); - if (prev_source) - obs_source_release(prev_source); - } + if (source) + obs_source_addref(source); + if (prev_source) + obs_source_release(prev_source); + + pthread_mutex_unlock(&viewport->channels_mutex); } void obs_enum_outputs(bool (*enum_proc)(void*, obs_output_t), void *param) @@ -630,15 +654,48 @@ obs_source_t obs_get_source_by_name(const char *name) effect_t obs_get_default_effect(void) { + if (!obs) return NULL; return obs->video.default_effect; } signal_handler_t obs_signalhandler(void) { + if (!obs) return NULL; return obs->signals; } proc_handler_t obs_prochandler(void) { + if (!obs) return NULL; return obs->procs; } + +void obs_add_draw_callback( + void (*draw)(void *param, uint32_t cx, uint32_t cy), + void *param) +{ + if (!obs) return; + + obs_display_add_draw_callback(&obs->video.main_display, draw, param); +} + +void obs_remove_draw_callback( + void (*draw)(void *param, uint32_t cx, uint32_t cy), + void *param) +{ + if (!obs) return; + + obs_display_remove_draw_callback(&obs->video.main_display, draw, param); +} + +void obs_resize(uint32_t cx, uint32_t cy) +{ + if (!obs || !obs->video.video || !obs->video.graphics) return; + obs_display_resize(&obs->video.main_display, cx, cy); +} + +void obs_render_main_viewport(void) +{ + if (!obs) return; + obs_viewport_render(&obs->data.main_viewport); +} diff --git a/libobs/obs.h b/libobs/obs.h index 07e5cb96e..4377200c2 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -33,6 +33,7 @@ /* opaque types */ struct obs_display; +struct obs_viewport; struct obs_source; struct obs_scene; struct obs_scene_item; @@ -41,6 +42,7 @@ struct obs_encoder; struct obs_service; typedef struct obs_display *obs_display_t; +typedef struct obs_viewport *obs_viewport_t; typedef struct obs_source *obs_source_t; typedef struct obs_scene *obs_scene_t; typedef struct obs_scene_item *obs_sceneitem_t; @@ -189,6 +191,9 @@ EXPORT bool obs_startup(void); /** Releases all data associated with OBS and terminates the OBS context */ EXPORT void obs_shutdown(void); +/** @return true if the main OBS context has been initialized */ +EXPORT bool obs_initialized(void); + /** * Sets base video ouput base resolution/fps/format * @@ -250,10 +255,13 @@ EXPORT bool obs_enum_transition_types(size_t idx, const char **id); */ EXPORT bool obs_enum_output_types(size_t idx, const char **id); -/** Gets the graphics context for this OBS context */ +/** Gets the main graphics context for this OBS context */ EXPORT graphics_t obs_graphics(void); +/** Gets the main audio output handler for this OBS context */ EXPORT audio_t obs_audio(void); + +/** Gets the main video output handler for this OBS context */ EXPORT video_t obs_video(void); /** @@ -317,25 +325,83 @@ EXPORT signal_handler_t obs_signalhandler(void); /** Returns the primary obs procedure handler */ EXPORT proc_handler_t obs_prochandler(void); +/** Adds a draw callback to the main render context */ +EXPORT void obs_add_draw_callback( + void (*draw)(void *param, uint32_t cx, uint32_t cy), + void *param); + +/** Removes a draw callback to the main render context */ +EXPORT void obs_remove_draw_callback( + void (*draw)(void *param, uint32_t cx, uint32_t cy), + void *param); + +/** Changes the size of the main viewport */ +EXPORT void obs_resize(uint32_t cx, uint32_t cy); + +/** Renders the main viewport */ +EXPORT void obs_render_main_viewport(void); + + +/* ------------------------------------------------------------------------- */ +/* Viewport context */ + +/** + * Creates a viewport context. + * + * A viewport can be used for things like separate previews, or drawing + * sources separately. + */ +EXPORT obs_viewport_t obs_viewport_create(void); + +/** Destroys this viewport context */ +EXPORT void obs_viewport_destroy(obs_viewport_t viewport); + +/** Sets the source to be used for this viewport context. */ +EXPORT void obs_viewport_setsource(obs_viewport_t viewport, uint32_t channel, + obs_source_t source); + +/** Gets the source currently in use for this viewport context */ +EXPORT obs_source_t obs_viewport_getsource(obs_viewport_t viewport, + uint32_t channel); + +/** Renders the sources of this viewport context */ +EXPORT void obs_viewport_render(obs_viewport_t viewport); + /* ------------------------------------------------------------------------- */ /* Display context */ /** - * Creates an extra display context. + * Adds a new window display linked to the main render pipeline. This creates + * a new swap chain which updates every frame. * - * An extra display can be used for things like separate previews, - * viewing sources independently, and other things. Creates a new swap chain - * linked to a specific window to display a source. + * @param graphics_data The swap chain initialization data. + * @return The new display context, or NULL if failed. */ EXPORT obs_display_t obs_display_create(struct gs_init_data *graphics_data); + +/** Destroys a display context */ EXPORT void obs_display_destroy(obs_display_t display); -/** Sets the source to be used for a display context. */ -EXPORT void obs_display_setsource(obs_display_t display, uint32_t channel, - obs_source_t source); -EXPORT obs_source_t obs_display_getsource(obs_display_t display, - uint32_t channel); +/** Changes the size of this display */ +EXPORT void obs_display_resize(obs_display_t display, uint32_t cx, uint32_t cy); + +/** + * Adds a draw callback for this display context + * + * @param display The display context. + * @param draw The draw callback which is called each time a frame + * updates. + * @param param The user data to be associated with this draw callback. + */ +EXPORT void obs_display_add_draw_callback(obs_display_t display, + void (*draw)(void *param, uint32_t cx, uint32_t cy), + void *param); + +/** Removes a draw callback for this display context */ +EXPORT void obs_display_remove_draw_callback(obs_display_t display, + void (*draw)(void *param, uint32_t cx, uint32_t cy), + void *param); /* ------------------------------------------------------------------------- */ diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index c9e59bf9c..93042c81f 100644 --- a/obs/window-basic-main.cpp +++ b/obs/window-basic-main.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - Copyright (C) 2013 by Hugh Bailey + Copyright (C) 2013-2014 by Hugh Bailey Copyright (C) 2014 by Zachary Lund This program is free software: you can redistribute it and/or modify @@ -55,6 +55,8 @@ void OBSBasic::OBSInit() if (!InitAudio()) throw "Failed to initialize audio"; + obs_add_draw_callback(OBSBasic::RenderMain, this); + signal_handler_connect(obs_signalhandler(), "source-add", OBSBasic::SourceAdded, this); signal_handler_connect(obs_signalhandler(), "source-remove", @@ -262,6 +264,11 @@ void OBSBasic::ChannelChanged(void *data, calldata_t params) Q_ARG(OBSSource, OBSSource(source))); } +void OBSBasic::RenderMain(void *data, uint32_t cx, uint32_t cy) +{ + obs_render_main_viewport(); +} + /* Main class functions */ bool OBSBasic::InitGraphics() @@ -331,12 +338,8 @@ void OBSBasic::ResizePreview(uint32_t cx, uint32_t cy) ui->preview->setGeometry(x, y, cx, cy); - graphics_t graphics = obs_graphics(); - if (graphics && isVisible()) { - gs_entercontext(graphics); - gs_resize(cx, cy); - gs_leavecontext(); - } + if (isVisible()) + obs_resize(cx, cy); } void OBSBasic::closeEvent(QCloseEvent *event) diff --git a/obs/window-basic-main.hpp b/obs/window-basic-main.hpp index 2434a9bd0..3ce9a52a5 100644 --- a/obs/window-basic-main.hpp +++ b/obs/window-basic-main.hpp @@ -1,5 +1,5 @@ /****************************************************************************** - Copyright (C) 2013 by Hugh Bailey + Copyright (C) 2013-2014 by Hugh Bailey This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,6 +52,7 @@ private: static void SourceAdded(void *data, calldata_t params); static void SourceRemoved(void *data, calldata_t params); static void ChannelChanged(void *data, calldata_t params); + static void RenderMain(void *data, uint32_t cx, uint32_t cy); void ResizePreview(uint32_t cx, uint32_t cy); diff --git a/vs/2013/libobs/libobs.vcxproj b/vs/2013/libobs/libobs.vcxproj index 1a8fdfe08..e0c18f51b 100644 --- a/vs/2013/libobs/libobs.vcxproj +++ b/vs/2013/libobs/libobs.vcxproj @@ -102,6 +102,7 @@ + diff --git a/vs/2013/libobs/libobs.vcxproj.filters b/vs/2013/libobs/libobs.vcxproj.filters index a73830813..97fb4ed59 100644 --- a/vs/2013/libobs/libobs.vcxproj.filters +++ b/vs/2013/libobs/libobs.vcxproj.filters @@ -344,5 +344,8 @@ libobs\Source Files + + libobs\Source Files + \ No newline at end of file