2013-09-30 19:37:13 -07:00
|
|
|
/******************************************************************************
|
|
|
|
Copyright (C) 2013 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
|
2013-12-02 21:24:38 -08:00
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
2013-09-30 19:37:13 -07:00
|
|
|
(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/>.
|
|
|
|
******************************************************************************/
|
|
|
|
|
2014-02-13 07:58:31 -08:00
|
|
|
#include "graphics/vec4.h"
|
2013-09-30 19:37:13 -07:00
|
|
|
#include "obs.h"
|
2014-01-26 17:48:14 -08:00
|
|
|
#include "obs-internal.h"
|
2013-09-30 19:37:13 -07:00
|
|
|
|
2014-02-13 07:58:31 -08:00
|
|
|
bool obs_display_init(struct obs_display *display,
|
2014-09-26 15:25:59 -07:00
|
|
|
const struct gs_init_data *graphics_data)
|
2013-09-30 19:37:13 -07:00
|
|
|
{
|
2014-02-13 07:58:31 -08:00
|
|
|
pthread_mutex_init_value(&display->draw_callbacks_mutex);
|
2016-12-17 15:21:00 -08:00
|
|
|
pthread_mutex_init_value(&display->draw_info_mutex);
|
2013-09-30 19:37:13 -07:00
|
|
|
|
|
|
|
if (graphics_data) {
|
2014-08-07 23:42:07 -07:00
|
|
|
display->swap = gs_swapchain_create(graphics_data);
|
2013-09-30 19:37:13 -07:00
|
|
|
if (!display->swap) {
|
2014-02-13 07:58:31 -08:00
|
|
|
blog(LOG_ERROR, "obs_display_init: Failed to "
|
|
|
|
"create swap chain");
|
|
|
|
return false;
|
2013-09-30 19:37:13 -07:00
|
|
|
}
|
2014-02-13 07:58:31 -08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2016-12-17 15:21:00 -08:00
|
|
|
if (pthread_mutex_init(&display->draw_info_mutex, NULL) != 0) {
|
|
|
|
blog(LOG_ERROR, "obs_display_init: Failed to create mutex");
|
|
|
|
return false;
|
|
|
|
}
|
2014-02-13 07:58:31 -08:00
|
|
|
|
2015-04-04 00:35:09 -07:00
|
|
|
display->background_color = 0x4C4C4C;
|
2015-04-01 16:22:28 -07:00
|
|
|
display->enabled = true;
|
2014-02-13 07:58:31 -08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-09-26 15:25:59 -07:00
|
|
|
obs_display_t *obs_display_create(const struct gs_init_data *graphics_data)
|
2014-02-13 07:58:31 -08:00
|
|
|
{
|
|
|
|
struct obs_display *display = bzalloc(sizeof(struct obs_display));
|
|
|
|
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_enter_context(obs->video.graphics);
|
2014-03-23 01:07:54 -07:00
|
|
|
|
2014-02-13 07:58:31 -08:00
|
|
|
if (!obs_display_init(display, graphics_data)) {
|
|
|
|
obs_display_destroy(display);
|
|
|
|
display = NULL;
|
2014-03-23 01:07:54 -07:00
|
|
|
} else {
|
|
|
|
pthread_mutex_lock(&obs->data.displays_mutex);
|
libobs: Add services API, reduce repeated code
Add API for streaming services. The services API simplifies the
creation of custom service features and user interface.
Custom streaming services later on will be able to do things such as:
- Be able to use service-specific APIs via modules, allowing a more
direct means of communicating with the service and requesting or
setting service-specific information
- Get URL/stream key via other means of authentication such as OAuth,
or be able to build custom URLs for services that require that sort
of thing.
- Query information (such as viewer count, chat, follower
notifications, and other information)
- Set channel information (such as current game, current channel title,
activating commercials)
Also, I reduce some repeated code that was used for all libobs objects.
This includes the name of the object, the private data, settings, as
well as the signal and procedure handlers.
I also switched to using linked lists for the global object lists,
rather than using an array of pointers (you could say it was..
pointless.) ..Anyway, the linked list info is also stored in the shared
context data structure.
2014-04-19 20:38:53 -07:00
|
|
|
display->prev_next = &obs->data.first_display;
|
|
|
|
display->next = obs->data.first_display;
|
|
|
|
obs->data.first_display = display;
|
|
|
|
if (display->next)
|
|
|
|
display->next->prev_next = &display->next;
|
2014-03-23 01:07:54 -07:00
|
|
|
pthread_mutex_unlock(&obs->data.displays_mutex);
|
2013-09-30 19:37:13 -07:00
|
|
|
}
|
|
|
|
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_leave_context();
|
2014-03-23 01:07:54 -07:00
|
|
|
|
2013-09-30 19:37:13 -07:00
|
|
|
return display;
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void obs_display_free(obs_display_t *display)
|
2014-02-13 07:58:31 -08:00
|
|
|
{
|
|
|
|
pthread_mutex_destroy(&display->draw_callbacks_mutex);
|
2016-12-17 15:21:00 -08:00
|
|
|
pthread_mutex_destroy(&display->draw_info_mutex);
|
2014-02-13 07:58:31 -08:00
|
|
|
da_free(display->draw_callbacks);
|
|
|
|
|
|
|
|
if (display->swap) {
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_swapchain_destroy(display->swap);
|
2014-02-13 07:58:31 -08:00
|
|
|
display->swap = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void obs_display_destroy(obs_display_t *display)
|
2013-09-30 19:37:13 -07:00
|
|
|
{
|
|
|
|
if (display) {
|
2013-11-20 14:00:16 -08:00
|
|
|
pthread_mutex_lock(&obs->data.displays_mutex);
|
2014-09-26 15:35:36 -07:00
|
|
|
if (display->prev_next)
|
|
|
|
*display->prev_next = display->next;
|
libobs: Add services API, reduce repeated code
Add API for streaming services. The services API simplifies the
creation of custom service features and user interface.
Custom streaming services later on will be able to do things such as:
- Be able to use service-specific APIs via modules, allowing a more
direct means of communicating with the service and requesting or
setting service-specific information
- Get URL/stream key via other means of authentication such as OAuth,
or be able to build custom URLs for services that require that sort
of thing.
- Query information (such as viewer count, chat, follower
notifications, and other information)
- Set channel information (such as current game, current channel title,
activating commercials)
Also, I reduce some repeated code that was used for all libobs objects.
This includes the name of the object, the private data, settings, as
well as the signal and procedure handlers.
I also switched to using linked lists for the global object lists,
rather than using an array of pointers (you could say it was..
pointless.) ..Anyway, the linked list info is also stored in the shared
context data structure.
2014-04-19 20:38:53 -07:00
|
|
|
if (display->next)
|
|
|
|
display->next->prev_next = display->prev_next;
|
2013-11-20 14:00:16 -08:00
|
|
|
pthread_mutex_unlock(&obs->data.displays_mutex);
|
|
|
|
|
2014-08-04 05:48:58 -07:00
|
|
|
obs_enter_graphics();
|
2014-02-13 07:58:31 -08:00
|
|
|
obs_display_free(display);
|
2014-08-04 05:48:58 -07:00
|
|
|
obs_leave_graphics();
|
2014-03-23 01:07:54 -07:00
|
|
|
|
2013-09-30 19:37:13 -07:00
|
|
|
bfree(display);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void obs_display_resize(obs_display_t *display, uint32_t cx, uint32_t cy)
|
2014-02-13 07:58:31 -08:00
|
|
|
{
|
|
|
|
if (!display) return;
|
|
|
|
|
2016-12-17 15:21:00 -08:00
|
|
|
pthread_mutex_lock(&display->draw_info_mutex);
|
2014-02-13 07:58:31 -08:00
|
|
|
|
|
|
|
display->cx = cx;
|
|
|
|
display->cy = cy;
|
|
|
|
display->size_changed = true;
|
|
|
|
|
2016-12-17 15:21:00 -08:00
|
|
|
pthread_mutex_unlock(&display->draw_info_mutex);
|
2014-02-13 07:58:31 -08:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void obs_display_add_draw_callback(obs_display_t *display,
|
2014-02-13 07:58:31 -08:00
|
|
|
void (*draw)(void *param, uint32_t cx, uint32_t cy),
|
|
|
|
void *param)
|
2013-09-30 19:37:13 -07:00
|
|
|
{
|
2014-02-13 07:58:31 -08:00
|
|
|
if (!display) return;
|
2014-01-30 00:31:52 -08:00
|
|
|
|
2014-02-13 07:58:31 -08:00
|
|
|
struct draw_callback data = {draw, param};
|
2014-01-30 00:31:52 -08:00
|
|
|
|
2014-02-13 07:58:31 -08:00
|
|
|
pthread_mutex_lock(&display->draw_callbacks_mutex);
|
|
|
|
da_push_back(display->draw_callbacks, &data);
|
|
|
|
pthread_mutex_unlock(&display->draw_callbacks_mutex);
|
2013-09-30 19:37:13 -07:00
|
|
|
}
|
|
|
|
|
2014-09-25 17:44:05 -07:00
|
|
|
void obs_display_remove_draw_callback(obs_display_t *display,
|
2014-02-13 07:58:31 -08:00
|
|
|
void (*draw)(void *param, uint32_t cx, uint32_t cy),
|
|
|
|
void *param)
|
2013-09-30 19:37:13 -07:00
|
|
|
{
|
2014-02-13 07:58:31 -08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-12-17 15:21:00 -08:00
|
|
|
static inline void render_display_begin(struct obs_display *display,
|
|
|
|
uint32_t cx, uint32_t cy, bool size_changed)
|
2014-02-13 07:58:31 -08:00
|
|
|
{
|
|
|
|
struct vec4 clear_color;
|
|
|
|
|
2017-02-25 07:45:45 -08:00
|
|
|
gs_load_swapchain(display->swap);
|
2014-02-13 07:58:31 -08:00
|
|
|
|
2016-12-17 15:21:00 -08:00
|
|
|
if (size_changed)
|
|
|
|
gs_resize(cx, cy);
|
2014-02-13 07:58:31 -08:00
|
|
|
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_begin_scene();
|
2014-03-07 09:19:03 -08:00
|
|
|
|
2015-04-04 00:35:09 -07:00
|
|
|
vec4_from_rgba(&clear_color, display->background_color);
|
|
|
|
clear_color.w = 1.0f;
|
|
|
|
|
2014-02-13 07:58:31 -08:00
|
|
|
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL,
|
|
|
|
&clear_color, 1.0f, 0);
|
|
|
|
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_enable_depth_test(false);
|
2014-02-13 07:58:31 -08:00
|
|
|
/* gs_enable_blending(false); */
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_set_cull_mode(GS_NEITHER);
|
2014-02-13 07:58:31 -08:00
|
|
|
|
2016-12-17 15:21:00 -08:00
|
|
|
gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -100.0f, 100.0f);
|
|
|
|
gs_set_viewport(0, 0, cx, cy);
|
2014-02-13 07:58:31 -08:00
|
|
|
}
|
|
|
|
|
2014-02-14 14:13:36 -08:00
|
|
|
static inline void render_display_end()
|
2014-02-13 07:58:31 -08:00
|
|
|
{
|
2014-08-07 23:42:07 -07:00
|
|
|
gs_end_scene();
|
2014-02-13 07:58:31 -08:00
|
|
|
gs_present();
|
|
|
|
}
|
|
|
|
|
|
|
|
void render_display(struct obs_display *display)
|
|
|
|
{
|
2016-12-17 15:21:00 -08:00
|
|
|
uint32_t cx, cy;
|
|
|
|
bool size_changed;
|
|
|
|
|
2015-04-01 16:22:28 -07:00
|
|
|
if (!display || !display->enabled) return;
|
2014-02-13 07:58:31 -08:00
|
|
|
|
2016-12-17 15:21:00 -08:00
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
|
|
|
pthread_mutex_lock(&display->draw_info_mutex);
|
|
|
|
|
|
|
|
cx = display->cx;
|
|
|
|
cy = display->cy;
|
|
|
|
size_changed = display->size_changed;
|
|
|
|
|
|
|
|
if (size_changed)
|
|
|
|
display->size_changed = false;
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&display->draw_info_mutex);
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
|
|
|
render_display_begin(display, cx, cy, size_changed);
|
2014-02-13 07:58:31 -08:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2016-12-17 15:21:00 -08:00
|
|
|
callback->draw(callback->param, cx, cy);
|
2014-02-13 07:58:31 -08:00
|
|
|
}
|
2013-11-20 14:00:16 -08:00
|
|
|
|
2014-02-13 07:58:31 -08:00
|
|
|
pthread_mutex_unlock(&display->draw_callbacks_mutex);
|
2013-11-20 14:00:16 -08:00
|
|
|
|
2014-02-14 14:13:36 -08:00
|
|
|
render_display_end();
|
2013-09-30 19:37:13 -07:00
|
|
|
}
|
2015-04-01 16:22:28 -07:00
|
|
|
|
|
|
|
void obs_display_set_enabled(obs_display_t *display, bool enable)
|
|
|
|
{
|
|
|
|
if (display)
|
|
|
|
display->enabled = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool obs_display_enabled(obs_display_t *display)
|
|
|
|
{
|
|
|
|
return display ? display->enabled : false;
|
|
|
|
}
|
2015-04-04 00:35:09 -07:00
|
|
|
|
|
|
|
void obs_display_set_background_color(obs_display_t *display, uint32_t color)
|
|
|
|
{
|
|
|
|
if (display)
|
|
|
|
display->background_color = color;
|
|
|
|
}
|