Kill off external driver plug interfaces.

These are too much work to maintain, and aren't really all
that useful.
This commit is contained in:
Themaister 2012-12-22 11:35:26 +01:00
parent 92e5036eb6
commit 6bb2349833
12 changed files with 3 additions and 1025 deletions

View File

@ -247,7 +247,6 @@ else ifeq ($(HAVE_CG), 1)
endif
ifeq ($(HAVE_DYLIB), 1)
OBJ += gfx/ext_gfx.o audio/ext_audio.o
LIBS += $(DYLIB_LIB)
endif

View File

@ -181,10 +181,6 @@ ifeq ($(HAVE_FBO), 1)
DEFINES += -DHAVE_FBO
endif
ifeq ($(HAVE_DYLIB), 1)
OBJ += gfx/ext_gfx.o audio/ext_audio.o
endif
ifeq ($(HAVE_PYTHON), 1)
LIBS += -lpython32
DEFINES += -DHAVE_PYTHON -Ipython

View File

@ -1,128 +0,0 @@
/////
// API header for external RetroArch audio driver plugins.
//
//
#ifndef __RARCH_AUDIO_DRIVER_PLUGIN_H
#define __RARCH_AUDIO_DRIVER_PLUGIN_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#ifdef RARCH_DLL_IMPORT
#define RARCH_API_EXPORT __declspec(dllimport)
#else
#define RARCH_API_EXPORT __declspec(dllexport)
#endif
#define RARCH_API_CALLTYPE __cdecl
#else
#define RARCH_API_EXPORT
#define RARCH_API_CALLTYPE
#endif
#ifndef RARCH_TRUE
#define RARCH_TRUE 1
#endif
#ifndef RARCH_FALSE
#define RARCH_FALSE 0
#endif
#ifndef RARCH_OK
#define RARCH_OK 1
#endif
#ifndef RARCH_ERROR
#define RARCH_ERROR 0
#endif
#define RARCH_AUDIO_API_VERSION 2
typedef struct rarch_audio_driver_info
{
// A hint for a subdevice of the audio driver.
// This is driver independent, and not relevant for all
// audio drivers. I.e. ALSA driver might use "hw:0",
// OSS "/dev/audio", etc.
const char *device;
// Audio sample rate.
unsigned sample_rate;
// Maximum audio latency requested for output,
// measured in milliseconds.
// If driver is not able to provide this latency, it can
// be disregarded.
unsigned latency;
} rarch_audio_driver_info_t;
typedef struct rarch_audio_driver
{
// Initializes the device.
void *(*init)(const rarch_audio_driver_info_t *info);
// Write data in buffer to audio driver.
// A frame here is defined as one combined sample of left and right
// channels. (I.e. 44.1kHz, 16-bit stereo has 88.2k samples/s, and
// 44.1k frames/s.)
//
// Samples are interleaved in format LRLRLRLRLR ...
// If the driver returns true in use_float(), a floating point
// format will be used, with range [-1.0, 1.0].
// If not, signed 16-bit samples in native byte ordering will be used.
//
// This function returns the number of frames successfully written.
// If an error occurs, -1 should be returned.
// Note that non-blocking behavior that cannot write at this time
// should return 0 as returning -1 will terminate the driver.
//
// Unless said otherwise with set_nonblock_state(), all writes
// are blocking, and it should block till it has written all frames.
int (*write)(void *data, const void *buffer, unsigned frames);
// Temporarily pauses the audio driver.
int (*stop)(void *data);
// Resumes audio driver from the paused state.
int (*start)(void *data);
// If state is true, nonblocking operation is assumed.
// This is typically used for fast-forwarding. If driver cannot
// implement nonblocking writes, this can be disregarded, but should
// log a message to stderr.
void (*set_nonblock_state)(void *data, int state);
// Stops and frees the audio driver.
void (*free)(void *data);
// If true is returned, the audio driver is capable of using
// floating point data. This will likely increase performance as the
// resampler unit uses floating point. The sample range is
// [-1.0, 1.0].
int (*use_float)(void *data);
// The driver might be forced to use a certain output frequency
// (i.e. Jack), and thus to avoid double resampling, the driver
// can request RetroArch to resample to a different sample rate.
// This function can be set to NULL if the driver does not
// desire to override the sample rate.
unsigned (*sample_rate)(void *data);
// Human readable identification string for the driver.
const char *ident;
// Must be set to RARCH_AUDIO_API_VERSION.
// Used for detecting API mismatch.
int api_version;
} rarch_audio_driver_t;
RARCH_API_EXPORT const rarch_audio_driver_t* RARCH_API_CALLTYPE
rarch_audio_driver_init(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,162 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "ext/rarch_audio.h"
#include "../boolean.h"
#include <stdlib.h>
#include <stdint.h>
#include "../driver.h"
#include "../dynamic.h"
#include "../general.h"
#include <sys/types.h>
typedef struct audio_ext
{
dylib_t lib;
const rarch_audio_driver_t *driver;
void *handle;
bool is_float;
} audio_ext_t;
static void audio_ext_free(void *data)
{
audio_ext_t *ext = (audio_ext_t*)data;
if (ext)
{
if (ext->driver && ext->handle)
ext->driver->free(ext->handle);
if (ext->lib)
dylib_close(ext->lib);
free(ext);
}
}
static void *audio_ext_init(const char *device, unsigned rate, unsigned latency)
{
if (!(*g_settings.audio.external_driver))
{
RARCH_ERR("Please define an external audio driver.\n");
return NULL;
}
audio_ext_t *ext = (audio_ext_t*)calloc(1, sizeof(*ext));
if (!ext)
return NULL;
rarch_audio_driver_info_t info = {0};
const rarch_audio_driver_t *(*plugin_load)(void) = NULL;
ext->lib = dylib_load(g_settings.audio.external_driver);
if (!ext->lib)
{
RARCH_ERR("Failed to load external library \"%s\"\n", g_settings.audio.external_driver);
goto error;
}
plugin_load = (const rarch_audio_driver_t *(*)(void))dylib_proc(ext->lib, "rarch_audio_driver_init");
if (!plugin_load)
{
RARCH_ERR("Failed to find symbol \"rarch_audio_driver_init\" in plugin.\n");
goto error;
}
ext->driver = plugin_load();
if (!ext->driver)
{
RARCH_ERR("Received invalid driver from plugin.\n");
goto error;
}
RARCH_LOG("Loaded external audio driver: \"%s\"\n", ext->driver->ident ? ext->driver->ident : "Unknown");
if (ext->driver->api_version != RARCH_AUDIO_API_VERSION)
{
RARCH_ERR("API mismatch in external audio plugin. RetroArch: %d, Plugin: %d ...\n", RARCH_AUDIO_API_VERSION, ext->driver->api_version);
goto error;
}
info.device = device;
info.sample_rate = rate;
info.latency = latency;
ext->handle = ext->driver->init(&info);
if (!ext->handle)
{
RARCH_ERR("Failed to init audio driver.\n");
goto error;
}
if (ext->driver->sample_rate)
g_settings.audio.out_rate = ext->driver->sample_rate(ext->handle);
if (!g_settings.audio.sync)
ext->driver->set_nonblock_state(ext->handle, RARCH_TRUE);
return ext;
error:
audio_ext_free(ext);
return NULL;
}
static ssize_t audio_ext_write(void *data, const void *buf, size_t size)
{
audio_ext_t *ext = (audio_ext_t*)data;
unsigned frame_size = ext->is_float ? (2 * sizeof(float)) : (2 * sizeof(int16_t));
size /= frame_size;
int ret = ext->driver->write(ext->handle, buf, size);
if (ret < 0)
return -1;
return ret * frame_size;
}
static bool audio_ext_start(void *data)
{
audio_ext_t *ext = (audio_ext_t*)data;
return ext->driver->start(ext->handle);
}
static bool audio_ext_stop(void *data)
{
audio_ext_t *ext = (audio_ext_t*)data;
return ext->driver->stop(ext->handle);
}
static void audio_ext_set_nonblock_state(void *data, bool toggle)
{
audio_ext_t *ext = (audio_ext_t*)data;
ext->driver->set_nonblock_state(ext->handle, toggle);
}
static bool audio_ext_use_float(void *data)
{
audio_ext_t *ext = (audio_ext_t*)data;
ext->is_float = ext->driver->use_float(ext->handle);
return ext->is_float;
}
const audio_driver_t audio_ext = {
audio_ext_init,
audio_ext_write,
audio_ext_stop,
audio_ext_start,
audio_ext_set_nonblock_state,
audio_ext_free,
audio_ext_use_float,
"ext"
};

View File

@ -67,9 +67,6 @@ static const audio_driver_t *audio_drivers[] = {
#ifdef HAVE_PULSE
&audio_pulse,
#endif
#ifdef HAVE_DYLIB
&audio_ext,
#endif
#ifdef __CELLOS_LV2__
&audio_ps3,
#endif
@ -110,9 +107,6 @@ static const video_driver_t *video_drivers[] = {
#ifdef HAVE_XVIDEO
&video_xvideo,
#endif
#ifdef HAVE_DYLIB
&video_ext,
#endif
#ifdef GEKKO
&video_gx,
#endif

View File

@ -291,7 +291,6 @@ extern const audio_driver_t audio_jack;
extern const audio_driver_t audio_sdl;
extern const audio_driver_t audio_xa;
extern const audio_driver_t audio_pulse;
extern const audio_driver_t audio_ext;
extern const audio_driver_t audio_dsound;
extern const audio_driver_t audio_coreaudio;
extern const audio_driver_t audio_xenon360;
@ -309,7 +308,6 @@ extern const video_driver_t video_xvideo;
extern const video_driver_t video_xdk_d3d;
extern const video_driver_t video_sdl;
extern const video_driver_t video_vg;
extern const video_driver_t video_ext;
extern const video_driver_t video_null;
extern const input_driver_t input_android;
extern const input_driver_t input_sdl;

View File

@ -147,7 +147,6 @@ struct settings
bool gpu_screenshot;
bool allow_rotate;
char external_driver[PATH_MAX];
} video;
struct
@ -162,7 +161,6 @@ struct settings
bool sync;
char dsp_plugin[PATH_MAX];
char external_driver[PATH_MAX];
bool rate_control;
float rate_control_delta;

View File

@ -1,285 +0,0 @@
/////
// API header for external RetroArch video and input plugins.
//
//
#ifndef __RARCH_VIDEO_DRIVER_H
#define __RARCH_VIDEO_DRIVER_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#ifdef RARCH_DLL_IMPORT
#define RARCH_API_EXPORT __declspec(dllimport)
#else
#define RARCH_API_EXPORT __declspec(dllexport)
#endif
#define RARCH_API_CALLTYPE __cdecl
#else
#define RARCH_API_EXPORT
#define RARCH_API_CALLTYPE
#endif
#define RARCH_GRAPHICS_API_VERSION 5
// Since we don't want to rely on C++ or C99 for a proper boolean type,
// make sure return semantics are perfectly clear ... ;)
#ifndef RARCH_OK
#define RARCH_OK 1
#endif
#ifndef RARCH_ERROR
#define RARCH_ERROR 0
#endif
#ifndef RARCH_TRUE
#define RARCH_TRUE 1
#endif
#ifndef RARCH_FALSE
#define RARCH_FALSE 0
#endif
#define RARCH_COLOR_FORMAT_RGB565 0
#define RARCH_COLOR_FORMAT_XRGB8888 1
#define RARCH_INPUT_SCALE_BASE 256
typedef struct py_state py_state_t;
// Create a new runtime for Python.
// py_script: The python script to be loaded. If is_file is true, this will be the full path to a file.
// If false, it will be an UTF-8 encoded string of the script.
// is_file: Tells if py_script is the path to a script, or a script itself.
// py_class: name of the class being instantiated.
typedef py_state_t *(*python_state_new_cb)(const char *py_script, unsigned is_file, const char *py_class);
// Grabs a value from the Python runtime.
// id: The uniform (class method) to be called.
// frame_count: Passes frame_count as an argument to the script.
typedef float (*python_state_get_cb)(py_state_t *handle, const char *id, unsigned frame_count);
// Frees the runtime.
typedef void (*python_state_free_cb)(py_state_t *handle);
typedef struct rarch_video_info
{
// Width of window.
// If fullscreen mode is requested,
// a width of 0 means the resolution of the desktop should be used.
unsigned width;
// Height of window.
// If fullscreen mode is requested,
// a height of 0 means the resolutiof the desktop should be used.
unsigned height;
// If true, start the window in fullscreen mode.
int fullscreen;
// If true, VSync should be enabled.
int vsync;
// If true, the output image should have the aspect ratio
// as set in aspect_ratio.
int force_aspect;
// Aspect ratio. Only takes effect if force_aspect is enabled.
float aspect_ratio;
// Requests that the image is smoothed,
// using bilinear filtering or otherwise.
// If this cannot be implemented efficiently, this can be disregarded.
// If smooth is false, nearest-neighbor scaling is requested.
int smooth;
// input_scale defines the maximum size of the picture that will
// ever be used with the frame callback.
// The maximum resolution is a multiple of 256x256 size (RARCH_INPUT_SCALE_BASE),
// so an input scale of 2
// means you should allocate a texture or of 512x512.
unsigned input_scale;
// Defines the coloring format used of the input frame.
// XRGB1555 format is 16-bit and has byte ordering: 0RRRRRGGGGGBBBBB,
// in native endian.
// ARGB8888 is AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB, native endian.
// Alpha channel should be disregarded.
int color_format;
// If non-NULL, requests the use of an XML shader.
// Can be disregarded.
const char *xml_shader;
// If non-NULL, requests the use of a Cg shader.
// Can be disregarded.
// If both are non-NULL,
// Cg or XML could be used at the discretion of the plugin.
const char *cg_shader;
// Requestes that a certain
// TTF font is used for rendering messages to the screen.
// Can be disregarded.
const char *ttf_font;
unsigned ttf_font_size;
unsigned ttf_font_color; // Font color, in format ARGB8888. Alpha should be disregarded.
// A title that should be displayed in the title bar of the window.
const char *title_hint;
// Functions to peek into the python runtime for shaders.
// Check typedefs above for explanation.
// These may be NULL if RetroArch is not built with Python support.
python_state_new_cb python_state_new;
python_state_get_cb python_state_get;
python_state_free_cb python_state_free;
} rarch_video_info_t;
// Some convenience macros.
// Extract which axes to test for in negative or positive direction.
// May be equal to RARCH_NO_AXIS, which means testing should not occur.
#define RARCH_AXIS_NEG_GET(x) (((unsigned)(x) >> 16) & 0xFFFFU)
#define RARCH_AXIS_POS_GET(x) ((unsigned)(x) & 0xFFFFU)
// I hope no joypad will ever have this many buttons or axes ... ;)
// If joykey is this value, do not check that button.
#define RARCH_NO_AXIS (0xFFFFFFFFU)
#define RARCH_NO_BTN ((unsigned short)0xFFFFU)
// Masks to test on joykey which hat direction is to be tested for.
#define RARCH_HAT_UP_MASK (1 << 15)
#define RARCH_HAT_DOWN_MASK (1 << 14)
#define RARCH_HAT_LEFT_MASK (1 << 13)
#define RARCH_HAT_RIGHT_MASK (1 << 12)
#define RARCH_HAT_MAP(x, hat) ((x & ((1 << 12) - 1)) | hat)
#define RARCH_HAT_MASK (RARCH_HAT_UP_MASK | RARCH_HAT_DOWN_MASK | \
RARCH_HAT_LEFT_MASK | RARCH_HAT_RIGHT_MASK)
// Test this on the joykey. If true, we want to test for a joypad hat
// rather than a button.
#define RARCH_GET_HAT_DIR(x) (x & RARCH_HAT_MASK)
// Gets the joypad hat to be tested for.
// Only valid when RARCH_GET_HAT_DIR() returns true.
#define RARCH_GET_HAT(x) (x & (~RARCH_HAT_MASK))
// key, joykey and joyaxis are all checked at the same time.
// If any one of these are pressed, return 1 in state callback.
struct rarch_keybind
{
// Keyboard key. The key values use the SDL 1.2 keysyms,
// which probably need to be transformed to the native format.
// The actual keysyms RetroArch uses are found in libretro.h.
unsigned short key;
// Joypad key. Joypad POV (hats) are embedded into this key as well.
unsigned short joykey;
// Joypad axis. Negative and positive axes are embedded into this variable.
unsigned joyaxis;
};
typedef struct rarch_input_driver
{
// Inits input driver.
// Joypad index denotes which joypads are desired for the various players.
// Should an entry be negative,
// do not open joypad for that player.
// Threshold states the minimum offset that a joypad axis
// has to be held for it to be registered.
// The range of this is [0, 1],
// where 0 means any displacement will register,
// and 1 means the axis has to be pressed all the way to register.
void *(*init)(const int joypad_index[8], float axis_threshold);
// Polls input. Called once every frame.
void (*poll)(void *data);
// Queries input state for a certain key on a certain player.
// Players are 1 - 8.
// For digital inputs, pressed key is 1, not pressed key is 0.
// Analog values have same range as a signed 16-bit integer.
short (*input_state)(void *data, const struct rarch_keybind *bind,
unsigned player);
// Queries analog input state for a certain key on a certain player in the range of [-0x8000, 0x7fff].
// Only the direction of the bind should be returned.
//
// E.g. if the bind has bind for negative axis 5, and the axis is pressed to the positive
// axis, the returned value should be 0.
short (*input_state_analog)(void *data, unsigned joyaxis,
unsigned player);
// Frees the input struct.
void (*free)(void *data);
// Human readable indentification string.
const char *ident;
} rarch_input_driver_t;
typedef struct rarch_video_driver
{
// Inits the video driver. Returns an opaque handle pointer to the driver.
// Returns NULL on error.
//
// Should the video driver request that a certain input driver is used,
// it is possible to set the driver to *input.
// If no certain driver is desired, set *input to NULL.
void *(*init)(const rarch_video_info_t *video,
const rarch_input_driver_t **input);
// Updates frame on the screen.
// Frame can be either XRGB1555 or ARGB32 format
// depending on rgb32 setting in rarch_video_info_t.
// Pitch is the distance in bytes between two scanlines in memory.
//
// When msg is non-NULL,
// it's a message that should be displayed to the user.
int (*frame)(void *data, const void *frame,
unsigned width, unsigned height, unsigned pitch, const char *msg);
// Requests nonblocking operation.
// True = VSync is turned off.
// False = VSync is turned on.
void (*set_nonblock_state)(void *data, int toggle);
// This must return false when the user exits the emulator.
int (*alive)(void *data);
// Does the window have focus?
int (*focus)(void *data);
// Frees the video driver.
void (*free)(void *data);
// A human-readable identification of the video driver.
const char *ident;
// Needs to be defined to RARCH_GRAPHICS_API_VERSION.
// This is used to detect API/ABI mismatches.
int api_version;
// The final image should be rotated counter-clockwise by rot * 90 degrees.
void (*set_rotation)(void *data, unsigned rot);
// Gets the current width/height of the viewport.
void (*viewport_size)(void *data, unsigned *width, unsigned *height);
// Reads the content of the viewport into memory.
// Tightly packed BGR888. Pitch is width * 3.
int (*read_viewport)(void *data, unsigned char *buffer);
} rarch_video_driver_t;
// Called by RetroArch on startup to get a driver handle.
// This is NOT dynamically allocated.
RARCH_API_EXPORT const rarch_video_driver_t* RARCH_API_CALLTYPE
rarch_video_init(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,424 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
// Loader for external API plugins.
#define RARCH_DLL_IMPORT
#include "ext/rarch_video.h"
#include "../boolean.h"
#include <stdlib.h>
#include <stdint.h>
#include "../dynamic.h"
#include "../general.h"
#include "gfx_common.h"
#ifdef HAVE_FREETYPE
#include "fonts/fonts.h"
#endif
#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;
/////////// Input hook
typedef struct
{
const rarch_input_driver_t *driver;
void *handle;
} input_ext_t;
static void *input_ext_init(void)
{
g_input_dead = false;
return calloc(1, sizeof(input_ext_t));
}
static void input_ext_poll(void *data)
{
input_ext_t *ext = (input_ext_t*)data;
ext->driver->poll(ext->handle);
}
static int16_t input_ext_input_state(void *data, const struct retro_keybind **retro_keybinds, unsigned port, unsigned device, unsigned index, unsigned id)
{
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;
}
return ext->driver->input_state(ext->handle, &bind, player);
}
static bool input_ext_key_pressed(void *data, int key)
{
input_ext_t *ext = (input_ext_t*)data;
if (key >= 0 && key < RARCH_BIND_LIST_END)
{
const struct retro_keybind *rarch_bind = &g_settings.input.binds[0][key];
if (!rarch_bind->valid)
return false;
struct rarch_keybind bind = {0};
bind.key = rarch_bind->key;
bind.joykey = rarch_bind->joykey;
bind.joyaxis = rarch_bind->joyaxis;
return ext->driver->input_state(ext->handle, &bind, 1);
}
else
return false;
}
static void input_ext_free(void *data)
{
input_ext_t *ext = (input_ext_t*)data;
if (ext)
{
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;
free(ext);
}
}
#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
static const input_driver_t input_ext = {
input_ext_init,
input_ext_poll,
input_ext_input_state,
input_ext_key_pressed,
input_ext_free,
#ifdef RARCH_CONSOLE
input_ext_set_default_keybind_lut,
input_ext_set_analog_dpad_mapping,
input_ext_input_post_init,
2,
#endif
"ext"
};
//////////// Video hook
typedef struct
{
const rarch_video_driver_t *driver;
void *handle;
} ext_t;
static void video_ext_free(void *data)
{
ext_t *ext = (ext_t*)data;
if (ext)
{
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;
free(ext);
}
}
static bool video_ext_focus(void *data)
{
ext_t *ext = (ext_t*)data;
return ext->driver->focus(ext->handle);
}
static bool video_ext_alive(void *data)
{
ext_t *ext = (ext_t*)data;
return ext->driver->alive(ext->handle);
}
static void video_ext_set_nonblock_state(void *data, bool state)
{
ext_t *ext = (ext_t*)data;
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;
ext_t *ext = (ext_t*)data;
return ext->driver->frame(ext->handle, frame, width, height, pitch, msg);
}
static void *setup_input(ext_t *ext, const rarch_input_driver_t *driver)
{
int joypad_index[8];
for (unsigned i = 0; i < 8; i++)
joypad_index[i] = g_settings.input.joypad_map[i] < 0 ? -1 : g_settings.input.joypad_map[i];
void *handle = driver->init(joypad_index, g_settings.input.axis_threshold);
if (!handle)
return NULL;
input_ext_t *wrap_handle = (input_ext_t*)input_ext.init();
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)
{
RARCH_LOG("Loaded driver: \"%s\"\n", ext->driver->ident ? ext->driver->ident : "Unknown");
if (RARCH_GRAPHICS_API_VERSION != ext->driver->api_version)
{
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);
return false;
}
const char *cg_shader = NULL;
const char *xml_shader = NULL;
enum rarch_shader_type type = g_settings.video.shader_type;
if ((type == RARCH_SHADER_CG || type == RARCH_SHADER_AUTO) && *g_settings.video.cg_shader_path)
cg_shader = g_settings.video.cg_shader_path;
else if ((type == RARCH_SHADER_BSNES || type == RARCH_SHADER_AUTO) && *g_settings.video.bsnes_shader_path)
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);
const char *font = NULL;
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);
rarch_video_info_t info = {0};
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;
info.color_format = video->rgb32 ? RARCH_COLOR_FORMAT_XRGB8888 : RARCH_COLOR_FORMAT_RGB565;
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;
#ifdef HAVE_PYTHON
info.python_state_new = py_state_new;
info.python_state_get = py_state_get;
info.python_state_free = py_state_free;
#endif
const rarch_input_driver_t *input_driver = NULL;
ext->handle = ext->driver->init(&info, &input_driver);
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;
}
static void *video_ext_init(const video_info_t *video, const input_driver_t **input, void **input_data)
{
ext_t *ext = (ext_t*)calloc(1, sizeof(*ext));
if (!ext)
return NULL;
const rarch_video_driver_t *(*video_init)(void) = NULL;
if (!(*g_settings.video.external_driver))
{
RARCH_ERR("External driver needs video_external_driver path to be set.\n");
goto error;
}
g_lib = dylib_load(g_settings.video.external_driver);
if (!g_lib)
{
RARCH_ERR("Failed to open library: \"%s\"\n", g_settings.video.external_driver);
goto error;
}
video_init = (const rarch_video_driver_t *(*)(void))dylib_proc(g_lib, "rarch_video_init");
if (!video_init)
{
RARCH_ERR("Couldn't find function rarch_video_init in library ...\n");
goto error;
}
ext->driver = video_init();
if (!ext->driver)
{
RARCH_ERR("External driver returned invalid driver handle.\n");
goto error;
}
if (!setup_video(ext, video, input, input_data))
{
RARCH_ERR("Failed to start driver.\n");
goto error;
}
g_video_dead = false;
return ext;
error:
video_ext_free(ext);
return NULL;
}
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)
{
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;
}
static bool video_read_viewport(void *data, uint8_t *buffer)
{
ext_t *ext = (ext_t*)data;
return ext->driver->read_viewport(ext->handle, buffer);
}
#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
const video_driver_t video_ext = {
video_ext_init,
video_ext_frame,
video_ext_set_nonblock_state,
video_ext_alive,
video_ext_focus,
NULL,
video_ext_free,
"ext",
#ifdef RARCH_CONSOLE
video_ext_gfx_start,
video_ext_gfx_stop,
video_ext_gfx_restart,
video_ext_gfx_apply_state_changes,
#endif
video_set_rotation,
video_viewport_info,
video_read_viewport,
};

