Add filters support to the gtk frontend

From Alberto, #3603211
This commit is contained in:
riccardom 2013-02-15 21:01:03 +00:00
parent 6acaab2bf5
commit ee6501fbc0
3 changed files with 107 additions and 27 deletions

View File

@ -28,7 +28,7 @@
#include "NDSSystem.h"
#include "utils/xstring.h"
int scanline_filter_a = 0, scanline_filter_b = 2, scanline_filter_c = 2, scanline_filter_d = 4;
int _scanline_filter_a = 0, _scanline_filter_b = 2, _scanline_filter_c = 2, _scanline_filter_d = 4;
int _commandline_linux_nojoy = 0;
CommandLine::CommandLine()
@ -91,10 +91,10 @@ void CommandLine::loadCommonOptions()
{ "bios-swi", 0, 0, G_OPTION_ARG_INT, &_bios_swi, "Uses SWI from the provided bios files", "BIOS_SWI"},
{ "spu-advanced", 0, 0, G_OPTION_ARG_INT, &_spu_advanced, "Uses advanced SPU capture functions", "SPU_ADVANCED"},
{ "num-cores", 0, 0, G_OPTION_ARG_INT, &_num_cores, "Override numcores detection and use this many", "NUM_CORES"},
{ "scanline-filter-a", 0, 0, G_OPTION_ARG_INT, &scanline_filter_a, "Intensity of fadeout for scanlines filter (topleft) (default 0)", "SCANLINE_FILTER_A"},
{ "scanline-filter-b", 0, 0, G_OPTION_ARG_INT, &scanline_filter_b, "Intensity of fadeout for scanlines filter (topright) (default 2)", "SCANLINE_FILTER_B"},
{ "scanline-filter-c", 0, 0, G_OPTION_ARG_INT, &scanline_filter_c, "Intensity of fadeout for scanlines filter (bottomleft) (default 2)", "SCANLINE_FILTER_C"},
{ "scanline-filter-d", 0, 0, G_OPTION_ARG_INT, &scanline_filter_d, "Intensity of fadeout for scanlines filter (bottomright) (default 4)", "SCANLINE_FILTER_D"},
{ "scanline-filter-a", 0, 0, G_OPTION_ARG_INT, &_scanline_filter_a, "Intensity of fadeout for scanlines filter (topleft) (default 0)", "SCANLINE_FILTER_A"},
{ "scanline-filter-b", 0, 0, G_OPTION_ARG_INT, &_scanline_filter_b, "Intensity of fadeout for scanlines filter (topright) (default 2)", "SCANLINE_FILTER_B"},
{ "scanline-filter-c", 0, 0, G_OPTION_ARG_INT, &_scanline_filter_c, "Intensity of fadeout for scanlines filter (bottomleft) (default 2)", "SCANLINE_FILTER_C"},
{ "scanline-filter-d", 0, 0, G_OPTION_ARG_INT, &_scanline_filter_d, "Intensity of fadeout for scanlines filter (bottomright) (default 4)", "SCANLINE_FILTER_D"},
{ "rigorous-timing", 0, 0, G_OPTION_ARG_INT, &_rigorous_timing, "Use some rigorous timings instead of unrealistically generous (default 0)", "RIGOROUS_TIMING"},
{ "advanced-timing", 0, 0, G_OPTION_ARG_INT, &_advanced_timing, "Use advanced BUS-level timing (default 1)", "ADVANCED_TIMING"},
{ "slot1", 0, 0, G_OPTION_ARG_STRING, &_slot1, "Device to load in slot 1 (default retail)", "SLOT1"},

View File

