RetroArch/gfx/ext_gfx.c

425 lines
11 KiB
C
Raw Normal View History

2012-04-21 21:13:50 +00:00
/* RetroArch - A frontend for libretro.
2012-01-08 00:08:18 +00:00
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
2011-05-11 16:40:03 +00:00
*
2012-04-21 21:13:50 +00:00
* RetroArch is free software: you can redistribute it and/or modify it under the terms
2011-05-11 16:40:03 +00:00
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
2012-04-21 21:13:50 +00:00
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
2011-05-11 16:40:03 +00:00
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
2012-04-21 21:31:57 +00:00
* You should have received a copy of the GNU General Public License along with RetroArch.
2011-05-11 16:40:03 +00:00
* If not, see <http://www.gnu.org/licenses/>.
*/
// Loader for external API plugins.
2012-04-21 21:25:32 +00:00
#define RARCH_DLL_IMPORT
#include "ext/rarch_video.h"
2011-12-24 12:46:12 +00:00
#include "../boolean.h"
2011-05-11 16:40:03 +00:00
#include <stdlib.h>
#include <stdint.h>
2011-12-24 23:59:46 +00:00
#include "../dynamic.h"
#include "../general.h"
#include "gfx_common.h"
#ifdef HAVE_FREETYPE
2012-05-27 00:04:50 +00:00
#include "fonts/fonts.h"
#endif
2011-05-11 16:40:03 +00:00
2011-11-15 14:41:49 +00:00
#ifdef HAVE_PYTHON
#define PY_STATE_OMIT_DECLARATION
#include "py_state/py_state.h"
#endif
static bool g_input_dead = true;
static bool g_video_dead = true;
static dylib_t g_lib = NULL;
2011-05-11 16:40:03 +00:00
/////////// Input hook
typedef struct
{
2012-04-21 21:25:32 +00:00
const rarch_input_driver_t *driver;
2011-05-11 16:40:03 +00:00
void *handle;
} input_ext_t;
2011-10-29 11:33:15 +00:00
static void *input_ext_init(void)
2011-05-11 16:40:03 +00:00
{
g_input_dead = false;
2011-05-11 16:40:03 +00:00
return calloc(1, sizeof(input_ext_t));
}
static void input_ext_poll(void *data)
{
2011-12-24 12:46:12 +00:00
input_ext_t *ext = (input_ext_t*)data;
2011-05-11 16:40:03 +00:00
ext->driver->poll(ext->handle);
}
2012-07-07 15:19:32 +00:00
static int16_t input_ext_input_state(void *data, const struct retro_keybind **retro_keybinds, unsigned port, unsigned device, unsigned index, unsigned id)
2011-05-11 16:40:03 +00:00
{
input_ext_t *ext = (input_ext_t*)data;
unsigned player = port + 1;
struct rarch_keybind bind = {0};
switch (device)
{
case RETRO_DEVICE_JOYPAD:
{
if (id >= RARCH_BIND_LIST_END)
return 0;
const struct retro_keybind *rarch_bind = &retro_keybinds[player - 1][id];
if (!rarch_bind->valid)
return 0;
bind.key = rarch_bind->key;
bind.joykey = rarch_bind->joykey;
bind.joyaxis = rarch_bind->joyaxis;
break;
}
// TODO: RETRO_DEVICE_ANALOG.
case RETRO_DEVICE_KEYBOARD:
if (id >= RETROK_LAST)
return 0;
bind.key = id;
bind.joykey = NO_BTN;
bind.joyaxis = AXIS_NONE;
break;
default:
return 0;
2011-05-11 16:40:03 +00:00
}
return ext->driver->input_state(ext->handle, &bind, player);
2011-05-11 16:40:03 +00:00
}
static bool input_ext_key_pressed(void *data, int key)
{
2011-12-24 12:46:12 +00:00
input_ext_t *ext = (input_ext_t*)data;
2011-05-11 16:40:03 +00:00
2012-04-21 21:25:32 +00:00
if (key >= 0 && key < RARCH_BIND_LIST_END)
2011-05-11 16:40:03 +00:00
{
2012-07-07 15:19:32 +00:00
const struct retro_keybind *rarch_bind = &g_settings.input.binds[0][key];
2012-04-21 21:25:32 +00:00
if (!rarch_bind->valid)
2012-01-30 00:45:18 +00:00
return false;
2011-05-11 16:40:03 +00:00
2012-04-21 21:25:32 +00:00
struct rarch_keybind bind = {0};
bind.key = rarch_bind->key;
bind.joykey = rarch_bind->joykey;
2012-04-21 21:25:32 +00:00
bind.joyaxis = rarch_bind->joyaxis;
2011-05-11 16:40:03 +00:00
return ext->driver->input_state(ext->handle, &bind, 1);
}
else
return false;
}
static void input_ext_free(void *data)
{
2011-12-24 12:46:12 +00:00
input_ext_t *ext = (input_ext_t*)data;
2011-05-11 16:40:03 +00:00
if (ext)
{
2011-05-11 16:47:36 +00:00
if (ext->driver && ext->handle)
ext->driver->free(ext->handle);
if (g_video_dead)
{
dylib_close(g_lib);
g_lib = NULL;
}
g_input_dead = true;
2011-05-11 16:40:03 +00:00
free(ext);
}
}
2012-09-17 03:31:29 +00:00
#ifdef RARCH_CONSOLE
static void input_ext_set_default_keybind_lut(unsigned device, unsigned port)
{
(void)device;
(void)port;
}
static void input_ext_set_analog_dpad_mapping(unsigned device, unsigned map_dpad_enum, unsigned controller_id)
{
(void)device;
(void)map_dpad_enum;
(void)controller_id;
}
static void input_ext_input_post_init(void) {}
#endif
2011-05-11 16:40:03 +00:00
static const input_driver_t input_ext = {
2011-12-24 12:46:12 +00:00
input_ext_init,
input_ext_poll,
input_ext_input_state,
input_ext_key_pressed,
input_ext_free,
2012-09-17 03:31:29 +00:00
#ifdef RARCH_CONSOLE
input_ext_set_default_keybind_lut,
input_ext_set_analog_dpad_mapping,
input_ext_input_post_init,
2,
#endif
2011-12-24 12:46:12 +00:00
"ext"
2011-05-11 16:40:03 +00:00
};
//////////// Video hook
typedef struct
{
2012-04-21 21:25:32 +00:00
const rarch_video_driver_t *driver;
2011-05-11 16:40:03 +00:00
void *handle;
} ext_t;
static void video_ext_free(void *data)
{
2011-12-24 12:46:12 +00:00
ext_t *ext = (ext_t*)data;
2011-05-11 16:40:03 +00:00
if (ext)
{
2011-05-11 16:47:36 +00:00
if (ext->driver && ext->handle)
ext->driver->free(ext->handle);
if (g_input_dead)
{
dylib_close(g_lib);
g_lib = NULL;
}
g_video_dead = true;
2011-05-11 16:40:03 +00:00
free(ext);
}
}
static bool video_ext_focus(void *data)
{
2011-12-24 12:46:12 +00:00
ext_t *ext = (ext_t*)data;
2011-05-11 16:40:03 +00:00
return ext->driver->focus(ext->handle);
}
static bool video_ext_alive(void *data)
{
2011-12-24 12:46:12 +00:00
ext_t *ext = (ext_t*)data;
2011-05-11 16:40:03 +00:00
return ext->driver->alive(ext->handle);
}
static void video_ext_set_nonblock_state(void *data, bool state)
{
2011-12-24 12:46:12 +00:00
ext_t *ext = (ext_t*)data;
2011-05-11 16:40:03 +00:00
ext->driver->set_nonblock_state(ext->handle, state);
}
static bool video_ext_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
{
if (!frame)
return true;
2011-12-24 12:46:12 +00:00
ext_t *ext = (ext_t*)data;
2011-05-11 16:40:03 +00:00
return ext->driver->frame(ext->handle, frame, width, height, pitch, msg);
}
2012-04-21 21:25:32 +00:00
static void *setup_input(ext_t *ext, const rarch_input_driver_t *driver)
2011-05-11 16:40:03 +00:00
{
2012-06-10 10:00:25 +00:00
int joypad_index[8];
for (unsigned i = 0; i < 8; i++)
2012-01-30 00:20:35 +00:00
joypad_index[i] = g_settings.input.joypad_map[i] < 0 ? -1 : g_settings.input.joypad_map[i];
2011-05-11 16:40:03 +00:00
2011-05-14 18:52:35 +00:00
void *handle = driver->init(joypad_index, g_settings.input.axis_threshold);
2011-05-11 16:40:03 +00:00
if (!handle)
return NULL;
2011-12-24 12:46:12 +00:00
input_ext_t *wrap_handle = (input_ext_t*)input_ext.init();
2011-05-11 16:40:03 +00:00
if (!wrap_handle)
return NULL;
wrap_handle->handle = handle;
wrap_handle->driver = driver;
return wrap_handle;
}
static bool setup_video(ext_t *ext, const video_info_t *video, const input_driver_t **input, void **input_data)
{
2012-04-21 21:25:32 +00:00
RARCH_LOG("Loaded driver: \"%s\"\n", ext->driver->ident ? ext->driver->ident : "Unknown");
2011-05-11 16:40:03 +00:00
2012-04-21 21:25:32 +00:00
if (RARCH_GRAPHICS_API_VERSION != ext->driver->api_version)
2011-05-11 16:40:03 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_ERR("API version mismatch detected.\n");
RARCH_ERR("Required API version: %d, Library version: %d\n", RARCH_GRAPHICS_API_VERSION, ext->driver->api_version);
2011-05-11 16:40:03 +00:00
return false;
}
2012-06-10 09:46:24 +00:00
const char *cg_shader = NULL;
2011-08-07 21:35:54 +00:00
const char *xml_shader = NULL;
2012-06-10 09:46:24 +00:00
2012-04-21 21:25:32 +00:00
enum rarch_shader_type type = g_settings.video.shader_type;
2012-06-10 09:46:24 +00:00
2012-04-21 21:25:32 +00:00
if ((type == RARCH_SHADER_CG || type == RARCH_SHADER_AUTO) && *g_settings.video.cg_shader_path)
2011-08-07 21:35:54 +00:00
cg_shader = g_settings.video.cg_shader_path;
2012-04-21 21:25:32 +00:00
else if ((type == RARCH_SHADER_BSNES || type == RARCH_SHADER_AUTO) && *g_settings.video.bsnes_shader_path)
2011-08-07 21:35:54 +00:00
xml_shader = g_settings.video.bsnes_shader_path;
int font_color_r = g_settings.video.msg_color_r * 255;
int font_color_g = g_settings.video.msg_color_g * 255;
int font_color_b = g_settings.video.msg_color_b * 255;
font_color_r = font_color_r > 255 ? 255 : (font_color_r < 0 ? 0 : font_color_r);
font_color_g = font_color_g > 255 ? 255 : (font_color_g < 0 ? 0 : font_color_g);
font_color_b = font_color_b > 255 ? 255 : (font_color_b < 0 ? 0 : font_color_b);
2011-08-07 21:35:54 +00:00
const char *font = NULL;
2011-11-09 23:15:41 +00:00
if (g_settings.video.font_enable)
{
font = *g_settings.video.font_path ?
g_settings.video.font_path : NULL;
}
char title_buf[128];
gfx_window_title_reset();
gfx_get_fps(title_buf, sizeof(title_buf), false);
2012-04-21 21:25:32 +00:00
rarch_video_info_t info = {0};
2012-06-10 09:46:24 +00:00
info.width = video->width;
info.height = video->height;
info.fullscreen = video->fullscreen;
info.vsync = video->vsync;
info.force_aspect = video->force_aspect;
info.aspect_ratio = g_settings.video.aspect_ratio;
info.smooth = video->smooth;
info.input_scale = video->input_scale;
2012-10-21 19:59:25 +00:00
info.color_format = video->rgb32 ? RARCH_COLOR_FORMAT_XRGB8888 : RARCH_COLOR_FORMAT_RGB565;
2012-06-10 09:46:24 +00:00
info.xml_shader = xml_shader;
info.cg_shader = cg_shader;
info.ttf_font = font;
info.ttf_font_size = g_settings.video.font_size;
info.ttf_font_color = (font_color_r << 16) | (font_color_g << 8) | (font_color_b << 0);
info.title_hint = title_buf;
2011-11-15 14:41:49 +00:00
#ifdef HAVE_PYTHON
2012-06-10 09:46:24 +00:00
info.python_state_new = py_state_new;
info.python_state_get = py_state_get;
2011-12-24 12:46:12 +00:00
info.python_state_free = py_state_free;
2011-11-15 14:41:49 +00:00
#endif
2011-05-11 16:40:03 +00:00
2012-04-21 21:25:32 +00:00
const rarch_input_driver_t *input_driver = NULL;
2011-05-11 19:12:14 +00:00
ext->handle = ext->driver->init(&info, &input_driver);
2011-05-11 16:40:03 +00:00
if (!ext->handle)
return false;
*input = input_driver ? &input_ext : NULL;
if (input_driver)
*input_data = setup_input(ext, input_driver);
else
*input_data = NULL;
return true;
}
2011-10-29 11:33:15 +00:00
static void *video_ext_init(const video_info_t *video, const input_driver_t **input, void **input_data)
2011-05-11 16:40:03 +00:00
{
2011-12-24 12:46:12 +00:00
ext_t *ext = (ext_t*)calloc(1, sizeof(*ext));
2011-05-11 16:40:03 +00:00
if (!ext)
return NULL;
2012-04-21 21:25:32 +00:00
const rarch_video_driver_t *(*video_init)(void) = NULL;
2011-12-24 12:46:12 +00:00
2011-05-11 16:40:03 +00:00
if (!(*g_settings.video.external_driver))
{
2012-04-21 21:25:32 +00:00
RARCH_ERR("External driver needs video_external_driver path to be set.\n");
2011-05-11 16:40:03 +00:00
goto error;
}
g_lib = dylib_load(g_settings.video.external_driver);
if (!g_lib)
2011-05-11 16:40:03 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_ERR("Failed to open library: \"%s\"\n", g_settings.video.external_driver);
2011-05-11 16:40:03 +00:00
goto error;
}
2012-04-21 21:25:32 +00:00
video_init = (const rarch_video_driver_t *(*)(void))dylib_proc(g_lib, "rarch_video_init");
2012-04-21 21:36:55 +00:00
2011-05-11 16:40:03 +00:00
if (!video_init)
{
2012-04-21 21:25:32 +00:00
RARCH_ERR("Couldn't find function rarch_video_init in library ...\n");
2011-05-11 16:40:03 +00:00
goto error;
}
ext->driver = video_init();
if (!ext->driver)
{
2012-04-21 21:25:32 +00:00
RARCH_ERR("External driver returned invalid driver handle.\n");
2011-05-11 16:40:03 +00:00
goto error;
}
if (!setup_video(ext, video, input, input_data))
{
2012-04-21 21:25:32 +00:00
RARCH_ERR("Failed to start driver.\n");
2011-05-11 16:40:03 +00:00
goto error;
}
g_video_dead = false;
2011-05-11 16:40:03 +00:00
return ext;
error:
video_ext_free(ext);
return NULL;
}
2012-06-10 09:46:24 +00:00
static void video_set_rotation(void *data, unsigned rot)
{
ext_t *ext = (ext_t*)data;
ext->driver->set_rotation(ext->handle, rot);
}
static void video_viewport_info(void *data, struct rarch_viewport *vp)
2012-06-10 09:46:24 +00:00
{
ext_t *ext = (ext_t*)data;
unsigned width = 0, height = 0;
ext->driver->viewport_size(ext->handle, &width, &height);
vp->x = vp->y = 0;
vp->width = width;
vp->height = height;
2012-06-10 09:46:24 +00:00
}
static bool video_read_viewport(void *data, uint8_t *buffer)
{
ext_t *ext = (ext_t*)data;
return ext->driver->read_viewport(ext->handle, buffer);
}
2012-09-17 03:31:29 +00:00
#ifdef RARCH_CONSOLE
static void video_ext_gfx_start(void) {}
static void video_ext_gfx_restart(void) {}
static void video_ext_gfx_stop(void) {}
static void video_ext_gfx_apply_state_changes(void) {}
#endif
2011-05-11 16:40:03 +00:00
const video_driver_t video_ext = {
2011-12-24 12:46:12 +00:00
video_ext_init,
video_ext_frame,
video_ext_set_nonblock_state,
video_ext_alive,
video_ext_focus,
NULL,
video_ext_free,
2012-06-10 09:46:24 +00:00
"ext",
2012-09-17 03:31:29 +00:00
#ifdef RARCH_CONSOLE
video_ext_gfx_start,
video_ext_gfx_stop,
video_ext_gfx_restart,
video_ext_gfx_apply_state_changes,
#endif
2012-06-10 09:46:24 +00:00
video_set_rotation,
video_viewport_info,
2012-06-10 09:46:24 +00:00
video_read_viewport,
2011-05-11 16:40:03 +00:00
};