mirror of
https://github.com/libretro/RetroArch
synced 2025-03-03 04:14:00 +00:00
(SoftFilter) Refactor most code associated to SoftFilter plugin - load .filt
files instead of the dynamic libraries directly. Options can be set in the config file. There's still a problem with config file options - will work this out later.
This commit is contained in:
parent
0bd97eb1ba
commit
4dea8caa6f
6
driver.c
6
driver.c
@ -1311,10 +1311,8 @@ void rarch_init_filter(enum retro_pixel_format colfmt)
|
||||
struct retro_game_geometry *geom = NULL;
|
||||
|
||||
rarch_deinit_filter();
|
||||
#ifndef HAVE_FILTERS_BUILTIN
|
||||
if (!*g_settings.video.filter_path)
|
||||
if (!*g_settings.video.softfilter_plugin)
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Deprecated format. Gets pre-converted.
|
||||
if (colfmt == RETRO_PIXEL_FORMAT_0RGB1555)
|
||||
@ -1333,7 +1331,7 @@ void rarch_init_filter(enum retro_pixel_format colfmt)
|
||||
pow2_y = 0;
|
||||
maxsize = 0;
|
||||
|
||||
g_extern.filter.filter = rarch_softfilter_new(g_settings.video.filter_path,
|
||||
g_extern.filter.filter = rarch_softfilter_new(g_settings.video.softfilter_plugin,
|
||||
RARCH_SOFTFILTER_THREADS_AUTO, colfmt, width, height);
|
||||
|
||||
if (!g_extern.filter.filter)
|
||||
|
17
driver.h
17
driver.h
@ -615,23 +615,6 @@ extern const menu_ctx_driver_t menu_ctx_lakka;
|
||||
extern const menu_ctx_driver_backend_t menu_ctx_backend_common;
|
||||
extern const menu_ctx_driver_backend_t menu_ctx_backend_lakka;
|
||||
|
||||
#ifdef HAVE_FILTERS_BUILTIN
|
||||
extern const struct softfilter_implementation *blargg_ntsc_snes_rf_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *blargg_ntsc_snes_composite_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *blargg_ntsc_snes_svideo_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *blargg_ntsc_snes_rgb_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *lq2x_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *phosphor2x_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *twoxbr_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *epx_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *twoxsai_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *supereagle_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *supertwoxsai_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *twoxbr_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *darken_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *scale2x_get_implementation(softfilter_simd_mask_t simd);
|
||||
#endif
|
||||
|
||||
static inline bool input_key_pressed_func(int key)
|
||||
{
|
||||
bool ret = false;
|
||||
|
@ -1655,7 +1655,7 @@ static void menu_parse_and_resolve(unsigned menu_type)
|
||||
else if (menu_common_type_is(menu_type) == MENU_SETTINGS_SHADER_OPTIONS)
|
||||
exts = "cg|glsl";
|
||||
else if (menu_type == MENU_SETTINGS_VIDEO_SOFTFILTER)
|
||||
exts = EXT_EXECUTABLES;
|
||||
exts = "filt";
|
||||
else if (menu_type == MENU_SETTINGS_AUDIO_DSP_FILTER)
|
||||
exts = "dsp";
|
||||
else if (menu_type == MENU_SETTINGS_OVERLAY_PRESET)
|
||||
@ -3286,41 +3286,8 @@ static int menu_common_setting_set(unsigned id, unsigned action, rarch_setting_t
|
||||
menu_common_setting_set_current_path_selection(setting, "", id, action);
|
||||
break;
|
||||
case MENU_SETTINGS_VIDEO_SOFTFILTER:
|
||||
switch (action)
|
||||
{
|
||||
#if defined(HAVE_DYLIB)
|
||||
case MENU_ACTION_OK:
|
||||
menu_common_setting_push_current_menu(
|
||||
driver.menu->menu_stack,
|
||||
g_settings.video.filter_dir, id,
|
||||
driver.menu->selection_ptr, action);
|
||||
break;
|
||||
case MENU_ACTION_START:
|
||||
strlcpy(g_settings.video.filter_path, "", sizeof(g_settings.video.filter_path));
|
||||
driver.menu_data_own = true;
|
||||
rarch_main_command(RARCH_CMD_REINIT);
|
||||
break;
|
||||
#elif defined(HAVE_FILTERS_BUILTIN)
|
||||
case MENU_ACTION_LEFT:
|
||||
if (g_settings.video.filter_idx > 0)
|
||||
g_settings.video.filter_idx--;
|
||||
break;
|
||||
case MENU_ACTION_RIGHT:
|
||||
if ((g_settings.video.filter_idx + 1) != softfilter_get_last_idx())
|
||||
g_settings.video.filter_idx++;
|
||||
break;
|
||||
case MENU_ACTION_OK:
|
||||
driver.menu_data_own = true;
|
||||
rarch_main_command(RARCH_CMD_REINIT);
|
||||
driver.menu->need_refresh = true;
|
||||
break;
|
||||
case MENU_ACTION_START:
|
||||
g_settings.video.filter_idx = 0;
|
||||
driver.menu_data_own = true;
|
||||
rarch_main_command(RARCH_CMD_REINIT);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (setting)
|
||||
menu_common_setting_set_current_path_selection(setting, g_settings.video.filter_dir, id, action);
|
||||
break;
|
||||
case MENU_SETTINGS_AUDIO_DSP_FILTER:
|
||||
if (setting)
|
||||
@ -4220,10 +4187,7 @@ static void menu_common_setting_set_label(char *type_str, size_t type_str_size,
|
||||
strlcpy(type_str, "...", type_str_size);
|
||||
break;
|
||||
case MENU_SETTINGS_VIDEO_SOFTFILTER:
|
||||
{
|
||||
const char *filter_name = rarch_softfilter_get_name(g_extern.filter.filter);
|
||||
strlcpy(type_str, filter_name ? filter_name : "N/A", type_str_size);
|
||||
}
|
||||
strlcpy(type_str, path_basename(g_settings.video.softfilter_plugin), type_str_size);
|
||||
break;
|
||||
case MENU_SETTINGS_AUDIO_DSP_FILTER:
|
||||
strlcpy(type_str, path_basename(g_settings.audio.dsp_plugin), type_str_size);
|
||||
|
@ -219,10 +219,7 @@ struct settings
|
||||
char shader_path[PATH_MAX];
|
||||
bool shader_enable;
|
||||
|
||||
#ifdef HAVE_FILTERS_BUILTIN
|
||||
unsigned filter_idx;
|
||||
#endif
|
||||
char filter_path[PATH_MAX];
|
||||
char softfilter_plugin[PATH_MAX];
|
||||
float refresh_rate;
|
||||
bool threaded;
|
||||
|
||||
|
420
gfx/filter.c
420
gfx/filter.c
@ -16,17 +16,24 @@
|
||||
#include "filter.h"
|
||||
#include "filters/softfilter.h"
|
||||
#include "../dynamic.h"
|
||||
#include "../conf/config_file.h"
|
||||
#include "../general.h"
|
||||
#include "../file_path.h"
|
||||
#include "../file_ext.h"
|
||||
#include "../performance.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#include "../thread.h"
|
||||
|
||||
struct rarch_soft_plug
|
||||
{
|
||||
#ifdef HAVE_DYLIB
|
||||
dylib_t lib;
|
||||
#endif
|
||||
const struct softfilter_implementation *impl;
|
||||
};
|
||||
|
||||
struct filter_thread_data
|
||||
{
|
||||
sthread_t *thread;
|
||||
@ -66,13 +73,14 @@ static void filter_thread_loop(void *data)
|
||||
|
||||
struct rarch_softfilter
|
||||
{
|
||||
#if !defined(HAVE_FILTERS_BUILTIN) && defined(HAVE_DYLIB)
|
||||
dylib_t lib;
|
||||
#endif
|
||||
config_file_t *conf;
|
||||
|
||||
const struct softfilter_implementation *impl;
|
||||
void *impl_data;
|
||||
|
||||
struct rarch_soft_plug *plugs;
|
||||
unsigned num_plugs;
|
||||
|
||||
unsigned max_width, max_height;
|
||||
enum retro_pixel_format pix_fmt, out_pix_fmt;
|
||||
|
||||
@ -84,110 +92,157 @@ struct rarch_softfilter
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef HAVE_FILTERS_BUILTIN
|
||||
static const struct softfilter_implementation *(*softfilter_drivers[]) (softfilter_simd_mask_t) =
|
||||
const struct softfilter_implementation *softfilter_find_implementation(rarch_softfilter_t *filt, const char *ident)
|
||||
{
|
||||
NULL,
|
||||
&blargg_ntsc_snes_rf_get_implementation,
|
||||
&blargg_ntsc_snes_composite_get_implementation,
|
||||
&blargg_ntsc_snes_svideo_get_implementation,
|
||||
&blargg_ntsc_snes_rgb_get_implementation,
|
||||
&lq2x_get_implementation,
|
||||
&phosphor2x_get_implementation,
|
||||
&twoxbr_get_implementation,
|
||||
&darken_get_implementation,
|
||||
&twoxsai_get_implementation,
|
||||
&supertwoxsai_get_implementation,
|
||||
&supereagle_get_implementation,
|
||||
&epx_get_implementation,
|
||||
&scale2x_get_implementation,
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->num_plugs; i++)
|
||||
{
|
||||
if (!strcmp(filt->plugs[i].impl->short_ident, ident))
|
||||
return filt->plugs[i].impl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct softfilter_userdata
|
||||
{
|
||||
config_file_t *conf;
|
||||
const char *prefix[2];
|
||||
};
|
||||
|
||||
unsigned softfilter_get_last_idx(void)
|
||||
static int softfilter_get_float(void *userdata, const char *key_str, float *value, float default_value)
|
||||
{
|
||||
return sizeof(softfilter_drivers) / sizeof(softfilter_drivers[0]);
|
||||
struct softfilter_userdata *filt = (struct softfilter_userdata*)userdata;
|
||||
|
||||
char key[2][256];
|
||||
snprintf(key[0], sizeof(key[0]), "%s_%s", filt->prefix[0], key_str);
|
||||
snprintf(key[1], sizeof(key[1]), "%s_%s", filt->prefix[1], key_str);
|
||||
|
||||
bool got = config_get_float(filt->conf, key[0], value);
|
||||
got = got || config_get_float(filt->conf, key[1], value);
|
||||
|
||||
if (!got)
|
||||
*value = default_value;
|
||||
return got;
|
||||
}
|
||||
|
||||
static softfilter_get_implementation_t softfilter_get_implementation_from_idx(unsigned i)
|
||||
static int softfilter_get_int(void *userdata, const char *key_str, int *value, int default_value)
|
||||
{
|
||||
if (i < softfilter_get_last_idx())
|
||||
return softfilter_drivers[i];
|
||||
return NULL;
|
||||
struct softfilter_userdata *filt = (struct softfilter_userdata*)userdata;
|
||||
|
||||
char key[2][256];
|
||||
snprintf(key[0], sizeof(key[0]), "%s_%s", filt->prefix[0], key_str);
|
||||
snprintf(key[1], sizeof(key[1]), "%s_%s", filt->prefix[1], key_str);
|
||||
|
||||
bool got = config_get_int(filt->conf, key[0], value);
|
||||
got = got || config_get_int(filt->conf, key[1], value);
|
||||
|
||||
if (!got)
|
||||
*value = default_value;
|
||||
return got;
|
||||
}
|
||||
|
||||
#endif
|
||||
#define softfilter_get_array_setup() \
|
||||
struct softfilter_userdata *filt = (struct softfilter_userdata*)userdata; \
|
||||
\
|
||||
char key[2][256]; \
|
||||
snprintf(key[0], sizeof(key[0]), "%s_%s", filt->prefix[0], key_str); \
|
||||
snprintf(key[1], sizeof(key[1]), "%s_%s", filt->prefix[1], key_str); \
|
||||
\
|
||||
char *str = NULL; \
|
||||
bool got = config_get_string(filt->conf, key[0], &str); \
|
||||
got = got || config_get_string(filt->conf, key[1], &str);
|
||||
|
||||
const char *rarch_softfilter_get_name(void *data)
|
||||
{
|
||||
(void)data;
|
||||
#ifdef HAVE_FILTERS_BUILTIN
|
||||
unsigned cpu_features;
|
||||
const struct softfilter_implementation *impl;
|
||||
softfilter_get_implementation_t cb = (softfilter_get_implementation_t)softfilter_get_implementation_from_idx(g_settings.video.filter_idx);
|
||||
if (cb)
|
||||
{
|
||||
cpu_features = rarch_get_cpu_features();
|
||||
impl = (const struct softfilter_implementation *)cb(cpu_features);
|
||||
if (impl)
|
||||
return impl->ident;
|
||||
#define softfilter_get_array_body(T) \
|
||||
if (got) \
|
||||
{ \
|
||||
unsigned i; \
|
||||
struct string_list *list = string_split(str, " "); \
|
||||
*values = (T*)calloc(list->size, sizeof(T)); \
|
||||
for (i = 0; i < list->size; i++) \
|
||||
(*values)[i] = (T)strtod(list->elems[i].data, NULL); \
|
||||
*out_num_values = list->size; \
|
||||
string_list_free(list); \
|
||||
return true; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
*values = (T*)calloc(num_default_values, sizeof(T)); \
|
||||
memcpy(*values, default_values, sizeof(T) * num_default_values); \
|
||||
*out_num_values = num_default_values; \
|
||||
return false; \
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
rarch_softfilter_t *filt = (rarch_softfilter_t*)data;
|
||||
if (!filt || !filt->impl)
|
||||
return NULL;
|
||||
|
||||
return filt->impl->ident;
|
||||
#endif
|
||||
static int softfilter_get_float_array(void *userdata, const char *key_str,
|
||||
float **values, unsigned *out_num_values,
|
||||
const float *default_values, unsigned num_default_values)
|
||||
{
|
||||
softfilter_get_array_setup()
|
||||
softfilter_get_array_body(float)
|
||||
}
|
||||
|
||||
rarch_softfilter_t *rarch_softfilter_new(const char *filter_path,
|
||||
unsigned threads,
|
||||
static int softfilter_get_int_array(void *userdata, const char *key_str,
|
||||
int **values, unsigned *out_num_values,
|
||||
const int *default_values, unsigned num_default_values)
|
||||
{
|
||||
softfilter_get_array_setup()
|
||||
softfilter_get_array_body(int)
|
||||
}
|
||||
|
||||
static int softfilter_get_string(void *userdata, const char *key_str,
|
||||
char **output, const char *default_output)
|
||||
{
|
||||
softfilter_get_array_setup()
|
||||
|
||||
if (got)
|
||||
{
|
||||
*output = str;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*output = strdup(default_output);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void softfilter_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static const struct softfilter_config softfilter_config = {
|
||||
softfilter_get_float,
|
||||
softfilter_get_int,
|
||||
softfilter_get_float_array,
|
||||
softfilter_get_int_array,
|
||||
softfilter_get_string,
|
||||
softfilter_free,
|
||||
};
|
||||
|
||||
|
||||
static bool create_softfilter_graph(rarch_softfilter_t *filt,
|
||||
enum retro_pixel_format in_pixel_format,
|
||||
unsigned max_width, unsigned max_height)
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads)
|
||||
{
|
||||
unsigned cpu_features, output_fmts, input_fmts, input_fmt;
|
||||
(void)filter_path;
|
||||
unsigned input_fmts, input_fmt, output_fmts;
|
||||
char key[64];
|
||||
struct softfilter_userdata userdata;
|
||||
|
||||
#if defined(HAVE_FILTERS_BUILTIN)
|
||||
if (!g_settings.video.filter_idx)
|
||||
return NULL;
|
||||
#endif
|
||||
snprintf(key, sizeof(key), "filter");
|
||||
|
||||
rarch_softfilter_t *filt = (rarch_softfilter_t*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
char name[64];
|
||||
if (!config_get_array(filt->conf, key, name, sizeof(name)))
|
||||
return false;
|
||||
|
||||
softfilter_get_implementation_t cb = NULL;
|
||||
#if defined(HAVE_FILTERS_BUILTIN)
|
||||
cb = (softfilter_get_implementation_t)softfilter_get_implementation_from_idx(g_settings.video.filter_idx);
|
||||
#elif defined(HAVE_DYLIB)
|
||||
RARCH_LOG("Loading softfilter from \"%s\"\n", filter_path);
|
||||
filt->lib = dylib_load(filter_path);
|
||||
if (!filt->lib)
|
||||
goto error;
|
||||
|
||||
cb = (softfilter_get_implementation_t)dylib_proc(filt->lib, "softfilter_get_implementation");
|
||||
#endif
|
||||
if (!cb)
|
||||
{
|
||||
RARCH_ERR("Couldn't find softfilter symbol.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
cpu_features = rarch_get_cpu_features();
|
||||
filt->impl = cb(cpu_features);
|
||||
filt->impl = softfilter_find_implementation(filt, name);
|
||||
if (!filt->impl)
|
||||
goto error;
|
||||
return false;
|
||||
|
||||
RARCH_LOG("Loaded softfilter \"%s\".\n", filt->impl->ident);
|
||||
|
||||
if (filt->impl->api_version != SOFTFILTER_API_VERSION)
|
||||
{
|
||||
RARCH_ERR("Softfilter ABI mismatch.\n");
|
||||
goto error;
|
||||
}
|
||||
userdata.conf = filt->conf;
|
||||
userdata.prefix[0] = key; // Index-specific configs take priority over ident-specific.
|
||||
userdata.prefix[1] = filt->impl->short_ident;
|
||||
|
||||
// Simple assumptions.
|
||||
filt->pix_fmt = in_pixel_format;
|
||||
@ -202,13 +257,13 @@ rarch_softfilter_t *rarch_softfilter_new(const char *filter_path,
|
||||
input_fmt = SOFTFILTER_FMT_RGB565;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(input_fmt & input_fmts))
|
||||
{
|
||||
RARCH_ERR("Softfilter does not support input format.\n");
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
output_fmts = filt->impl->query_output_formats(input_fmt);
|
||||
@ -221,25 +276,26 @@ rarch_softfilter_t *rarch_softfilter_new(const char *filter_path,
|
||||
else
|
||||
{
|
||||
RARCH_ERR("Did not find suitable output format for softfilter.\n");
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
filt->max_width = max_width;
|
||||
filt->max_height = max_height;
|
||||
|
||||
filt->impl_data = filt->impl->create(NULL, input_fmt, input_fmt, max_width, max_height,
|
||||
threads != RARCH_SOFTFILTER_THREADS_AUTO ? threads : rarch_get_cpu_cores(), cpu_features);
|
||||
filt->impl_data = filt->impl->create(&softfilter_config, input_fmt, input_fmt, max_width, max_height,
|
||||
threads != RARCH_SOFTFILTER_THREADS_AUTO ? threads : rarch_get_cpu_cores(), rarch_get_cpu_features(),
|
||||
&userdata);
|
||||
if (!filt->impl_data)
|
||||
{
|
||||
RARCH_ERR("Failed to create softfilter state.\n");
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
threads = filt->impl->query_num_threads(filt->impl_data);
|
||||
if (!threads)
|
||||
{
|
||||
RARCH_ERR("Invalid number of threads.\n");
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
RARCH_LOG("Using %u threads for softfilter.\n", threads);
|
||||
@ -248,13 +304,13 @@ rarch_softfilter_t *rarch_softfilter_new(const char *filter_path,
|
||||
if (!filt->packets)
|
||||
{
|
||||
RARCH_ERR("Failed to allocate softfilter packets.\n");
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
filt->thread_data = (struct filter_thread_data*)calloc(threads, sizeof(*filt->thread_data));
|
||||
if (!filt->thread_data)
|
||||
goto error;
|
||||
return false;
|
||||
filt->threads = threads;
|
||||
|
||||
unsigned i;
|
||||
@ -265,19 +321,165 @@ rarch_softfilter_t *rarch_softfilter_new(const char *filter_path,
|
||||
|
||||
filt->thread_data[i].lock = slock_new();
|
||||
if (!filt->thread_data[i].lock)
|
||||
goto error;
|
||||
return false;
|
||||
filt->thread_data[i].cond = scond_new();
|
||||
if (!filt->thread_data[i].cond)
|
||||
goto error;
|
||||
return false;
|
||||
filt->thread_data[i].thread = sthread_create(filter_thread_loop, &filt->thread_data[i]);
|
||||
if (!filt->thread_data[i].thread)
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FILTERS_BUILTIN
|
||||
extern const struct softfilter_implementation *blargg_ntsc_snes_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *lq2x_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *phosphor2x_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *twoxbr_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *epx_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *twoxsai_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *supereagle_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *supertwoxsai_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *twoxbr_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *darken_get_implementation(softfilter_simd_mask_t simd);
|
||||
extern const struct softfilter_implementation *scale2x_get_implementation(softfilter_simd_mask_t simd);
|
||||
|
||||
static const softfilter_get_implementation_t soft_plugs_builtin[] = {
|
||||
blargg_ntsc_snes_get_implementation,
|
||||
lq2x_get_implementation,
|
||||
phosphor2x_get_implementation,
|
||||
twoxbr_get_implementation,
|
||||
darken_get_implementation,
|
||||
twoxsai_get_implementation,
|
||||
supertwoxsai_get_implementation,
|
||||
supereagle_get_implementation,
|
||||
epx_get_implementation,
|
||||
scale2x_get_implementation,
|
||||
};
|
||||
|
||||
static bool append_softfilter_plugs(rarch_softfilter_t *filt)
|
||||
{
|
||||
unsigned i;
|
||||
softfilter_simd_mask_t mask = rarch_get_cpu_features();
|
||||
|
||||
filt->plugs = (struct rarch_soft_plug*)calloc(ARRAY_SIZE(soft_plugs_builtin), sizeof(*filt->plugs));
|
||||
if (!filt->plugs)
|
||||
return false;
|
||||
filt->num_plugs = ARRAY_SIZE(soft_plugs_builtin);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(soft_plugs_builtin); i++)
|
||||
{
|
||||
filt->plugs[i].impl = soft_plugs_builtin[i](mask);
|
||||
if (!filt->plugs[i].impl)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static bool append_softfilter_plugs(rarch_softfilter_t *filt, struct string_list *list)
|
||||
{
|
||||
unsigned i;
|
||||
softfilter_simd_mask_t mask = rarch_get_cpu_features();
|
||||
|
||||
for (i = 0; i < list->size; i++)
|
||||
{
|
||||
dylib_t lib = dylib_load(list->elems[i].data);
|
||||
if (!lib)
|
||||
continue;
|
||||
|
||||
softfilter_get_implementation_t cb = (softfilter_get_implementation_t)dylib_proc(lib, "softfilter_get_implementation");
|
||||
if (!cb)
|
||||
{
|
||||
dylib_close(lib);
|
||||
continue;
|
||||
}
|
||||
|
||||
const struct softfilter_implementation *impl = cb(mask);
|
||||
if (!impl)
|
||||
{
|
||||
dylib_close(lib);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (impl->api_version != SOFTFILTER_API_VERSION)
|
||||
{
|
||||
dylib_close(lib);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct rarch_soft_plug *new_plugs = (struct rarch_soft_plug*)realloc(filt->plugs, sizeof(*filt->plugs) * (filt->num_plugs + 1));
|
||||
if (!new_plugs)
|
||||
{
|
||||
dylib_close(lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
RARCH_LOG("[SoftFilter]: Found plug: %s (%s).\n", impl->ident, impl->short_ident);
|
||||
|
||||
filt->plugs = new_plugs;
|
||||
filt->plugs[filt->num_plugs].lib = lib;
|
||||
filt->plugs[filt->num_plugs].impl = impl;
|
||||
filt->num_plugs++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
rarch_softfilter_t *rarch_softfilter_new(const char *filter_config,
|
||||
unsigned threads,
|
||||
enum retro_pixel_format in_pixel_format,
|
||||
unsigned max_width, unsigned max_height)
|
||||
{
|
||||
#if !defined(HAVE_FILTERS_BUILTIN) && defined(HAVE_DYLIB)
|
||||
char basedir[PATH_MAX];
|
||||
#endif
|
||||
unsigned cpu_features;
|
||||
struct string_list *plugs = NULL;
|
||||
|
||||
rarch_softfilter_t *filt = (rarch_softfilter_t*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
|
||||
filt->conf = config_file_new(filter_config);
|
||||
if (!filt->conf)
|
||||
{
|
||||
RARCH_ERR("[SoftFilter]: Did not find config: %s\n", filter_config);
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if defined(HAVE_FILTERS_BUILTIN)
|
||||
if (!append_softfilter_plugs(filt))
|
||||
goto error;
|
||||
#elif defined(HAVE_DYLIB)
|
||||
fill_pathname_basedir(basedir, filter_config, sizeof(basedir));
|
||||
|
||||
plugs = dir_list_new(basedir, EXT_EXECUTABLES, false);
|
||||
if (!plugs)
|
||||
goto error;
|
||||
|
||||
if (!append_softfilter_plugs(filt, plugs))
|
||||
goto error;
|
||||
|
||||
string_list_free(plugs);
|
||||
plugs = NULL;
|
||||
#endif
|
||||
|
||||
if (!create_softfilter_graph(filt, in_pixel_format,
|
||||
max_width, max_height, threads))
|
||||
goto error;
|
||||
|
||||
return filt;
|
||||
|
||||
error:
|
||||
string_list_free(plugs);
|
||||
rarch_softfilter_free(filt);
|
||||
return NULL;
|
||||
}
|
||||
@ -285,18 +487,24 @@ error:
|
||||
void rarch_softfilter_free(rarch_softfilter_t *filt)
|
||||
{
|
||||
unsigned i;
|
||||
i = 0;
|
||||
(void)i;
|
||||
|
||||
if (!filt)
|
||||
return;
|
||||
|
||||
free(filt->packets);
|
||||
if (filt->impl && filt->impl_data)
|
||||
filt->impl->destroy(filt->impl_data);
|
||||
#if !defined(HAVE_FILTERS_BUILTIN) && defined(HAVE_DYLIB)
|
||||
if (filt->lib)
|
||||
dylib_close(filt->lib);
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
for (i = 0; i < filt->num_plugs; i++)
|
||||
{
|
||||
if (filt->plugs[i].lib)
|
||||
dylib_close(filt->plugs[i].lib);
|
||||
}
|
||||
free(filt->plugs);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
|
1
gfx/filters/2xBR.filt
Normal file
1
gfx/filters/2xBR.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = 2xbr
|
1
gfx/filters/2xSaI.filt
Normal file
1
gfx/filters/2xSaI.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = 2xsai
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#define softfilter_get_implementation twoxbr_get_implementation
|
||||
@ -223,10 +224,11 @@ static void SetupFormat(void * data)
|
||||
static void *twoxbr_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -720,8 +722,9 @@ static const struct softfilter_implementation twoxbr_generic = {
|
||||
twoxbr_generic_threads,
|
||||
twoxbr_generic_output,
|
||||
twoxbr_generic_packets,
|
||||
"2xBR",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"2xBR",
|
||||
"2xbr",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#define softfilter_get_implementation twoxsai_get_implementation
|
||||
@ -66,10 +67,11 @@ static unsigned twoxsai_generic_threads(void *data)
|
||||
static void *twoxsai_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -347,8 +349,9 @@ static const struct softfilter_implementation twoxsai_generic = {
|
||||
twoxsai_generic_threads,
|
||||
twoxsai_generic_output,
|
||||
twoxsai_generic_packets,
|
||||
"2xSaI",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"2xSaI",
|
||||
"2xsai",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
3
gfx/filters/Blargg_NTSC_SNES_Composite.filt
Normal file
3
gfx/filters/Blargg_NTSC_SNES_Composite.filt
Normal file
@ -0,0 +1,3 @@
|
||||
filter = blargg_ntsc_snes
|
||||
|
||||
tvtype = "composite"
|
2
gfx/filters/Blargg_NTSC_SNES_RF.filt
Normal file
2
gfx/filters/Blargg_NTSC_SNES_RF.filt
Normal file
@ -0,0 +1,2 @@
|
||||
filter = blargg_ntsc_snes
|
||||
tvtype = "rf"
|
3
gfx/filters/Blargg_NTSC_SNES_RGB.filt
Normal file
3
gfx/filters/Blargg_NTSC_SNES_RGB.filt
Normal file
@ -0,0 +1,3 @@
|
||||
filter = blargg_ntsc_snes
|
||||
|
||||
tvtype = "rgb"
|
2
gfx/filters/Blargg_NTSC_SNES_S-Video.filt
Normal file
2
gfx/filters/Blargg_NTSC_SNES_S-Video.filt
Normal file
@ -0,0 +1,2 @@
|
||||
filter = blargg_ntsc_snes
|
||||
tvtype = "svideo"
|
1
gfx/filters/Darken.filt
Normal file
1
gfx/filters/Darken.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = darken
|
1
gfx/filters/EPX.filt
Normal file
1
gfx/filters/EPX.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = epx
|
1
gfx/filters/LQ2x.filt
Normal file
1
gfx/filters/LQ2x.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = lq2x
|
@ -68,7 +68,7 @@ ASMFLAGS := -INEON/asm
|
||||
asflags += -mfpu=neon
|
||||
endif
|
||||
|
||||
objects += blargg_ntsc_snes_composite.$(DYLIB) blargg_ntsc_snes_rf.$(DYLIB) blargg_ntsc_snes_svideo.$(DYLIB) blargg_ntsc_snes_rgb.$(DYLIB) phosphor2x.$(DYLIB) epx.$(DYLIB) lq2x.$(DYLIB) 2xsai.$(DYLIB) super2xsai.$(DYLIB) supereagle.$(DYLIB) 2xbr.$(DYLIB) darken.$(DYLIB) scale2x.$(DYLIB)
|
||||
objects += blargg_ntsc_snes.$(DYLIB) phosphor2x.$(DYLIB) epx.$(DYLIB) lq2x.$(DYLIB) 2xsai.$(DYLIB) super2xsai.$(DYLIB) supereagle.$(DYLIB) 2xbr.$(DYLIB) darken.$(DYLIB) scale2x.$(DYLIB)
|
||||
|
||||
all: build;
|
||||
|
||||
|
1
gfx/filters/Phosphor2x.filt
Normal file
1
gfx/filters/Phosphor2x.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = phosphor2x
|
1
gfx/filters/Scale2x.filt
Normal file
1
gfx/filters/Scale2x.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = scale2x
|
1
gfx/filters/Super2xSaI.filt
Normal file
1
gfx/filters/Super2xSaI.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = super2xsai
|
1
gfx/filters/SuperEagle.filt
Normal file
1
gfx/filters/SuperEagle.filt
Normal file
@ -0,0 +1 @@
|
||||
filter = supereagle
|
@ -15,15 +15,17 @@
|
||||
*/
|
||||
|
||||
#include "softfilter.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "boolean.h"
|
||||
#include "snes_ntsc/snes_ntsc.h"
|
||||
#include "snes_ntsc/snes_ntsc.c"
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#define softfilter_get_implementation blargg_ntsc_snes_composite_get_implementation
|
||||
#define softfilter_thread_data blargg_ntsc_snes_composite_softfilter_thread_data
|
||||
#define filter_data blargg_ntsc_snes_composite_filter_data
|
||||
#define softfilter_get_implementation blargg_ntsc_snes_get_implementation
|
||||
#define softfilter_thread_data blargg_ntsc_snes_softfilter_thread_data
|
||||
#define filter_data blargg_ntsc_snes_filter_data
|
||||
#endif
|
||||
|
||||
struct softfilter_thread_data
|
||||
@ -50,43 +52,76 @@ struct filter_data
|
||||
};
|
||||
|
||||
|
||||
static unsigned blargg_ntsc_snes_composite_generic_input_fmts(void)
|
||||
static unsigned blargg_ntsc_snes_generic_input_fmts(void)
|
||||
{
|
||||
return SOFTFILTER_FMT_RGB565;
|
||||
}
|
||||
|
||||
static unsigned blargg_ntsc_snes_composite_generic_output_fmts(unsigned input_fmts)
|
||||
static unsigned blargg_ntsc_snes_generic_output_fmts(unsigned input_fmts)
|
||||
{
|
||||
return input_fmts;
|
||||
}
|
||||
|
||||
static unsigned blargg_ntsc_snes_composite_generic_threads(void *data)
|
||||
static unsigned blargg_ntsc_snes_generic_threads(void *data)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
return filt->threads;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_composite_initialize(void *data)
|
||||
static void blargg_ntsc_snes_initialize(void *data,
|
||||
const struct softfilter_config *config,
|
||||
void *userdata)
|
||||
{
|
||||
char *tvtype = NULL;
|
||||
snes_ntsc_setup_t setup;
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
filt->ntsc = (snes_ntsc_t*)calloc(1, sizeof(*filt->ntsc));
|
||||
setup = snes_ntsc_composite;
|
||||
setup.merge_fields = 1;
|
||||
|
||||
if (config->get_string(userdata, "tvtype", &tvtype, "composite"))
|
||||
{
|
||||
if (!strcmp(tvtype, "composite"))
|
||||
{
|
||||
setup = snes_ntsc_composite;
|
||||
setup.merge_fields = 1;
|
||||
}
|
||||
else if (!strcmp(tvtype, "rf"))
|
||||
{
|
||||
setup = snes_ntsc_composite;
|
||||
setup.merge_fields = 0;
|
||||
}
|
||||
else if (!strcmp(tvtype, "rgb"))
|
||||
{
|
||||
setup = snes_ntsc_rgb;
|
||||
setup.merge_fields = 1;
|
||||
}
|
||||
else if (!strcmp(tvtype, "svideo"))
|
||||
{
|
||||
setup = snes_ntsc_svideo;
|
||||
setup.merge_fields = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setup = snes_ntsc_composite;
|
||||
setup.merge_fields = 1;
|
||||
}
|
||||
|
||||
config->free(tvtype);
|
||||
tvtype = NULL;
|
||||
|
||||
snes_ntsc_init(filt->ntsc, &setup);
|
||||
|
||||
filt->burst = 0;
|
||||
filt->burst_toggle = (setup.merge_fields ? 0 : 1);
|
||||
}
|
||||
|
||||
static void *blargg_ntsc_snes_composite_generic_create(const struct softfilter_config *config,
|
||||
static void *blargg_ntsc_snes_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -99,20 +134,21 @@ static void *blargg_ntsc_snes_composite_generic_create(const struct softfilter_c
|
||||
free(filt);
|
||||
return NULL;
|
||||
}
|
||||
blargg_ntsc_snes_composite_initialize(filt);
|
||||
|
||||
blargg_ntsc_snes_initialize(filt, config, userdata);
|
||||
|
||||
return filt;
|
||||
}
|
||||
|
||||
|
||||
static void blargg_ntsc_snes_composite_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
static void blargg_ntsc_snes_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = SNES_NTSC_OUT_WIDTH(width);
|
||||
*out_height = height;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_composite_generic_destroy(void *data)
|
||||
static void blargg_ntsc_snes_generic_destroy(void *data)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
@ -123,7 +159,7 @@ static void blargg_ntsc_snes_composite_generic_destroy(void *data)
|
||||
free(filt);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_composite_render_rgb565(void *data, int width, int height,
|
||||
static void blargg_ntsc_snes_render_rgb565(void *data, int width, int height,
|
||||
int first, int last,
|
||||
uint16_t *input, int pitch, uint16_t *output, int outpitch)
|
||||
{
|
||||
@ -136,18 +172,18 @@ static void blargg_ntsc_snes_composite_render_rgb565(void *data, int width, int
|
||||
filt->burst ^= filt->burst_toggle;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_composite_rgb565(void *data, unsigned width, unsigned height,
|
||||
static void blargg_ntsc_snes_rgb565(void *data, unsigned width, unsigned height,
|
||||
int first, int last, uint16_t *src,
|
||||
unsigned src_stride, uint16_t *dst, unsigned dst_stride)
|
||||
{
|
||||
blargg_ntsc_snes_composite_render_rgb565(data, width, height,
|
||||
blargg_ntsc_snes_render_rgb565(data, width, height,
|
||||
first, last,
|
||||
src, src_stride,
|
||||
dst, dst_stride);
|
||||
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_composite_work_cb_rgb565(void *data, void *thread_data)
|
||||
static void blargg_ntsc_snes_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
@ -155,11 +191,11 @@ static void blargg_ntsc_snes_composite_work_cb_rgb565(void *data, void *thread_d
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
blargg_ntsc_snes_composite_rgb565(data, width, height,
|
||||
blargg_ntsc_snes_rgb565(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_composite_generic_packets(void *data,
|
||||
static void blargg_ntsc_snes_generic_packets(void *data,
|
||||
struct softfilter_work_packet *packets,
|
||||
void *output, size_t output_stride,
|
||||
const void *input, unsigned width, unsigned height, size_t input_stride)
|
||||
@ -184,29 +220,30 @@ static void blargg_ntsc_snes_composite_generic_packets(void *data,
|
||||
thr->last = y_end == height;
|
||||
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
|
||||
packets[i].work = blargg_ntsc_snes_composite_work_cb_rgb565;
|
||||
packets[i].work = blargg_ntsc_snes_work_cb_rgb565;
|
||||
packets[i].thread_data = thr;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct softfilter_implementation blargg_ntsc_snes_composite_generic = {
|
||||
blargg_ntsc_snes_composite_generic_input_fmts,
|
||||
blargg_ntsc_snes_composite_generic_output_fmts,
|
||||
static const struct softfilter_implementation blargg_ntsc_snes_generic = {
|
||||
blargg_ntsc_snes_generic_input_fmts,
|
||||
blargg_ntsc_snes_generic_output_fmts,
|
||||
|
||||
blargg_ntsc_snes_composite_generic_create,
|
||||
blargg_ntsc_snes_composite_generic_destroy,
|
||||
blargg_ntsc_snes_generic_create,
|
||||
blargg_ntsc_snes_generic_destroy,
|
||||
|
||||
blargg_ntsc_snes_composite_generic_threads,
|
||||
blargg_ntsc_snes_composite_generic_output,
|
||||
blargg_ntsc_snes_composite_generic_packets,
|
||||
"Blargg NTSC SNES Composite",
|
||||
blargg_ntsc_snes_generic_threads,
|
||||
blargg_ntsc_snes_generic_output,
|
||||
blargg_ntsc_snes_generic_packets,
|
||||
SOFTFILTER_API_VERSION,
|
||||
"Blargg NTSC SNES",
|
||||
"blargg_ntsc_snes",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &blargg_ntsc_snes_composite_generic;
|
||||
return &blargg_ntsc_snes_generic;
|
||||
}
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
@ -1,214 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2014 - Daniel De Matteis
|
||||
*
|
||||
* 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 "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
#include "boolean.h"
|
||||
#include "snes_ntsc/snes_ntsc.h"
|
||||
#include "snes_ntsc/snes_ntsc.c"
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#define softfilter_get_implementation blargg_ntsc_snes_rf_get_implementation
|
||||
#define softfilter_thread_data blargg_ntsc_snes_rf_softfilter_thread_data
|
||||
#define filter_data blargg_ntsc_snes_rf_filter_data
|
||||
#endif
|
||||
|
||||
struct softfilter_thread_data
|
||||
{
|
||||
void *out_data;
|
||||
const void *in_data;
|
||||
size_t out_pitch;
|
||||
size_t in_pitch;
|
||||
unsigned colfmt;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
int first;
|
||||
int last;
|
||||
};
|
||||
|
||||
struct filter_data
|
||||
{
|
||||
unsigned threads;
|
||||
struct softfilter_thread_data *workers;
|
||||
unsigned in_fmt;
|
||||
struct snes_ntsc_t *ntsc;
|
||||
int burst;
|
||||
int burst_toggle;
|
||||
};
|
||||
|
||||
static unsigned blargg_ntsc_snes_rf_generic_input_fmts(void)
|
||||
{
|
||||
return SOFTFILTER_FMT_RGB565;
|
||||
}
|
||||
|
||||
static unsigned blargg_ntsc_snes_rf_generic_output_fmts(unsigned input_fmts)
|
||||
{
|
||||
return input_fmts;
|
||||
}
|
||||
|
||||
static unsigned blargg_ntsc_snes_rf_generic_threads(void *data)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
return filt->threads;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rf_initialize(void *data)
|
||||
{
|
||||
snes_ntsc_setup_t setup;
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
filt->ntsc = (snes_ntsc_t*)calloc(1, sizeof(*filt->ntsc));
|
||||
setup = snes_ntsc_composite;
|
||||
setup.merge_fields = 0;
|
||||
snes_ntsc_init(filt->ntsc, &setup);
|
||||
|
||||
filt->burst = 0;
|
||||
filt->burst_toggle = (setup.merge_fields ? 0 : 1);
|
||||
}
|
||||
|
||||
static void *blargg_ntsc_snes_rf_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
{
|
||||
free(filt);
|
||||
return NULL;
|
||||
}
|
||||
blargg_ntsc_snes_rf_initialize(filt);
|
||||
|
||||
return filt;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rf_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = SNES_NTSC_OUT_WIDTH(width);
|
||||
*out_height = height;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rf_generic_destroy(void *data)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
if(filt->ntsc)
|
||||
free(filt->ntsc);
|
||||
|
||||
free(filt->workers);
|
||||
free(filt);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rf_render_rgb565(void *data, int width, int height,
|
||||
int first, int last,
|
||||
uint16_t *input, int pitch, uint16_t *output, int outpitch)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
if(width <= 256)
|
||||
snes_ntsc_blit(filt->ntsc, input, pitch, filt->burst, width, height, output, outpitch * 2, first, last);
|
||||
else
|
||||
snes_ntsc_blit_hires(filt->ntsc, input, pitch, filt->burst, width, height, output, outpitch * 2, first, last);
|
||||
|
||||
filt->burst ^= filt->burst_toggle;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rf_rgb565(void *data, unsigned width, unsigned height,
|
||||
int first, int last, uint16_t *src,
|
||||
unsigned src_stride, uint16_t *dst, unsigned dst_stride)
|
||||
{
|
||||
blargg_ntsc_snes_rf_render_rgb565(data, width, height,
|
||||
first, last,
|
||||
src, src_stride,
|
||||
dst, dst_stride);
|
||||
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rf_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
blargg_ntsc_snes_rf_rgb565(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rf_generic_packets(void *data,
|
||||
struct softfilter_work_packet *packets,
|
||||
void *output, size_t output_stride,
|
||||
const void *input, unsigned width, unsigned height, size_t input_stride)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
thr->out_data = (uint8_t*)output + y_start * output_stride;
|
||||
thr->in_data = (const uint8_t*)input + y_start * input_stride;
|
||||
thr->out_pitch = output_stride;
|
||||
thr->in_pitch = input_stride;
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
|
||||
packets[i].work = blargg_ntsc_snes_rf_work_cb_rgb565;
|
||||
packets[i].thread_data = thr;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct softfilter_implementation blargg_ntsc_snes_rf_generic = {
|
||||
blargg_ntsc_snes_rf_generic_input_fmts,
|
||||
blargg_ntsc_snes_rf_generic_output_fmts,
|
||||
|
||||
blargg_ntsc_snes_rf_generic_create,
|
||||
blargg_ntsc_snes_rf_generic_destroy,
|
||||
|
||||
blargg_ntsc_snes_rf_generic_threads,
|
||||
blargg_ntsc_snes_rf_generic_output,
|
||||
blargg_ntsc_snes_rf_generic_packets,
|
||||
"Blargg NTSC NES/SNES RF",
|
||||
SOFTFILTER_API_VERSION,
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &blargg_ntsc_snes_rf_generic;
|
||||
}
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#undef softfilter_get_implementation
|
||||
#undef softfilter_thread_data
|
||||
#undef filter_data
|
||||
#endif
|
@ -1,215 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2014 - Daniel De Matteis
|
||||
*
|
||||
* 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 "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
#include "boolean.h"
|
||||
#include "snes_ntsc/snes_ntsc.h"
|
||||
#include "snes_ntsc/snes_ntsc.c"
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#define softfilter_get_implementation blargg_ntsc_snes_rgb_get_implementation
|
||||
#define softfilter_thread_data blargg_ntsc_snes_rgb_softfilter_thread_data
|
||||
#define filter_data blargg_ntsc_snes_rgb_filter_data
|
||||
#endif
|
||||
|
||||
struct softfilter_thread_data
|
||||
{
|
||||
void *out_data;
|
||||
const void *in_data;
|
||||
size_t out_pitch;
|
||||
size_t in_pitch;
|
||||
unsigned colfmt;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
int first;
|
||||
int last;
|
||||
};
|
||||
|
||||
struct filter_data
|
||||
{
|
||||
unsigned threads;
|
||||
struct softfilter_thread_data *workers;
|
||||
unsigned in_fmt;
|
||||
struct snes_ntsc_t *ntsc;
|
||||
int burst;
|
||||
int burst_toggle;
|
||||
};
|
||||
|
||||
static unsigned blargg_ntsc_snes_rgb_generic_input_fmts(void)
|
||||
{
|
||||
return SOFTFILTER_FMT_RGB565;
|
||||
}
|
||||
|
||||
static unsigned blargg_ntsc_snes_rgb_generic_output_fmts(unsigned input_fmts)
|
||||
{
|
||||
return input_fmts;
|
||||
}
|
||||
|
||||
static unsigned blargg_ntsc_snes_rgb_generic_threads(void *data)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
return filt->threads;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rgb_initialize(void *data)
|
||||
{
|
||||
snes_ntsc_setup_t setup;
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
filt->ntsc = (snes_ntsc_t*)calloc(1, sizeof(*filt->ntsc));
|
||||
setup = snes_ntsc_rgb;
|
||||
setup.merge_fields = 1;
|
||||
snes_ntsc_init(filt->ntsc, &setup);
|
||||
|
||||
filt->burst = 0;
|
||||
filt->burst_toggle = (setup.merge_fields ? 0 : 1);
|
||||
}
|
||||
|
||||
static void *blargg_ntsc_snes_rgb_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
{
|
||||
free(filt);
|
||||
return NULL;
|
||||
}
|
||||
blargg_ntsc_snes_rgb_initialize(filt);
|
||||
|
||||
return filt;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rgb_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = SNES_NTSC_OUT_WIDTH(width);
|
||||
*out_height = height;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rgb_generic_destroy(void *data)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
if(filt->ntsc)
|
||||
free(filt->ntsc);
|
||||
|
||||
free(filt->workers);
|
||||
free(filt);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rgb_render_rgb565(void *data, int width, int height,
|
||||
int first, int last,
|
||||
uint16_t *input, int pitch, uint16_t *output, int outpitch)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
if(width <= 256)
|
||||
snes_ntsc_blit(filt->ntsc, input, pitch, filt->burst, width, height, output, outpitch * 2, first, last);
|
||||
else
|
||||
snes_ntsc_blit_hires(filt->ntsc, input, pitch, filt->burst, width, height, output, outpitch * 2, first, last);
|
||||
|
||||
filt->burst ^= filt->burst_toggle;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rgb_rgb565(void *data, unsigned width, unsigned height,
|
||||
int first, int last, uint16_t *src,
|
||||
unsigned src_stride, uint16_t *dst, unsigned dst_stride)
|
||||
{
|
||||
blargg_ntsc_snes_rgb_render_rgb565(data, width, height,
|
||||
first, last,
|
||||
src, src_stride,
|
||||
dst, dst_stride);
|
||||
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rgb_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
blargg_ntsc_snes_rgb_rgb565(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_rgb_generic_packets(void *data,
|
||||
struct softfilter_work_packet *packets,
|
||||
void *output, size_t output_stride,
|
||||
const void *input, unsigned width, unsigned height, size_t input_stride)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
thr->out_data = (uint8_t*)output + y_start * output_stride;
|
||||
thr->in_data = (const uint8_t*)input + y_start * input_stride;
|
||||
thr->out_pitch = output_stride;
|
||||
thr->in_pitch = input_stride;
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
|
||||
packets[i].work = blargg_ntsc_snes_rgb_work_cb_rgb565;
|
||||
packets[i].thread_data = thr;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct softfilter_implementation blargg_ntsc_snes_rgb_generic = {
|
||||
blargg_ntsc_snes_rgb_generic_input_fmts,
|
||||
blargg_ntsc_snes_rgb_generic_output_fmts,
|
||||
|
||||
blargg_ntsc_snes_rgb_generic_create,
|
||||
blargg_ntsc_snes_rgb_generic_destroy,
|
||||
|
||||
blargg_ntsc_snes_rgb_generic_threads,
|
||||
blargg_ntsc_snes_rgb_generic_output,
|
||||
blargg_ntsc_snes_rgb_generic_packets,
|
||||
"Blargg NTSC NES/SNES RGB",
|
||||
SOFTFILTER_API_VERSION,
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &blargg_ntsc_snes_rgb_generic;
|
||||
}
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#undef softfilter_get_implementation
|
||||
#undef softfilter_thread_data
|
||||
#undef filter_data
|
||||
#endif
|
@ -1,214 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2014 - Daniel De Matteis
|
||||
*
|
||||
* 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 "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
#include "boolean.h"
|
||||
#include "snes_ntsc/snes_ntsc.h"
|
||||
#include "snes_ntsc/snes_ntsc.c"
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#define softfilter_get_implementation blargg_ntsc_snes_svideo_get_implementation
|
||||
#define softfilter_thread_data blargg_ntsc_snes_svideo_softfilter_thread_data
|
||||
#define filter_data blargg_ntsc_snes_svideo_filter_data
|
||||
#endif
|
||||
|
||||
struct softfilter_thread_data
|
||||
{
|
||||
void *out_data;
|
||||
const void *in_data;
|
||||
size_t out_pitch;
|
||||
size_t in_pitch;
|
||||
unsigned colfmt;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
int first;
|
||||
int last;
|
||||
};
|
||||
|
||||
struct filter_data
|
||||
{
|
||||
unsigned threads;
|
||||
struct softfilter_thread_data *workers;
|
||||
unsigned in_fmt;
|
||||
struct snes_ntsc_t *ntsc;
|
||||
int burst;
|
||||
int burst_toggle;
|
||||
};
|
||||
|
||||
static unsigned blargg_ntsc_snes_svideo_generic_input_fmts(void)
|
||||
{
|
||||
return SOFTFILTER_FMT_RGB565;
|
||||
}
|
||||
|
||||
static unsigned blargg_ntsc_snes_svideo_generic_output_fmts(unsigned input_fmts)
|
||||
{
|
||||
return input_fmts;
|
||||
}
|
||||
|
||||
static unsigned blargg_ntsc_snes_svideo_generic_threads(void *data)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
return filt->threads;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_svideo_initialize(void *data)
|
||||
{
|
||||
snes_ntsc_setup_t setup;
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
filt->ntsc = (snes_ntsc_t*)calloc(1, sizeof(*filt->ntsc));
|
||||
setup = snes_ntsc_svideo;
|
||||
setup.merge_fields = 1;
|
||||
snes_ntsc_init(filt->ntsc, &setup);
|
||||
|
||||
filt->burst = 0;
|
||||
filt->burst_toggle = (setup.merge_fields ? 0 : 1);
|
||||
}
|
||||
|
||||
static void *blargg_ntsc_snes_svideo_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
{
|
||||
free(filt);
|
||||
return NULL;
|
||||
}
|
||||
blargg_ntsc_snes_svideo_initialize(filt);
|
||||
return filt;
|
||||
}
|
||||
|
||||
|
||||
static void blargg_ntsc_snes_svideo_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = SNES_NTSC_OUT_WIDTH(width);
|
||||
*out_height = height;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_svideo_generic_destroy(void *data)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
if(filt->ntsc)
|
||||
free(filt->ntsc);
|
||||
|
||||
free(filt->workers);
|
||||
free(filt);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_svideo_render_rgb565(void *data, int width, int height,
|
||||
int first, int last,
|
||||
uint16_t *input, int pitch, uint16_t *output, int outpitch)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
if(width <= 256)
|
||||
snes_ntsc_blit(filt->ntsc, input, pitch, filt->burst, width, height, output, outpitch * 2, first, last);
|
||||
else
|
||||
snes_ntsc_blit_hires(filt->ntsc, input, pitch, filt->burst, width, height, output, outpitch * 2, first, last);
|
||||
|
||||
filt->burst ^= filt->burst_toggle;
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_svideo_rgb565(void *data, unsigned width, unsigned height,
|
||||
int first, int last, uint16_t *src,
|
||||
unsigned src_stride, uint16_t *dst, unsigned dst_stride)
|
||||
{
|
||||
blargg_ntsc_snes_svideo_render_rgb565(data, width, height,
|
||||
first, last,
|
||||
src, src_stride,
|
||||
dst, dst_stride);
|
||||
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_svideo_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
blargg_ntsc_snes_svideo_rgb565(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_svideo_generic_packets(void *data,
|
||||
struct softfilter_work_packet *packets,
|
||||
void *output, size_t output_stride,
|
||||
const void *input, unsigned width, unsigned height, size_t input_stride)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
thr->out_data = (uint8_t*)output + y_start * output_stride;
|
||||
thr->in_data = (const uint8_t*)input + y_start * input_stride;
|
||||
thr->out_pitch = output_stride;
|
||||
thr->in_pitch = input_stride;
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
|
||||
packets[i].work = blargg_ntsc_snes_svideo_work_cb_rgb565;
|
||||
packets[i].thread_data = thr;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct softfilter_implementation blargg_ntsc_snes_svideo_generic = {
|
||||
blargg_ntsc_snes_svideo_generic_input_fmts,
|
||||
blargg_ntsc_snes_svideo_generic_output_fmts,
|
||||
|
||||
blargg_ntsc_snes_svideo_generic_create,
|
||||
blargg_ntsc_snes_svideo_generic_destroy,
|
||||
|
||||
blargg_ntsc_snes_svideo_generic_threads,
|
||||
blargg_ntsc_snes_svideo_generic_output,
|
||||
blargg_ntsc_snes_svideo_generic_packets,
|
||||
"Blargg NTSC NES/SNES S-Video",
|
||||
SOFTFILTER_API_VERSION,
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &blargg_ntsc_snes_svideo_generic;
|
||||
}
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#undef softfilter_get_implementation
|
||||
#undef softfilter_thread_data
|
||||
#undef filter_data
|
||||
#endif
|
@ -66,10 +66,11 @@ static unsigned darken_threads(void *data)
|
||||
static void *darken_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -164,8 +165,9 @@ static const struct softfilter_implementation darken = {
|
||||
darken_threads,
|
||||
darken_output,
|
||||
darken_packets,
|
||||
"Darken",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"Darken",
|
||||
"darken",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
@ -66,10 +66,11 @@ static unsigned epx_generic_threads(void *data)
|
||||
static void *epx_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -416,8 +417,9 @@ static const struct softfilter_implementation epx_generic = {
|
||||
epx_generic_threads,
|
||||
epx_generic_output,
|
||||
epx_generic_packets,
|
||||
"EPX",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"EPX",
|
||||
"epx",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
@ -66,10 +66,11 @@ static unsigned lq2x_generic_threads(void *data)
|
||||
static void *lq2x_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -261,8 +262,9 @@ static const struct softfilter_implementation lq2x_generic = {
|
||||
lq2x_generic_threads,
|
||||
lq2x_generic_output,
|
||||
lq2x_generic_packets,
|
||||
"LQ2x",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"LQ2x",
|
||||
"lq2x",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
@ -219,7 +219,7 @@ static unsigned phosphor2x_generic_threads(void *data)
|
||||
static void *phosphor2x_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
unsigned i;
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
@ -229,6 +229,7 @@ static void *phosphor2x_generic_create(const struct softfilter_config *config,
|
||||
(void)max_width;
|
||||
(void)max_height;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
if (!filt)
|
||||
return NULL;
|
||||
@ -420,8 +421,9 @@ static const struct softfilter_implementation phosphor2x_generic = {
|
||||
phosphor2x_generic_threads,
|
||||
phosphor2x_generic_output,
|
||||
phosphor2x_generic_packets,
|
||||
"Phosphor2x",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"Phosphor2x",
|
||||
"phosphor2x",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
@ -125,10 +125,11 @@ static unsigned scale2x_generic_threads(void *data)
|
||||
static void *scale2x_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -224,8 +225,9 @@ static const struct softfilter_implementation scale2x_generic = {
|
||||
scale2x_generic_threads,
|
||||
scale2x_generic_output,
|
||||
scale2x_generic_packets,
|
||||
"Scale2x",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"Scale2x",
|
||||
"scale2x",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
@ -111,7 +111,7 @@ struct softfilter_work_packet
|
||||
// Input sizes can very per call to softfilter_process_t, but they will never be larger than the maximum.
|
||||
typedef void *(*softfilter_create_t)(const struct softfilter_config *config, unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd);
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata);
|
||||
typedef void (*softfilter_destroy_t)(void *data);
|
||||
|
||||
// Given an input size, query the output size of the filter.
|
||||
@ -145,8 +145,9 @@ struct softfilter_implementation
|
||||
softfilter_query_output_size_t query_output_size;
|
||||
softfilter_get_work_packets_t get_work_packets;
|
||||
|
||||
const char *ident; // Human readable identifier of implementation.
|
||||
unsigned api_version; // Must be SOFTFILTER_API_VERSION
|
||||
const char *ident; // Human readable identifier of implementation.
|
||||
const char *short_ident; // Computer-friendly short version of ident. Lower case, no spaces and special characters, etc.
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -66,10 +66,11 @@ static unsigned supertwoxsai_generic_threads(void *data)
|
||||
static void *supertwoxsai_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -319,8 +320,9 @@ static const struct softfilter_implementation supertwoxsai_generic = {
|
||||
supertwoxsai_generic_threads,
|
||||
supertwoxsai_generic_output,
|
||||
supertwoxsai_generic_packets,
|
||||
"Super2xSaI",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"Super2xSaI",
|
||||
"super2xsai",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
@ -66,10 +66,11 @@ static unsigned supereagle_generic_threads(void *data)
|
||||
static void *supereagle_generic_create(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd)
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
|
||||
{
|
||||
(void)simd;
|
||||
(void)config;
|
||||
(void)userdata;
|
||||
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
@ -324,8 +325,9 @@ static const struct softfilter_implementation supereagle_generic = {
|
||||
supereagle_generic_threads,
|
||||
supereagle_generic_output,
|
||||
supereagle_generic_packets,
|
||||
"SuperEagle",
|
||||
SOFTFILTER_API_VERSION,
|
||||
"SuperEagle",
|
||||
"supereagle",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
|
16
settings.c
16
settings.c
@ -433,8 +433,8 @@ void config_set_defaults(void)
|
||||
*g_settings.video.shader_path = '\0';
|
||||
*g_settings.video.shader_dir = '\0';
|
||||
*g_settings.video.filter_dir = '\0';
|
||||
*g_settings.video.filter_path = '\0';
|
||||
*g_settings.audio.filter_dir = '\0';
|
||||
*g_settings.video.softfilter_plugin = '\0';
|
||||
*g_settings.audio.dsp_plugin = '\0';
|
||||
#ifdef HAVE_MENU
|
||||
*g_settings.menu_content_directory = '\0';
|
||||
@ -836,10 +836,6 @@ bool config_load_file(const char *path, bool set_defaults)
|
||||
CONFIG_GET_FLOAT(video.msg_pos_y, "video_message_pos_y");
|
||||
CONFIG_GET_INT(video.rotation, "video_rotation");
|
||||
|
||||
#if defined(HAVE_FILTERS_BUILTIN)
|
||||
CONFIG_GET_INT(video.filter_idx, "filter_index");
|
||||
#endif
|
||||
|
||||
#ifdef RARCH_CONSOLE
|
||||
/* TODO - will be refactored later to make it more clean - it's more
|
||||
* important that it works for consoles right now */
|
||||
@ -907,10 +903,6 @@ bool config_load_file(const char *path, bool set_defaults)
|
||||
CONFIG_GET_BOOL(video.gpu_record, "video_gpu_record");
|
||||
CONFIG_GET_BOOL(video.gpu_screenshot, "video_gpu_screenshot");
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
CONFIG_GET_PATH(video.filter_path, "video_filter");
|
||||
#endif
|
||||
|
||||
CONFIG_GET_PATH(video.shader_dir, "video_shader_dir");
|
||||
if (!strcmp(g_settings.video.shader_dir, "default"))
|
||||
*g_settings.video.shader_dir = '\0';
|
||||
@ -964,6 +956,7 @@ bool config_load_file(const char *path, bool set_defaults)
|
||||
CONFIG_GET_STRING(menu.driver, "menu_driver");
|
||||
CONFIG_GET_STRING(video.gl_context, "video_gl_context");
|
||||
CONFIG_GET_STRING(audio.driver, "audio_driver");
|
||||
CONFIG_GET_PATH(video.softfilter_plugin, "video_filter");
|
||||
CONFIG_GET_PATH(audio.dsp_plugin, "audio_dsp_plugin");
|
||||
CONFIG_GET_STRING(input.driver, "input_driver");
|
||||
CONFIG_GET_STRING(input.joypad_driver, "input_joypad_driver");
|
||||
@ -1327,9 +1320,6 @@ bool config_save_file(const char *path)
|
||||
config_set_path(conf, "libretro_info_path", g_settings.libretro_info_path);
|
||||
config_set_path(conf, "cheat_database_path", g_settings.cheat_database);
|
||||
config_set_bool(conf, "rewind_enable", g_settings.rewind_enable);
|
||||
#ifdef HAVE_FILTERS_BUILTIN
|
||||
config_set_int(conf, "filter_index", g_settings.video.filter_idx);
|
||||
#endif
|
||||
config_set_int(conf, "audio_latency", g_settings.audio.latency);
|
||||
config_set_bool(conf, "audio_sync", g_settings.audio.sync);
|
||||
config_set_int(conf, "audio_block_frames", g_settings.audio.block_frames);
|
||||
@ -1367,6 +1357,7 @@ bool config_save_file(const char *path)
|
||||
config_set_path(conf, "screenshot_directory", *g_settings.screenshot_directory ? g_settings.screenshot_directory : "default");
|
||||
config_set_int(conf, "aspect_ratio_index", g_settings.video.aspect_ratio_idx);
|
||||
config_set_string(conf, "audio_device", g_settings.audio.device);
|
||||
config_set_string(conf, "video_filter", g_settings.video.softfilter_plugin);
|
||||
config_set_string(conf, "audio_dsp_plugin", g_settings.audio.dsp_plugin);
|
||||
config_set_string(conf, "camera_device", g_settings.camera.device);
|
||||
config_set_bool(conf, "camera_allow", g_settings.camera.allow);
|
||||
@ -1387,7 +1378,6 @@ bool config_save_file(const char *path)
|
||||
config_set_path(conf, "savefile_directory", *g_extern.savefile_dir ? g_extern.savefile_dir : "default");
|
||||
config_set_path(conf, "savestate_directory", *g_extern.savestate_dir ? g_extern.savestate_dir : "default");
|
||||
config_set_path(conf, "video_shader_dir", *g_settings.video.shader_dir ? g_settings.video.shader_dir : "default");
|
||||
config_set_path(conf, "video_filter", g_settings.video.filter_path);
|
||||
config_set_path(conf, "video_filter_dir", *g_settings.video.filter_dir ? g_settings.video.filter_dir : "default");
|
||||
config_set_path(conf, "audio_filter_dir", *g_settings.audio.filter_dir ? g_settings.audio.filter_dir : "default");
|
||||
|
||||
|
@ -1179,7 +1179,7 @@ static void general_read_handler(const void *data)
|
||||
else if (!strcmp(setting->name, "video_aspect_ratio_auto"))
|
||||
*setting->value.boolean = g_settings.video.aspect_ratio_auto;
|
||||
else if (!strcmp(setting->name, "video_filter"))
|
||||
strlcpy(setting->value.string, g_settings.video.filter_path, setting->size);
|
||||
strlcpy(setting->value.string, g_settings.video.softfilter_plugin, setting->size);
|
||||
else if (!strcmp(setting->name, "camera_allow"))
|
||||
*setting->value.boolean = g_settings.camera.allow;
|
||||
else if (!strcmp(setting->name, "location_allow"))
|
||||
@ -1324,9 +1324,7 @@ static void general_write_handler(const void *data)
|
||||
g_settings.audio.latency = *setting->value.unsigned_integer;
|
||||
else if (!strcmp(setting->name, "audio_dsp_plugin"))
|
||||
{
|
||||
#ifdef HAVE_DYLIB
|
||||
strlcpy(g_settings.audio.dsp_plugin, setting->value.string, sizeof(g_settings.audio.dsp_plugin));
|
||||
#endif
|
||||
rarch_cmd = RARCH_CMD_DSP_FILTER_INIT;
|
||||
}
|
||||
else if (!strcmp(setting->name, "state_slot"))
|
||||
@ -1507,7 +1505,7 @@ static void general_write_handler(const void *data)
|
||||
g_settings.video.aspect_ratio_auto = *setting->value.boolean;
|
||||
else if (!strcmp(setting->name, "video_filter"))
|
||||
{
|
||||
strlcpy(g_settings.video.filter_path, setting->value.string, sizeof(g_settings.video.filter_path));
|
||||
strlcpy(g_settings.video.softfilter_plugin, setting->value.string, sizeof(g_settings.video.softfilter_plugin));
|
||||
rarch_cmd = RARCH_CMD_REINIT;
|
||||
}
|
||||
else if (!strcmp(setting->name, "video_filter_flicker"))
|
||||
@ -1727,7 +1725,7 @@ rarch_setting_t* setting_data_get_list(void)
|
||||
CONFIG_BOOL(g_settings.video.allow_rotate, "video_allow_rotate", "Allow rotation", allow_rotate, GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler)
|
||||
CONFIG_BOOL(g_settings.video.crop_overscan, "video_crop_overscan", "Crop Overscan (reload)", crop_overscan, GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler)
|
||||
#ifndef HAVE_FILTERS_BUILTIN
|
||||
CONFIG_PATH(g_settings.video.filter_path, "video_filter", "Software filter", "", GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler) WITH_FLAGS(SD_FLAG_ALLOW_EMPTY)
|
||||
CONFIG_PATH(g_settings.video.softfilter_plugin, "video_filter", "Software filter", "", GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler) WITH_FLAGS(SD_FLAG_ALLOW_EMPTY)
|
||||
#endif
|
||||
#ifdef _XBOX1
|
||||
CONFIG_UINT(g_settings.video.swap_interval, "video_filter_flicker", "Flicker filter", 0, GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler) WITH_RANGE(0, 5, 1, true, true)
|
||||
|
Loading…
x
Reference in New Issue
Block a user