mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 03:32:46 +00:00
(RS90) Add optional approximate 'semi-linear' scaling filter
This commit is contained in:
parent
d4d9129ad4
commit
218286aa99
@ -420,6 +420,11 @@
|
||||
* in Dingux devices */
|
||||
#define DEFAULT_DINGUX_REFRESH_RATE DINGUX_REFRESH_RATE_60HZ
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
/* Sets image filtering method on the RS90
|
||||
* when integer scaling is disabled */
|
||||
#define DEFAULT_DINGUX_RS90_SOFTFILTER_TYPE DINGUX_RS90_SOFTFILTER_POINT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Save configuration file on exit. */
|
||||
|
@ -2137,6 +2137,9 @@ static struct config_uint_setting *populate_settings_uint(
|
||||
#if defined(DINGUX_BETA)
|
||||
SETTING_UINT("video_dingux_refresh_rate", &settings->uints.video_dingux_refresh_rate, true, DEFAULT_DINGUX_REFRESH_RATE, false);
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
SETTING_UINT("video_dingux_rs90_softfilter_type", &settings->uints.video_dingux_rs90_softfilter_type, true, DEFAULT_DINGUX_RS90_SOFTFILTER_TYPE, false);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
@ -209,6 +209,7 @@ typedef struct settings
|
||||
unsigned video_3ds_display_mode;
|
||||
unsigned video_dingux_ipu_filter_type;
|
||||
unsigned video_dingux_refresh_rate;
|
||||
unsigned video_dingux_rs90_softfilter_type;
|
||||
#ifdef HAVE_VIDEO_LAYOUT
|
||||
unsigned video_layout_selected_view;
|
||||
#endif
|
||||
|
@ -206,16 +206,19 @@ static void xdg_screensaver_inhibit(Window wnd)
|
||||
|
||||
RARCH_LOG("[X11]: Suspending screensaver (X11, xdg-screensaver).\n");
|
||||
|
||||
/* Make sure the window has a title, even if it's a bogus one, otherwise
|
||||
* xdg-screensaver will fail and report to stderr, framing RA for its bug.
|
||||
* A single space character is used so that the title bar stays visibly
|
||||
* the same, as if there's no title at all. */
|
||||
video_driver_get_window_title(title, sizeof(title));
|
||||
if (strlen(title) == 0)
|
||||
snprintf(title, sizeof(title), " ");
|
||||
XChangeProperty(g_x11_dpy, g_x11_win, XA_WM_NAME, XA_STRING,
|
||||
8, PropModeReplace, (const unsigned char*) title,
|
||||
strlen(title));
|
||||
if (g_x11_dpy && g_x11_win)
|
||||
{
|
||||
/* Make sure the window has a title, even if it's a bogus one, otherwise
|
||||
* xdg-screensaver will fail and report to stderr, framing RA for its bug.
|
||||
* A single space character is used so that the title bar stays visibly
|
||||
* the same, as if there's no title at all. */
|
||||
video_driver_get_window_title(title, sizeof(title));
|
||||
if (strlen(title) == 0)
|
||||
snprintf(title, sizeof(title), " ");
|
||||
XChangeProperty(g_x11_dpy, g_x11_win, XA_WM_NAME, XA_STRING,
|
||||
8, PropModeReplace, (const unsigned char*) title,
|
||||
strlen(title));
|
||||
}
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "xdg-screensaver suspend 0x%x", (int)wnd);
|
||||
|
||||
|
@ -56,11 +56,18 @@
|
||||
|
||||
#define SDL_RS90_NUM_FONT_GLYPHS 256
|
||||
|
||||
typedef struct sdl_rs90_video
|
||||
typedef struct sdl_rs90_video sdl_rs90_video_t;
|
||||
struct sdl_rs90_video
|
||||
{
|
||||
retro_time_t last_frame_time;
|
||||
retro_time_t ff_frame_time_min;
|
||||
SDL_Surface *screen;
|
||||
void (*scale_frame16)(sdl_rs90_video_t *vid,
|
||||
uint16_t *src, unsigned width, unsigned height,
|
||||
unsigned src_pitch);
|
||||
void (*scale_frame32)(sdl_rs90_video_t *vid,
|
||||
uint32_t *src, unsigned width, unsigned height,
|
||||
unsigned src_pitch);
|
||||
bitmapfont_lut_t *osd_font;
|
||||
/* Scaling/padding/cropping parameters */
|
||||
unsigned content_width;
|
||||
@ -71,6 +78,7 @@ typedef struct sdl_rs90_video
|
||||
unsigned frame_padding_y;
|
||||
unsigned frame_crop_x;
|
||||
unsigned frame_crop_y;
|
||||
enum dingux_rs90_softfilter_type softfilter_type;
|
||||
#if defined(DINGUX_BETA)
|
||||
enum dingux_refresh_rate refresh_rate;
|
||||
#endif
|
||||
@ -85,7 +93,380 @@ typedef struct sdl_rs90_video
|
||||
bool was_in_menu;
|
||||
bool quitting;
|
||||
bool mode_valid;
|
||||
} sdl_rs90_video_t;
|
||||
};
|
||||
|
||||
/* Image interpolation START */
|
||||
|
||||
static void sdl_rs90_scale_frame16_integer(sdl_rs90_video_t *vid,
|
||||
uint16_t *src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
/* 16 bit - divide pitch by 2 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 1);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 1);
|
||||
|
||||
/* Manipulate offsets so that padding/crop
|
||||
* are applied correctly */
|
||||
uint16_t *in_ptr = src + vid->frame_crop_x + vid->frame_crop_y * in_stride;
|
||||
uint16_t *out_ptr = (uint16_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
out_stride * vid->frame_padding_y;
|
||||
|
||||
size_t y = vid->frame_height;
|
||||
|
||||
/* TODO/FIXME: Optimize this loop */
|
||||
do
|
||||
{
|
||||
memcpy(out_ptr, in_ptr, vid->frame_width * sizeof(uint16_t));
|
||||
in_ptr += in_stride;
|
||||
out_ptr += out_stride;
|
||||
}
|
||||
while (--y);
|
||||
}
|
||||
|
||||
static void sdl_rs90_scale_frame32_integer(sdl_rs90_video_t *vid,
|
||||
uint32_t *src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
/* 32 bit - divide pitch by 4 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 2);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 2);
|
||||
|
||||
/* Manipulate offsets so that padding/crop
|
||||
* are applied correctly */
|
||||
uint32_t *in_ptr = src + vid->frame_crop_x + vid->frame_crop_y * in_stride;
|
||||
uint32_t *out_ptr = (uint32_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
out_stride * vid->frame_padding_y;
|
||||
|
||||
size_t y = vid->frame_height;
|
||||
|
||||
/* TODO/FIXME: Optimize this loop */
|
||||
do
|
||||
{
|
||||
memcpy(out_ptr, in_ptr, vid->frame_width * sizeof(uint32_t));
|
||||
in_ptr += in_stride;
|
||||
out_ptr += out_stride;
|
||||
}
|
||||
while (--y);
|
||||
}
|
||||
|
||||
/* Approximate nearest-neighbour scaling using
|
||||
* bitshifts and integer math */
|
||||
static void sdl_rs90_scale_frame16_point(sdl_rs90_video_t *vid,
|
||||
uint16_t *src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
uint32_t x_step = (((uint32_t)(width) << 16) + 1) / vid->frame_width;
|
||||
uint32_t y_step = (((uint32_t)(height) << 16) + 1) / vid->frame_height;
|
||||
|
||||
/* 16 bit - divide pitch by 2 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 1);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 1);
|
||||
|
||||
/* Apply x/y padding offset */
|
||||
uint16_t *top_corner = (uint16_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
out_stride * vid->frame_padding_y;
|
||||
|
||||
/* Temporary pointers */
|
||||
uint16_t *in_ptr = NULL;
|
||||
uint16_t *out_ptr = NULL;
|
||||
|
||||
uint32_t y = 0;
|
||||
size_t row;
|
||||
|
||||
/* TODO/FIXME: Optimize these loops further.
|
||||
* Consider saving these computations in an array
|
||||
* and indexing over them.
|
||||
* Would likely be slower due to cache (non-)locality,
|
||||
* but it's worth a shot.
|
||||
* Tons of -> operations. */
|
||||
for (row = 0; row < vid->frame_height; row++)
|
||||
{
|
||||
size_t col = vid->frame_width;
|
||||
uint32_t x = 0;
|
||||
|
||||
out_ptr = top_corner + out_stride * row;
|
||||
in_ptr = src + (y >> 16) * in_stride;
|
||||
|
||||
do
|
||||
{
|
||||
*(out_ptr++) = in_ptr[x >> 16];
|
||||
x += x_step;
|
||||
}
|
||||
while (--col);
|
||||
|
||||
y += y_step;
|
||||
}
|
||||
}
|
||||
|
||||
static void sdl_rs90_scale_frame32_point(sdl_rs90_video_t *vid,
|
||||
uint32_t *src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
uint32_t x_step = (((uint32_t)(width) << 16) + 1) / vid->frame_width;
|
||||
uint32_t y_step = (((uint32_t)(height) << 16) + 1) / vid->frame_height;
|
||||
|
||||
/* 32 bit - divide pitch by 4 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 2);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 2);
|
||||
|
||||
/* Apply x/y padding offset */
|
||||
uint32_t *top_corner = (uint32_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
out_stride * vid->frame_padding_y;
|
||||
|
||||
/* Temporary pointers */
|
||||
uint32_t *in_ptr = NULL;
|
||||
uint32_t *out_ptr = NULL;
|
||||
|
||||
uint32_t y = 0;
|
||||
size_t row;
|
||||
|
||||
/* TODO/FIXME: Optimize these loops further.
|
||||
* Consider saving these computations in an array
|
||||
* and indexing over them.
|
||||
* Would likely be slower due to cache (non-)locality,
|
||||
* but it's worth a shot.
|
||||
* Tons of -> operations. */
|
||||
for (row = 0; row < vid->frame_height; row++)
|
||||
{
|
||||
size_t col = vid->frame_width;
|
||||
uint32_t x = 0;
|
||||
|
||||
out_ptr = top_corner + out_stride * row;
|
||||
in_ptr = src + (y >> 16) * in_stride;
|
||||
|
||||
do
|
||||
{
|
||||
*(out_ptr++) = in_ptr[x >> 16];
|
||||
x += x_step;
|
||||
}
|
||||
while (--col);
|
||||
|
||||
y += y_step;
|
||||
}
|
||||
}
|
||||
|
||||
/* Produces a 50:50 mix of pixels a and b
|
||||
* > c.f. "Mixing Packed RGB Pixels Efficiently"
|
||||
* http://blargg.8bitalley.com/info/rgb_mixing.html */
|
||||
#define SDL_RS90_PIXEL_AVERAGE_16(a, b) (((a) + (b) + (((a) ^ (b)) & 0x821)) >> 1)
|
||||
#define SDL_RS90_PIXEL_AVERAGE_32(a, b) (((a) + (b) + (((a) ^ (b)) & 0x10101)) >> 1)
|
||||
|
||||
/* Scales a single horizontal line using approximate
|
||||
* linear scaling
|
||||
* > c.f. "Image Scaling with Bresenham"
|
||||
* https://www.drdobbs.com/image-scaling-with-bresenham/184405045 */
|
||||
static void sdl_rs90_scale_line_bresenham16(uint16_t *target, uint16_t *src,
|
||||
unsigned src_width, unsigned target_width,
|
||||
unsigned int_part, unsigned fract_part, unsigned midpoint)
|
||||
{
|
||||
unsigned num_pixels = target_width;
|
||||
unsigned E = 0; /* TODO/FIXME: Determine better variable name - 'error'? */
|
||||
|
||||
/* If source and target have the same width,
|
||||
* can perform a fast copy of raw pixel data */
|
||||
if (src_width == target_width)
|
||||
{
|
||||
memcpy(target, src, target_width * sizeof(uint16_t));
|
||||
return;
|
||||
}
|
||||
else if (target_width > src_width)
|
||||
num_pixels--;
|
||||
|
||||
do
|
||||
{
|
||||
*(target++) = (E >= midpoint) ?
|
||||
SDL_RS90_PIXEL_AVERAGE_16(*src, *(src + 1)) : *src;
|
||||
|
||||
src += int_part;
|
||||
E += fract_part;
|
||||
|
||||
if (E >= target_width)
|
||||
{
|
||||
E -= target_width;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
while (--num_pixels);
|
||||
|
||||
if (target_width > src_width)
|
||||
*target = *src;
|
||||
}
|
||||
|
||||
static void sdl_rs90_scale_frame16_bresenham_horz(sdl_rs90_video_t *vid,
|
||||
uint16_t *src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
/* 16 bit - divide pitch by 2 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 1);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 1);
|
||||
|
||||
uint16_t *prev_src = NULL;
|
||||
|
||||
/* Account for x/y padding */
|
||||
uint16_t *target = (uint16_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
(out_stride * vid->frame_padding_y);
|
||||
unsigned target_width = vid->frame_width;
|
||||
unsigned target_height = vid->frame_height;
|
||||
|
||||
unsigned num_lines = target_height;
|
||||
unsigned int_part = (height / target_height) * in_stride;
|
||||
unsigned fract_part = height % target_height;
|
||||
unsigned E = 0; /* TODO/FIXME: Determine better variable name - 'error'? */
|
||||
|
||||
unsigned col_int_part = width / target_width;
|
||||
unsigned col_fract_part = width % target_width;
|
||||
/* Enhance midpoint selection as described in
|
||||
* https://www.compuphase.com/graphic/scale1errata.htm */
|
||||
int col_midpoint = (target_width > width) ?
|
||||
((int)target_width - 3 * ((int)target_width - (int)width)) >> 1 :
|
||||
(int)(target_width << 1) - (int)width;
|
||||
/* Clamp lower bound to (target_width / 2) */
|
||||
if (col_midpoint < (int)(target_width >> 1))
|
||||
col_midpoint = (int)(target_width >> 1);
|
||||
|
||||
while (num_lines--)
|
||||
{
|
||||
/* If line is supposed to be identical to
|
||||
* previous line, just copy it */
|
||||
if (src == prev_src)
|
||||
memcpy(target, target - out_stride, target_width * sizeof(uint16_t));
|
||||
else
|
||||
{
|
||||
sdl_rs90_scale_line_bresenham16(target, src, width, target_width,
|
||||
col_int_part, col_fract_part, (unsigned)col_midpoint);
|
||||
prev_src = src;
|
||||
}
|
||||
|
||||
target += out_stride;
|
||||
src += int_part;
|
||||
E += fract_part;
|
||||
|
||||
if (E >= target_height)
|
||||
{
|
||||
E -= target_height;
|
||||
src += in_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sdl_rs90_scale_line_bresenham32(uint32_t *target, uint32_t *src,
|
||||
unsigned src_width, unsigned target_width,
|
||||
unsigned int_part, unsigned fract_part, unsigned midpoint)
|
||||
{
|
||||
unsigned num_pixels = target_width;
|
||||
unsigned E = 0; /* TODO/FIXME: Determine better variable name - 'error'? */
|
||||
|
||||
/* If source and target have the same width,
|
||||
* can perform a fast copy of raw pixel data */
|
||||
if (src_width == target_width)
|
||||
{
|
||||
memcpy(target, src, target_width * sizeof(uint32_t));
|
||||
return;
|
||||
}
|
||||
else if (target_width > src_width)
|
||||
num_pixels--;
|
||||
|
||||
do
|
||||
{
|
||||
*(target++) = (E >= midpoint) ?
|
||||
SDL_RS90_PIXEL_AVERAGE_32(*src, *(src + 1)) : *src;
|
||||
|
||||
src += int_part;
|
||||
E += fract_part;
|
||||
|
||||
if (E >= target_width)
|
||||
{
|
||||
E -= target_width;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
while (--num_pixels);
|
||||
|
||||
if (target_width > src_width)
|
||||
*target = *src;
|
||||
}
|
||||
|
||||
static void sdl_rs90_scale_frame32_bresenham_horz(sdl_rs90_video_t *vid,
|
||||
uint32_t *src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
/* 32 bit - divide pitch by 4 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 2);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 2);
|
||||
|
||||
uint32_t *prev_src = NULL;
|
||||
|
||||
/* Account for x/y padding */
|
||||
uint32_t *target = (uint32_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
(out_stride * vid->frame_padding_y);
|
||||
unsigned target_width = vid->frame_width;
|
||||
unsigned target_height = vid->frame_height;
|
||||
|
||||
unsigned num_lines = target_height;
|
||||
unsigned int_part = (height / target_height) * in_stride;
|
||||
unsigned fract_part = height % target_height;
|
||||
unsigned E = 0; /* TODO/FIXME: Determine better variable name - 'error'? */
|
||||
|
||||
unsigned col_int_part = width / target_width;
|
||||
unsigned col_fract_part = width % target_width;
|
||||
/* Enhance midpoint selection as described in
|
||||
* https://www.compuphase.com/graphic/scale1errata.htm */
|
||||
int col_midpoint = (target_width > width) ?
|
||||
((int)target_width - 3 * ((int)target_width - (int)width)) >> 1 :
|
||||
(int)(target_width << 1) - (int)width;
|
||||
/* Clamp lower bound to (target_width / 2) */
|
||||
if (col_midpoint < (int)(target_width >> 1))
|
||||
col_midpoint = (int)(target_width >> 1);
|
||||
|
||||
while (num_lines--)
|
||||
{
|
||||
/* If line is supposed to be identical to
|
||||
* previous line, just copy it */
|
||||
if (src == prev_src)
|
||||
memcpy(target, target - out_stride, target_width * sizeof(uint32_t));
|
||||
else
|
||||
{
|
||||
sdl_rs90_scale_line_bresenham32(target, src, width, target_width,
|
||||
col_int_part, col_fract_part, (unsigned)col_midpoint);
|
||||
prev_src = src;
|
||||
}
|
||||
|
||||
target += out_stride;
|
||||
src += int_part;
|
||||
E += fract_part;
|
||||
|
||||
if (E >= target_height)
|
||||
{
|
||||
E -= target_height;
|
||||
src += in_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sdl_rs90_set_scale_frame_functions(sdl_rs90_video_t *vid)
|
||||
{
|
||||
/* Set integer scaling by default */
|
||||
vid->scale_frame16 = sdl_rs90_scale_frame16_integer;
|
||||
vid->scale_frame32 = sdl_rs90_scale_frame32_integer;
|
||||
|
||||
if (!vid->scale_integer)
|
||||
{
|
||||
switch (vid->softfilter_type)
|
||||
{
|
||||
case DINGUX_RS90_SOFTFILTER_BRESENHAM_HORZ:
|
||||
vid->scale_frame16 = sdl_rs90_scale_frame16_bresenham_horz;
|
||||
vid->scale_frame32 = sdl_rs90_scale_frame32_bresenham_horz;
|
||||
break;
|
||||
case DINGUX_RS90_SOFTFILTER_POINT:
|
||||
default:
|
||||
vid->scale_frame16 = sdl_rs90_scale_frame16_point;
|
||||
vid->scale_frame32 = sdl_rs90_scale_frame32_point;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Image interpolation END */
|
||||
|
||||
static void sdl_rs90_init_font_color(sdl_rs90_video_t *vid)
|
||||
{
|
||||
@ -496,6 +877,8 @@ static void *sdl_rs90_gfx_init(const video_info_t *video,
|
||||
vid->vsync = video->vsync;
|
||||
vid->keep_aspect = settings->bools.video_dingux_ipu_keep_aspect;
|
||||
vid->scale_integer = settings->bools.video_scale_integer;
|
||||
vid->softfilter_type = (enum dingux_rs90_softfilter_type)
|
||||
settings->uints.video_dingux_rs90_softfilter_type;
|
||||
vid->menu_active = false;
|
||||
vid->was_in_menu = false;
|
||||
vid->quitting = false;
|
||||
@ -520,6 +903,9 @@ static void *sdl_rs90_gfx_init(const video_info_t *video,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Assign frame scaling function pointers */
|
||||
sdl_rs90_set_scale_frame_functions(vid);
|
||||
|
||||
return vid;
|
||||
|
||||
error:
|
||||
@ -638,82 +1024,6 @@ static void sdl_rs90_set_output(
|
||||
}
|
||||
}
|
||||
|
||||
/* Approximate nearest-neighbour scaling using
|
||||
* bitshifts and integer math */
|
||||
static void sdl_rs90_blit_frame16_scale(sdl_rs90_video_t *vid,
|
||||
uint16_t* src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
uint32_t x_step = (((uint32_t)(width) << 16) + 1) / vid->frame_width;
|
||||
uint32_t y_step = (((uint32_t)(height) << 16) + 1) / vid->frame_height;
|
||||
|
||||
/* 16 bit - divide pitch by 2 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 1);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 1);
|
||||
|
||||
/* Apply x/y padding offset */
|
||||
uint16_t *top_corner = (uint16_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
out_stride * vid->frame_padding_y;
|
||||
|
||||
/* Temporary pointers */
|
||||
uint16_t *in_ptr = NULL;
|
||||
uint16_t *out_ptr = NULL;
|
||||
|
||||
uint32_t y = 0;
|
||||
size_t row;
|
||||
|
||||
/* TODO/FIXME: Optimize these loops further.
|
||||
* Consider saving these computations in an array
|
||||
* and indexing over them.
|
||||
* Would likely be slower due to cache (non-)locality,
|
||||
* but it's worth a shot.
|
||||
* Tons of -> operations. */
|
||||
for (row = 0; row < vid->frame_height; row++)
|
||||
{
|
||||
size_t col = vid->frame_width;
|
||||
uint32_t x = 0;
|
||||
|
||||
out_ptr = top_corner + out_stride * row;
|
||||
in_ptr = src + (y >> 16) * in_stride;
|
||||
|
||||
do
|
||||
{
|
||||
*out_ptr = in_ptr[x >> 16];
|
||||
x += x_step;
|
||||
out_ptr++;
|
||||
}
|
||||
while (--col);
|
||||
|
||||
y += y_step;
|
||||
}
|
||||
}
|
||||
|
||||
static void sdl_rs90_blit_frame16_no_scale(sdl_rs90_video_t *vid,
|
||||
uint16_t* src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
/* 16 bit - divide pitch by 2 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 1);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 1);
|
||||
|
||||
/* Manipulate offsets so that padding/crop
|
||||
* are applied correctly */
|
||||
uint16_t *in_ptr = src + vid->frame_crop_x + vid->frame_crop_y * in_stride;
|
||||
uint16_t *out_ptr = (uint16_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
out_stride * vid->frame_padding_y;
|
||||
|
||||
size_t y = vid->frame_height;
|
||||
|
||||
/* TODO/FIXME: Optimize this loop */
|
||||
do
|
||||
{
|
||||
memcpy(out_ptr, in_ptr, vid->frame_width * sizeof(uint16_t));
|
||||
in_ptr += in_stride;
|
||||
out_ptr += out_stride;
|
||||
}
|
||||
while (--y);
|
||||
}
|
||||
|
||||
static void sdl_rs90_blit_frame16(sdl_rs90_video_t *vid,
|
||||
uint16_t* src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
@ -726,88 +1036,7 @@ static void sdl_rs90_blit_frame16(sdl_rs90_video_t *vid,
|
||||
height == SDL_RS90_HEIGHT)
|
||||
memcpy(vid->screen->pixels, src, src_pitch * SDL_RS90_HEIGHT);
|
||||
else
|
||||
{
|
||||
if (vid->scale_integer)
|
||||
sdl_rs90_blit_frame16_no_scale(
|
||||
vid, src, width, height, src_pitch);
|
||||
else
|
||||
sdl_rs90_blit_frame16_scale(
|
||||
vid, src, width, height, src_pitch);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdl_rs90_blit_frame32_scale(sdl_rs90_video_t *vid,
|
||||
uint32_t* src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
uint32_t x_step = (((uint32_t)(width) << 16) + 1) / vid->frame_width;
|
||||
uint32_t y_step = (((uint32_t)(height) << 16) + 1) / vid->frame_height;
|
||||
|
||||
/* 32 bit - divide pitch by 4 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 2);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 2);
|
||||
|
||||
/* Apply x/y padding offset */
|
||||
uint32_t *top_corner = (uint32_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
out_stride * vid->frame_padding_y;
|
||||
|
||||
/* Temporary pointers */
|
||||
uint32_t *in_ptr = NULL;
|
||||
uint32_t *out_ptr = NULL;
|
||||
|
||||
uint32_t y = 0;
|
||||
size_t row;
|
||||
|
||||
/* TODO/FIXME: Optimize these loops further.
|
||||
* Consider saving these computations in an array
|
||||
* and indexing over them.
|
||||
* Would likely be slower due to cache (non-)locality,
|
||||
* but it's worth a shot.
|
||||
* Tons of -> operations. */
|
||||
for (row = 0; row < vid->frame_height; row++)
|
||||
{
|
||||
size_t col = vid->frame_width;
|
||||
uint32_t x = 0;
|
||||
|
||||
out_ptr = top_corner + out_stride * row;
|
||||
in_ptr = src + (y >> 16) * in_stride;
|
||||
|
||||
do
|
||||
{
|
||||
*out_ptr = in_ptr[x >> 16];
|
||||
x += x_step;
|
||||
out_ptr++;
|
||||
}
|
||||
while (--col);
|
||||
|
||||
y += y_step;
|
||||
}
|
||||
}
|
||||
|
||||
static void sdl_rs90_blit_frame32_no_scale(sdl_rs90_video_t *vid,
|
||||
uint32_t* src, unsigned width, unsigned height,
|
||||
unsigned src_pitch)
|
||||
{
|
||||
/* 32 bit - divide pitch by 4 */
|
||||
size_t in_stride = (size_t)(src_pitch >> 2);
|
||||
size_t out_stride = (size_t)(vid->screen->pitch >> 2);
|
||||
|
||||
/* Manipulate offsets so that padding/crop
|
||||
* are applied correctly */
|
||||
uint32_t *in_ptr = src + vid->frame_crop_x + vid->frame_crop_y * in_stride;
|
||||
uint32_t *out_ptr = (uint32_t*)(vid->screen->pixels) + vid->frame_padding_x +
|
||||
out_stride * vid->frame_padding_y;
|
||||
|
||||
size_t y = vid->frame_height;
|
||||
|
||||
/* TODO/FIXME: Optimize this loop */
|
||||
do
|
||||
{
|
||||
memcpy(out_ptr, in_ptr, vid->frame_width * sizeof(uint32_t));
|
||||
in_ptr += in_stride;
|
||||
out_ptr += out_stride;
|
||||
}
|
||||
while (--y);
|
||||
vid->scale_frame16(vid, src, width, height, src_pitch);
|
||||
}
|
||||
|
||||
static void sdl_rs90_blit_frame32(sdl_rs90_video_t *vid,
|
||||
@ -822,14 +1051,7 @@ static void sdl_rs90_blit_frame32(sdl_rs90_video_t *vid,
|
||||
(height == SDL_RS90_HEIGHT))
|
||||
memcpy(vid->screen->pixels, src, src_pitch * SDL_RS90_HEIGHT);
|
||||
else
|
||||
{
|
||||
if (vid->scale_integer)
|
||||
sdl_rs90_blit_frame32_no_scale(
|
||||
vid, src, width, height, src_pitch);
|
||||
else
|
||||
sdl_rs90_blit_frame32_scale(
|
||||
vid, src, width, height, src_pitch);
|
||||
}
|
||||
vid->scale_frame32(vid, src, width, height, src_pitch);
|
||||
}
|
||||
|
||||
static bool sdl_rs90_gfx_frame(void *data, const void *frame,
|
||||
@ -1096,6 +1318,25 @@ static float sdl_rs90_get_refresh_rate(void *data)
|
||||
return 60.0f;
|
||||
}
|
||||
|
||||
static void sdl_rs90_set_filtering(void *data, unsigned index, bool smooth, bool ctx_scaling)
|
||||
{
|
||||
sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
|
||||
settings_t *settings = config_get_ptr();
|
||||
enum dingux_rs90_softfilter_type softfilter_type = (settings) ?
|
||||
(enum dingux_rs90_softfilter_type)settings->uints.video_dingux_rs90_softfilter_type :
|
||||
DINGUX_RS90_SOFTFILTER_POINT;
|
||||
|
||||
if (!vid || !settings)
|
||||
return;
|
||||
|
||||
/* Update software filter setting, if required */
|
||||
if (vid->softfilter_type != softfilter_type)
|
||||
{
|
||||
vid->softfilter_type = softfilter_type;
|
||||
sdl_rs90_set_scale_frame_functions(vid);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdl_rs90_apply_state_changes(void *data)
|
||||
{
|
||||
sdl_rs90_video_t *vid = (sdl_rs90_video_t*)data;
|
||||
@ -1112,12 +1353,17 @@ static void sdl_rs90_apply_state_changes(void *data)
|
||||
vid->keep_aspect = keep_aspect;
|
||||
vid->scale_integer = integer_scaling;
|
||||
|
||||
/* Reassign frame scaling function pointers */
|
||||
sdl_rs90_set_scale_frame_functions(vid);
|
||||
|
||||
/* Aspect/scaling changes require all frame
|
||||
* dimension/padding/cropping parameters to
|
||||
* be recalculated. Easiest method is to just
|
||||
* (re-)set the current output video mode */
|
||||
* (re-)set the current output video mode
|
||||
* Note: If menu is active, colour depth is
|
||||
* overridden to 16 bit */
|
||||
sdl_rs90_set_output(vid, vid->content_width,
|
||||
vid->content_height, vid->rgb32);
|
||||
vid->content_height, vid->menu_active ? false : vid->rgb32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1132,7 +1378,7 @@ static const video_poke_interface_t sdl_rs90_poke_interface = {
|
||||
NULL,
|
||||
NULL,
|
||||
sdl_rs90_get_refresh_rate,
|
||||
NULL, /* set_filtering */
|
||||
sdl_rs90_set_filtering,
|
||||
NULL, /* get_video_output_size */
|
||||
NULL, /* get_video_output_prev */
|
||||
NULL, /* get_video_output_next */
|
||||
|
@ -3181,6 +3181,12 @@ MSG_HASH(
|
||||
"video_dingux_refresh_rate"
|
||||
)
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE,
|
||||
"video_dingux_rs90_softfilter_type"
|
||||
)
|
||||
#endif
|
||||
#endif
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VIDEO_BLACK_FRAME_INSERTION,
|
||||
|
@ -1373,6 +1373,24 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_IPU_FILTER_NEAREST,
|
||||
"Nearest Neighbor"
|
||||
)
|
||||
#if defined(RS90)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE,
|
||||
"Image Interpolation"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE,
|
||||
"Specify image interpolation method when 'Integer Scale' is disabled. 'Nearest Neighbor' has the least performance impact."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_RS90_SOFTFILTER_POINT,
|
||||
"Nearest Neighbor"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_RS90_SOFTFILTER_BRESENHAM_HORZ,
|
||||
"Semi-Linear"
|
||||
)
|
||||
#endif
|
||||
#endif
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_DELAY,
|
||||
|
@ -872,6 +872,9 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_dingux_ipu_filter_type,
|
||||
#if defined(DINGUX_BETA)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_dingux_refresh_rate, MENU_ENUM_SUBLABEL_VIDEO_DINGUX_REFRESH_RATE)
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_dingux_rs90_softfilter_type, MENU_ENUM_SUBLABEL_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE)
|
||||
#endif
|
||||
#endif
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_viewport_custom_height, MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_HEIGHT)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_viewport_custom_width, MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_WIDTH)
|
||||
@ -1968,6 +1971,11 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_dingux_refresh_rate);
|
||||
break;
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
case MENU_ENUM_LABEL_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_dingux_rs90_softfilter_type);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case MENU_ENUM_LABEL_CORE_INFORMATION:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_information);
|
||||
|
@ -416,6 +416,15 @@ enum quit_on_close_content_type
|
||||
QUIT_ON_CLOSE_CONTENT_LAST
|
||||
};
|
||||
|
||||
#if defined(DINGUX) && defined(RS90)
|
||||
enum dingux_rs90_softfilter_type
|
||||
{
|
||||
DINGUX_RS90_SOFTFILTER_POINT = 0,
|
||||
DINGUX_RS90_SOFTFILTER_BRESENHAM_HORZ,
|
||||
DINGUX_RS90_SOFTFILTER_LAST
|
||||
};
|
||||
#endif
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -6028,6 +6028,12 @@ unsigned menu_displaylist_build_list(
|
||||
MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_FILTER_TYPE,
|
||||
PARSE_ONLY_UINT, false) == 0)
|
||||
count++;
|
||||
#if defined(RS90)
|
||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
MENU_ENUM_LABEL_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE,
|
||||
PARSE_ONLY_UINT, false) == 0)
|
||||
count++;
|
||||
#endif
|
||||
#endif
|
||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
MENU_ENUM_LABEL_VIDEO_SHADER_DELAY,
|
||||
|
@ -5200,6 +5200,32 @@ static void setting_get_string_representation_uint_video_dingux_refresh_rate(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RS90)
|
||||
static void setting_get_string_representation_uint_video_dingux_rs90_softfilter_type(
|
||||
rarch_setting_t *setting,
|
||||
char *s, size_t len)
|
||||
{
|
||||
if (!setting)
|
||||
return;
|
||||
|
||||
switch (*setting->value.target.unsigned_integer)
|
||||
{
|
||||
case DINGUX_RS90_SOFTFILTER_POINT:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_RS90_SOFTFILTER_POINT),
|
||||
len);
|
||||
break;
|
||||
case DINGUX_RS90_SOFTFILTER_BRESENHAM_HORZ:
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_RS90_SOFTFILTER_BRESENHAM_HORZ),
|
||||
len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void setting_get_string_representation_uint_input_auto_game_focus(
|
||||
@ -7615,10 +7641,14 @@ static void general_write_handler(rarch_setting_t *setting)
|
||||
case MENU_ENUM_LABEL_VIDEO_CTX_SCALING:
|
||||
#if defined(DINGUX)
|
||||
case MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_FILTER_TYPE:
|
||||
#if defined(RS90)
|
||||
case MENU_ENUM_LABEL_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE:
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
video_driver_set_filtering(1, settings->bools.video_ctx_scaling, settings->bools.video_ctx_scaling);
|
||||
video_driver_set_filtering(1, settings->bools.video_smooth,
|
||||
settings->bools.video_ctx_scaling);
|
||||
}
|
||||
break;
|
||||
case MENU_ENUM_LABEL_VIDEO_ROTATION:
|
||||
@ -11482,7 +11512,28 @@ static bool setting_append_list(
|
||||
menu_settings_list_current_add_range(list, list_info, 0, DINGUX_IPU_FILTER_LAST - 1, 1, true, true);
|
||||
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX;
|
||||
}
|
||||
else if (!string_is_equal(settings->arrays.video_driver, "sdl_rs90"))
|
||||
#if defined(RS90)
|
||||
else if (string_is_equal(settings->arrays.video_driver, "sdl_rs90"))
|
||||
{
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->uints.video_dingux_rs90_softfilter_type,
|
||||
MENU_ENUM_LABEL_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE,
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE,
|
||||
DEFAULT_DINGUX_RS90_SOFTFILTER_TYPE,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
(*list)[list_info->index - 1].get_string_representation =
|
||||
&setting_get_string_representation_uint_video_dingux_rs90_softfilter_type;
|
||||
menu_settings_list_current_add_range(list, list_info, 0, DINGUX_RS90_SOFTFILTER_LAST - 1, 1, true, true);
|
||||
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
#endif
|
||||
{
|
||||
CONFIG_BOOL(
|
||||
|
@ -2474,6 +2474,12 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_REFRESH_RATE_60HZ,
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_REFRESH_RATE_50HZ,
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
MENU_LABEL(VIDEO_DINGUX_RS90_SOFTFILTER_TYPE),
|
||||
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_RS90_SOFTFILTER_POINT,
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_RS90_SOFTFILTER_BRESENHAM_HORZ,
|
||||
#endif
|
||||
#endif
|
||||
MENU_LABEL(VIDEO_VFILTER),
|
||||
MENU_LABEL(VIDEO_GPU_RECORD),
|
||||
|
Loading…
x
Reference in New Issue
Block a user