提交 515f44be 编写于 作者: J jp9000

Revamp rendering system to allow custom rendering

Originally, the rendering system was designed to only display sources
and such, but I realized there would be a flaw; if you wanted to render
the main viewport in a custom way, or maybe even the entire application
as a graphics-based front end, you wouldn't have been able to do that.

Displays have now been separated in to viewports and displays.  A
viewport is used to store and draw sources, a display is used to handle
draw callbacks.  You can even use displays without using viewports to
draw custom render displays containing graphics calls if you wish, but
usually they would be used in combination with source viewports at
least.

This requires a tiny bit more work to create simple source displays, but
in the end its worth it for the added flexibility and options it brings.
上级 88519f08
......@@ -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
......
......@@ -15,64 +15,156 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include "graphics/vec4.h"
#include "obs.h"
#include "obs-internal.h"
obs_display_t obs_display_create(struct gs_init_data *graphics_data)
bool obs_display_init(struct obs_display *display,
struct gs_init_data *graphics_data)
{
struct obs_display *display = bzalloc(sizeof(struct obs_display));
pthread_mutex_init_value(&display->draw_callbacks_mutex);
if (graphics_data) {
display->swap = gs_create_swapchain(graphics_data);
if (!display->swap) {
obs_display_destroy(display);
return NULL;
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 (!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)
{
if (!display) return;
pthread_mutex_lock(&display->draw_callbacks_mutex);
display->cx = cx;
display->cy = cy;
display->size_changed = true;
pthread_mutex_unlock(&display->draw_callbacks_mutex);
}
void obs_display_add_draw_callback(obs_display_t display,
void (*draw)(void *param, uint32_t cx, uint32_t cy),
void *param)
{
obs_source_t source;
assert(channel < MAX_CHANNELS);
if (!display) return;
source = display->channels[channel];
if (source)
obs_source_addref(source);
struct draw_callback data = {draw, param};
return 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_setsource(obs_display_t display, uint32_t channel,
obs_source_t source)
void obs_display_remove_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;
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);
}
prev_source = display->channels[channel];
display->channels[channel] = source;
pthread_mutex_unlock(&display->draw_callbacks_mutex);
if (source)
obs_source_addref(source);
if (prev_source)
obs_source_release(prev_source);
render_display_end(display);
}
......@@ -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;
video_t video;
pthread_t video_thread;
bool thread_initialized;
uint32_t base_width;
uint32_t base_height;
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;
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;
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;
volatile bool valid;
DARRAY(struct obs_display*) displays;
DARRAY(struct obs_source*) sources;
DARRAY(struct obs_output*) outputs;
DARRAY(struct obs_encoder*) encoders;
pthread_mutex_t sources_mutex;
pthread_mutex_t displays_mutex;
pthread_mutex_t outputs_mutex;
pthread_mutex_t encoders_mutex;
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;
};
/******************************************************************************
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
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;
}
......
/******************************************************************************
Copyright (C) 2014 by Hugh Bailey <obs.jim@gmail.com>
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 <http://www.gnu.org/licenses/>.
******************************************************************************/
#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);
}
/******************************************************************************
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
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)
{
assert(channel < MAX_CHANNELS);
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};
assert(channel < MAX_CHANNELS);
prev_source = obs->data.channels[channel];
pthread_mutex_lock(&viewport->channels_mutex);
prev_source = viewport->channels[channel];
calldata_setuint32(&params, "channel", channel);
calldata_setptr(&params, "prev_source", prev_source);
......@@ -558,14 +582,14 @@ void obs_set_output_source(uint32_t channel, obs_source_t source)
calldata_getptr(&params, "source", &source);
calldata_free(&params);
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);
}
......@@ -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);
/* ------------------------------------------------------------------------- */
......
/******************************************************************************
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
Copyright (C) 2014 by Zachary Lund <admin@computerquip.com>
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)
......
/******************************************************************************
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
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);
......
......@@ -102,6 +102,7 @@
<ClCompile Include="..\..\..\libobs\obs-scene.c" />
<ClCompile Include="..\..\..\libobs\obs-source.c" />
<ClCompile Include="..\..\..\libobs\obs-video.c" />
<ClCompile Include="..\..\..\libobs\obs-viewport.c" />
<ClCompile Include="..\..\..\libobs\obs-windows.c" />
<ClCompile Include="..\..\..\libobs\obs.c" />
<ClCompile Include="..\..\..\libobs\util\base.c" />
......
......@@ -344,5 +344,8 @@
<ClCompile Include="..\..\..\libobs\obs-properties.c">
<Filter>libobs\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\libobs\obs-viewport.c">
<Filter>libobs\Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册