View File

@ -563,7 +563,7 @@ static void print_features(void)
_PSUPP(dsound, "DirectSound", "audio driver");
_PSUPP(xaudio, "XAudio2", "audio driver");
_PSUPP(al, "OpenAL", "audio driver");
_PSUPP(dylib, "External", "External filter and driver support");
_PSUPP(dylib, "External", "External filter and plugin support");
_PSUPP(cg, "Cg", "Cg pixel shaders");
_PSUPP(xml, "XML", "bSNES XML pixel shaders");
_PSUPP(sdl_image, "SDL_image", "SDL_image image loading");

View File

@ -36,12 +36,9 @@
#### Video
# Video driver to use. "gl", "xvideo", "sdl" or "ext" (external API driver)
# Video driver to use. "gl", "xvideo", "sdl"
# video_driver = "gl"
# Path to external video driver using the RetroArch driver API.
# video_external_driver =
# Windowed xscale and yscale
# (Real x res: base_size * xscale * aspect_ratio, real y res: base_size * yscale)
# video_xscale = 3.0
@ -158,12 +155,9 @@
# When altering audio_in_rate on-the-fly, define by how much each time.
# audio_rate_step = 0.25
# Audio driver backend. Depending on configuration possible candidates are: alsa, pulse, oss, jack, rsound, roar, openal, sdl, xaudio and ext (external driver).
# Audio driver backend. Depending on configuration possible candidates are: alsa, pulse, oss, jack, rsound, roar, openal, sdl, xaudio.
# audio_driver =
# Path to external audio driver using the RetroArch audio driver API.
# audio_external_driver =
# Override the default audio device the audio_driver uses. This is driver dependant. E.g. ALSA wants a PCM device, OSS wants a path (e.g. /dev/dsp), Jack wants portnames (e.g. system:playback1,system:playback_2), and so on ...
# audio_device =

View File

@ -478,8 +478,6 @@ bool config_load_file(const char *path)
#ifdef HAVE_DYLIB
CONFIG_GET_PATH(video.filter_path, "video_filter");
CONFIG_GET_PATH(video.external_driver, "video_external_driver");
CONFIG_GET_PATH(audio.external_driver, "audio_external_driver");
#endif
#if defined(HAVE_CG) || defined(HAVE_XML)