@ -18,6 +18,12 @@ desmume_SOURCES = \
../driver.h ../driver.cpp \
osmesa_3Demu.cpp osmesa_3Demu.h \
cheatsGTK.h cheatsGTK.cpp \
../filter/hq2x.cpp ../filter/hq2x.h \
../filter/hq4x.cpp ../filter/hq4x.h \
../filter/2xsai.cpp ../filter/bilinear.cpp \
../filter/epx.cpp ../filter/lq2x.cpp \
../filter/scanline.cpp \
../filter/videofilter.cpp ../filter/videofilter.h \
main.cpp main.h
desmume_LDADD = ../libdesmume.a \
$(SDL_LIBS) $(GTK_LIBS) $(GTHREAD_LIBS) $(ALSA_LIBS) $(LIBAGG_LIBS) $(LIBSOUNDTOUCH_LIBS)

View File

@ -53,6 +53,8 @@
#include "addons.h"
#include "filter/videofilter.h"
#ifdef GDB_STUB
#include "gdbstub.h"
#endif
@ -81,6 +83,8 @@
#define FPS_LIMITER_FRAME_PERIOD 8
static SDL_sem *fps_limiter_semaphore;
static int gtk_fps_limiter_disabled;
extern int _scanline_filter_a, _scanline_filter_b, _scanline_filter_c, _scanline_filter_d;
VideoFilter video(256, 384, VideoFilterTypeID_HQ2XS, 4);
enum {
MAIN_BG_0 = 0,
@ -237,9 +241,31 @@ static const char *ui_description =
" <separator/>"
" <menuitem action='orient_swapscreens'/>"
" </menu>"
" <menu action='PriInterpolationMenu'>"
" <menuitem action='pri_interp_none'/>"
" <menuitem action='pri_interp_nearest2x'/>"
" <menuitem action='pri_interp_lq2x'/>"
" <menuitem action='pri_interp_lq2xs'/>"
" <menuitem action='pri_interp_hq2x'/>"
" <menuitem action='pri_interp_hq4x'/>"
" <menuitem action='pri_interp_hq2xs'/>"
" <menuitem action='pri_interp_2xsai'/>"
" <menuitem action='pri_interp_super2xsai'/>"
" <menuitem action='pri_interp_supereagle'/>"
" <menuitem action='pri_interp_scanline'/>"
" <menuitem action='pri_interp_bilinear'/>"
" <menuitem action='pri_interp_epx'/>"
" <menuitem action='pri_interp_epxplus'/>"
" <menuitem action='pri_interp_epx_1point5x'/>"
" <menuitem action='pri_interp_epxplus_1point5x'/>"
" <menuitem action='pri_interp_nearest_1point5x'/>"
" <menuitem action='pri_interp_nearestplus_1point5x'/>"
" </menu>"
" <menu action='InterpolationMenu'>"
" <menuitem action='interp_nearest'/>"
" <menuitem action='interp_tiles'/>"
" <menuitem action='interp_bilinear'/>"
" <menuitem action='interp_hyper'/>"
" </menu>"
" <menuitem action='gap'/>"
" <menuitem action='editctrls'/>"
@ -300,7 +326,8 @@ static const GtkActionEntry action_entries[] = {
{ "editjoyctrls", NULL, "Edit _Joystick controls",NULL, NULL, Edit_Joystick_Controls },
{ "RotationMenu", NULL, "_Rotation" },
{ "OrientationMenu", NULL, "_Orientation" },
{ "InterpolationMenu", NULL, "_Interpolation" },
{ "PriInterpolationMenu", NULL, "Primary _Interpolation" },
{ "InterpolationMenu", NULL, "Secondary _Interpolation" },
{ "ViewMenu", NULL, "_View" },
{ "ToolsMenu", NULL, "_Tools" },
@ -322,9 +349,32 @@ static const GtkToggleActionEntry toggle_entries[] = {
{ "fullscreen", NULL, "Fullscreen", "<Ctrl>f", NULL, G_CALLBACK(ToggleFullscreen), FALSE},
};
static const GtkRadioActionEntry pri_interpolation_entries[] = {
{ "pri_interp_none", NULL, VideoFilterAttributesList[VideoFilterTypeID_None].typeString, NULL, NULL, VideoFilterTypeID_None},
{ "pri_interp_nearest2x", NULL, VideoFilterAttributesList[VideoFilterTypeID_Nearest2X].typeString, NULL, NULL, VideoFilterTypeID_Nearest2X},
{ "pri_interp_lq2x", NULL, VideoFilterAttributesList[VideoFilterTypeID_LQ2X].typeString, NULL, NULL, VideoFilterTypeID_LQ2X},
{ "pri_interp_lq2xs", NULL, VideoFilterAttributesList[VideoFilterTypeID_LQ2XS].typeString, NULL, NULL, VideoFilterTypeID_LQ2XS},
{ "pri_interp_hq2x", NULL, VideoFilterAttributesList[VideoFilterTypeID_HQ2X].typeString, NULL, NULL, VideoFilterTypeID_HQ2X},
{ "pri_interp_hq4x", NULL, VideoFilterAttributesList[VideoFilterTypeID_HQ4X].typeString, NULL, NULL, VideoFilterTypeID_HQ4X},
{ "pri_interp_hq2xs", NULL, VideoFilterAttributesList[VideoFilterTypeID_HQ2XS].typeString, NULL, NULL, VideoFilterTypeID_HQ2XS},
{ "pri_interp_2xsai", NULL, VideoFilterAttributesList[VideoFilterTypeID_2xSaI].typeString, NULL, NULL, VideoFilterTypeID_2xSaI},
{ "pri_interp_super2xsai", NULL, VideoFilterAttributesList[VideoFilterTypeID_Super2xSaI].typeString, NULL, NULL, VideoFilterTypeID_Super2xSaI},
{ "pri_interp_supereagle", NULL, VideoFilterAttributesList[VideoFilterTypeID_SuperEagle].typeString, NULL, NULL, VideoFilterTypeID_SuperEagle},
{ "pri_interp_scanline", NULL, VideoFilterAttributesList[VideoFilterTypeID_Scanline].typeString, NULL, NULL, VideoFilterTypeID_Scanline},
{ "pri_interp_bilinear", NULL, VideoFilterAttributesList[VideoFilterTypeID_Bilinear].typeString, NULL, NULL, VideoFilterTypeID_Bilinear},
{ "pri_interp_epx", NULL, VideoFilterAttributesList[VideoFilterTypeID_EPX].typeString, NULL, NULL, VideoFilterTypeID_EPX},
{ "pri_interp_epxplus", NULL, VideoFilterAttributesList[VideoFilterTypeID_EPXPlus].typeString, NULL, NULL, VideoFilterTypeID_EPXPlus},
{ "pri_interp_epx_1point5x", NULL, VideoFilterAttributesList[VideoFilterTypeID_EPX1_5X].typeString, NULL, NULL, VideoFilterTypeID_EPX1_5X},
{ "pri_interp_epxplus_1point5x", NULL, VideoFilterAttributesList[VideoFilterTypeID_EPXPlus1_5X].typeString, NULL, NULL, VideoFilterTypeID_EPXPlus1_5X},
{ "pri_interp_nearest_1point5x", NULL, VideoFilterAttributesList[VideoFilterTypeID_Nearest1_5X].typeString, NULL, NULL, VideoFilterTypeID_Nearest1_5X},
{ "pri_interp_nearestplus_1point5x", NULL, VideoFilterAttributesList[VideoFilterTypeID_NearestPlus1_5X].typeString, NULL, NULL, VideoFilterTypeID_NearestPlus1_5X},
};
static const GtkRadioActionEntry interpolation_entries[] = {
{ "interp_nearest", NULL, "_Nearest", NULL, NULL, 0},
{ "interp_bilinear", NULL, "_Bilinear", NULL, NULL, 1},
{ "interp_nearest", NULL, "_Nearest", NULL, NULL, GDK_INTERP_NEAREST},
{ "interp_tiles", NULL, "_Tiles", NULL, NULL, GDK_INTERP_TILES},
{ "interp_bilinear", NULL, "_Bilinear", NULL, NULL, GDK_INTERP_BILINEAR},
{ "interp_hyper", NULL, "_Hyper", NULL, NULL, GDK_INTERP_HYPER},
};
static const GtkRadioActionEntry rotation_entries[] = {
@ -582,7 +632,7 @@ joinThread_gdb( void *thread_handle) {
uint SPUMode = SPUMODE_DUALASYNC;
uint Frameskip = 0;
bool autoframeskip = false;
GdkInterpType Interpolation = GDK_INTERP_BILINEAR;
GdkInterpType Interpolation = GDK_INTERP_NEAREST;
static GtkWidget *pWindow;
static GtkWidget *pStatusBar;
@ -1094,6 +1144,7 @@ static void UpdateDrawingAreaAspect()
}
}
video.SetSourceSize(W, H);
gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea), W, H);
}
@ -1125,7 +1176,7 @@ static int ConfigureDrawingArea(GtkWidget *widget, GdkEventConfigure *event, gpo
}
static inline void gpu_screen_to_rgb(guchar * rgb, int size)
static inline void gpu_screen_to_rgb(guchar * rgb, int size, int pixelsize)
{
gint rot = nds_screen.rotation_angle;
gint height, width;
@ -1135,7 +1186,6 @@ static inline void gpu_screen_to_rgb(guchar * rgb, int size)
width = screen_size[nds_screen.orientation].width;
height = screen_size[nds_screen.orientation].height;
memset(rgb, 0, size);
for (gint i = 0; i < width; i++) {
for (gint j = 0; j < height; j++) {
gint row = j, col = i;
@ -1150,12 +1200,12 @@ static inline void gpu_screen_to_rgb(guchar * rgb, int size)
gpu_pixel = *((u16 *) & GPU_screen[(col + row * 256) << 1]);
if (rot == 0 || rot == 180)
offset = i * 3 + j * 3 * width;
offset = i * pixelsize + j * pixelsize * width;
else
offset = j * 3 + (width - i - 1) * 3 * height;
offset = j * pixelsize + (width - i - 1) * pixelsize * height;
if (rot == 90 || rot == 180)
offset = size - offset - 3;
offset = size - offset - pixelsize;
*(rgb + offset + 0) = ((gpu_pixel >> 0) & 0x1f) << 3;
*(rgb + offset + 1) = ((gpu_pixel >> 5) & 0x1f) << 3;
@ -1168,7 +1218,6 @@ static inline void gpu_screen_to_rgb(guchar * rgb, int size)
static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
GdkPixbuf *resizedPixbuf, *drawPixbuf;
guchar rgb[SCREENS_PIXEL_SIZE*SCREEN_BYTES_PER_PIXEL];
cairo_t *cr;
GdkWindow *window;
@ -1242,16 +1291,28 @@ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpo
osd->update();
DrawHUD();
gpu_screen_to_rgb(rgb, imgW*imgH*SCREEN_BYTES_PER_PIXEL);
drawPixbuf = gdk_pixbuf_new_from_data(rgb, GDK_COLORSPACE_RGB,
FALSE, 8, imgW, imgH, imgW*SCREEN_BYTES_PER_PIXEL, NULL, NULL);
if ((hratio != 1.0) || (vratio != 1.0)) {
resizedPixbuf = gdk_pixbuf_scale_simple (drawPixbuf, hratio*imgW, vratio*imgH,
Interpolation);
g_object_unref(drawPixbuf);
drawPixbuf = resizedPixbuf;
gpu_screen_to_rgb((u8*)video.GetSrcBufferPtr(), imgW*imgH*4, 4);
u32* fbuf = video.RunFilter();
int dstW = video.GetDstWidth();
int dstH = video.GetDstHeight();
//Convert to 24-bit
guchar dsurf24[dstW*dstH*SCREEN_BYTES_PER_PIXEL];
gint k=0;
for (gint i=0; i<dstW*dstH; i++)
{
*(u32*) &(dsurf24[k]) = fbuf[i];
k+=3;
}
drawPixbuf = gdk_pixbuf_new_from_data(dsurf24, GDK_COLORSPACE_RGB,
FALSE, 8, dstW, dstH, dstW*SCREEN_BYTES_PER_PIXEL, NULL, NULL);
resizedPixbuf = gdk_pixbuf_scale_simple(drawPixbuf, hratio*imgW, vratio*imgH,
Interpolation);
g_object_unref(drawPixbuf);
drawPixbuf = resizedPixbuf;
cr = gdk_cairo_create(widget->window);
gdk_cairo_set_source_pixbuf(cr, drawPixbuf, 0, 0);
@ -1694,7 +1755,7 @@ static void Printscreen()
H = screen_size[nds_screen.orientation].width;
}
gpu_screen_to_rgb(rgb, W*H*SCREEN_BYTES_PER_PIXEL);
gpu_screen_to_rgb(rgb, W*H*SCREEN_BYTES_PER_PIXEL, 3);
screenshot = gdk_pixbuf_new_from_data(rgb,
GDK_COLORSPACE_RGB,
FALSE,
@ -1775,10 +1836,15 @@ static void SelectFirmwareFile()
}
#endif
static void Modify_PriInterpolation(GtkAction *action, GtkRadioAction *current)
{
uint filter = gtk_radio_action_get_current_value(current) ;
video.ChangeFilterByID((VideoFilterTypeID)filter);
}
static void Modify_Interpolation(GtkAction *action, GtkRadioAction *current)
{
uint i = gtk_radio_action_get_current_value(current) ;
Interpolation = (i == 0 ? GDK_INTERP_NEAREST : GDK_INTERP_BILINEAR);
Interpolation = (GdkInterpType)gtk_radio_action_get_current_value(current);
}
static void Modify_SPUMode(GtkAction *action, GtkRadioAction *current)
@ -2219,7 +2285,9 @@ common_gtk_main( class configured_features *my_config)
gtk_action_group_add_radio_actions(action_group, savet_entries, G_N_ELEMENTS(savet_entries),
my_config->savetype, G_CALLBACK(changesavetype), NULL);
gtk_action_group_add_radio_actions(action_group, interpolation_entries, G_N_ELEMENTS(interpolation_entries),
1, G_CALLBACK(Modify_Interpolation), NULL);
GDK_INTERP_NEAREST, G_CALLBACK(Modify_Interpolation), NULL);
gtk_action_group_add_radio_actions(action_group, pri_interpolation_entries, G_N_ELEMENTS(pri_interpolation_entries),
VideoFilterTypeID_HQ2XS, G_CALLBACK(Modify_PriInterpolation), NULL);
gtk_action_group_add_radio_actions(action_group, spumode_entries, G_N_ELEMENTS(spumode_entries),
0, G_CALLBACK(Modify_SPUMode), NULL);
gtk_action_group_add_radio_actions(action_group, frameskip_entries, G_N_ELEMENTS(frameskip_entries),
@ -2349,6 +2417,12 @@ common_gtk_main( class configured_features *my_config)
g_timeout_add_seconds(my_config->timeout, timeout_exit_cb, GINT_TO_POINTER(my_config->timeout));
}
/* Video filter parameters */
video.SetFilterParameteri(VF_PARAM_SCANLINE_A, _scanline_filter_a);
video.SetFilterParameteri(VF_PARAM_SCANLINE_B, _scanline_filter_b);
video.SetFilterParameteri(VF_PARAM_SCANLINE_C, _scanline_filter_c);
video.SetFilterParameteri(VF_PARAM_SCANLINE_D, _scanline_filter_d);
/* Main loop */
gtk_main();