From f2cfd23ef20e0b43dbcb4ac17d080ea8e072dc1a Mon Sep 17 00:00:00 2001 From: Max Fedotov Date: Thu, 25 Jan 2024 17:28:46 +0300 Subject: [PATCH] gtk: implement GPU scale factor feature (#764) * [WIP] gtk: implement GPU scale factor feature * Replace combobox with spin button, fix taking screenshot * Fix distorted image, add some checks for scale factor value * Make OSD at least properly visible --- desmume/src/frontend/posix/gtk/config.cpp | 18 ++++++ desmume/src/frontend/posix/gtk/config_opts.h | 1 + desmume/src/frontend/posix/gtk/graphics.ui | 29 ++++++++-- desmume/src/frontend/posix/gtk/main.cpp | 61 ++++++++++++++++---- desmume/src/frontend/posix/gtk/sdl_3Demu.cpp | 6 +- 5 files changed, 98 insertions(+), 17 deletions(-) diff --git a/desmume/src/frontend/posix/gtk/config.cpp b/desmume/src/frontend/posix/gtk/config.cpp index eceb2f06b..a0e593a5b 100644 --- a/desmume/src/frontend/posix/gtk/config.cpp +++ b/desmume/src/frontend/posix/gtk/config.cpp @@ -63,6 +63,24 @@ void value::save() { g_key_file_set_integer(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), this->mData); } +/*class value */ + +template<> +void value::load() { + GError* err = NULL; + float val = g_key_file_get_double(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), &err); + if (err != NULL) { + g_error_free(err); + } else { + this->mData = val; + } +} + +template<> +void value::save() { + g_key_file_set_double(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), this->mData); +} + /* class value */ template<> diff --git a/desmume/src/frontend/posix/gtk/config_opts.h b/desmume/src/frontend/posix/gtk/config_opts.h index 151d0f874..7481ab634 100644 --- a/desmume/src/frontend/posix/gtk/config_opts.h +++ b/desmume/src/frontend/posix/gtk/config_opts.h @@ -60,6 +60,7 @@ OPT(core3D, int, 1, Config, Core3D) OPT(textureDeposterize, bool, false, Config, 3DTextureDeposterization) OPT(textureSmoothing, bool, false, Config, 3DTextureSmoothing) OPT(textureUpscale, int, 1, Config, 3DTextureUpscaling) +OPT(gpuScaleFactor, float, 1.0, Config, GPUScaleFactor) OPT(highColorInterpolation, bool, true, Config, HighResolutionColorInterpolation) OPT(multisampling, bool, false, Config, OpenGLMultisampling) OPT(multisamplingSize, int, 0, Config, OpenGLMultisamplingSize) diff --git a/desmume/src/frontend/posix/gtk/graphics.ui b/desmume/src/frontend/posix/gtk/graphics.ui index 44eed71fc..f8dc2976b 100644 --- a/desmume/src/frontend/posix/gtk/graphics.ui +++ b/desmume/src/frontend/posix/gtk/graphics.ui @@ -94,6 +94,25 @@ 1 + + + GPU scale factor: + + + 0 + 2 + + + + + true + 0 + + + 1 + 2 + + 3D Texture Deposterization @@ -101,7 +120,7 @@ 0 - 2 + 3 @@ -111,7 +130,7 @@ 0 - 3 + 4 @@ -121,7 +140,7 @@ 1 - 3 + 4 @@ -130,7 +149,7 @@ 0 - 4 + 5 @@ -146,7 +165,7 @@ 1 - 4 + 5 diff --git a/desmume/src/frontend/posix/gtk/main.cpp b/desmume/src/frontend/posix/gtk/main.cpp index 2cecb5313..1bf5bd492 100644 --- a/desmume/src/frontend/posix/gtk/main.cpp +++ b/desmume/src/frontend/posix/gtk/main.cpp @@ -99,6 +99,14 @@ static int draw_count; extern int _scanline_filter_a, _scanline_filter_b, _scanline_filter_c, _scanline_filter_d; VideoFilter* video; +#define GPU_SCALE_FACTOR_MIN 1.0f +#define GPU_SCALE_FACTOR_MAX 10.0f + +float gpu_scale_factor = 1.0f; +int real_framebuffer_width = GPU_FRAMEBUFFER_NATIVE_WIDTH; +int real_framebuffer_height = GPU_FRAMEBUFFER_NATIVE_HEIGHT; + + desmume::config::Config config; #ifdef GDB_STUB @@ -1310,7 +1318,8 @@ static int ConfigureDrawingArea(GtkWidget *widget, GdkEventConfigure *event, gpo static inline void gpu_screen_to_rgb(u32* dst) { - ColorspaceConvertBuffer555To8888Opaque(GPU->GetDisplayInfo().masterNativeBuffer16, dst, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); + ColorspaceConvertBuffer555To8888Opaque(GPU->GetDisplayInfo().isCustomSizeRequested ? (u16*)(GPU->GetDisplayInfo().masterCustomBuffer) : GPU->GetDisplayInfo().masterNativeBuffer16, + dst, real_framebuffer_width * real_framebuffer_height * 2); } static inline void drawScreen(cairo_t* cr, u32* buf, gint w, gint h) { @@ -1384,7 +1393,7 @@ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpo gint dstW = video->GetDstWidth(); gint dstH = video->GetDstHeight(); - gint dstScale = dstW * 2 / 256; // Actual scale * 2 to handle 1.5x filters + gint dstScale = dstW * 2 / GPU_FRAMEBUFFER_NATIVE_WIDTH; // Actual scale * 2 to handle 1.5x filters gint gap = nds_screen.orientation == ORIENT_VERTICAL ? nds_screen.gap_size * dstScale / 2 : 0; gint imgW, imgH; @@ -1436,9 +1445,11 @@ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpo } static void RedrawScreen() { - ColorspaceConvertBuffer555To8888Opaque(GPU->GetDisplayInfo().masterNativeBuffer16, (uint32_t *)video->GetSrcBufferPtr(), GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); + ColorspaceConvertBuffer555To8888Opaque( + GPU->GetDisplayInfo().isCustomSizeRequested ? (u16*)(GPU->GetDisplayInfo().masterCustomBuffer) : GPU->GetDisplayInfo().masterNativeBuffer16, + (uint32_t *)video->GetSrcBufferPtr(), real_framebuffer_width * real_framebuffer_height * 2); #ifdef HAVE_LIBAGG - aggDraw.hud->attach((u8*)video->GetSrcBufferPtr(), 256, 384, 1024); + aggDraw.hud->attach((u8*)video->GetSrcBufferPtr(), real_framebuffer_width, real_framebuffer_height * 2, 1024 * gpu_scale_factor); osd->update(); DrawHUD(); osd->clear(); @@ -1989,12 +2000,16 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g GtkGrid *wGrid; GtkComboBox *coreCombo, *wScale, *wMultisample; GtkToggleButton *wPosterize, *wSmoothing, *wHCInterpolate; + GtkSpinButton *wGPUScale; GtkBuilder *builder = gtk_builder_new_from_resource("/org/desmume/DeSmuME/graphics.ui"); dialog = GTK_DIALOG(gtk_builder_get_object(builder, "dialog")); wGrid = GTK_GRID(gtk_builder_get_object(builder, "graphics_grid")); coreCombo = GTK_COMBO_BOX(gtk_builder_get_object(builder, "core_combo")); wScale = GTK_COMBO_BOX(gtk_builder_get_object(builder, "scale")); + wGPUScale = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "gpuscale")); + gtk_spin_button_set_range(wGPUScale, GPU_SCALE_FACTOR_MIN, GPU_SCALE_FACTOR_MAX); + gtk_spin_button_set_increments(wGPUScale, 1.0, 1.0); wMultisample = GTK_COMBO_BOX(gtk_builder_get_object(builder, "multisample")); wPosterize = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "posterize")); wSmoothing = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "smoothing")); @@ -2010,6 +2025,9 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g // The shift it work for scale up to 4. For scaling more than 4, a mapping function is required gtk_combo_box_set_active(wScale, CommonSettings.GFX3D_Renderer_TextureScalingFactor >> 1); + //GPU scaling factor + gtk_spin_button_set_value(wGPUScale, gpu_scale_factor); + // 3D Texture Deposterization gtk_toggle_button_set_active(wPosterize, CommonSettings.GFX3D_Renderer_TextureDeposterize); @@ -2080,6 +2098,17 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g default: break; } + gpu_scale_factor = gtk_spin_button_get_value(wGPUScale); + if(gpu_scale_factor < GPU_SCALE_FACTOR_MIN) + gpu_scale_factor = GPU_SCALE_FACTOR_MIN; + if(gpu_scale_factor > GPU_SCALE_FACTOR_MAX) + gpu_scale_factor = GPU_SCALE_FACTOR_MAX; + gtk_spin_button_set_value(wGPUScale, gpu_scale_factor); + config.gpuScaleFactor = gpu_scale_factor; + real_framebuffer_width = GPU_FRAMEBUFFER_NATIVE_WIDTH * gpu_scale_factor; + real_framebuffer_height = GPU_FRAMEBUFFER_NATIVE_HEIGHT * gpu_scale_factor; + GPU->SetCustomFramebufferSize(real_framebuffer_width, real_framebuffer_height); + video->SetSourceSize(real_framebuffer_width, real_framebuffer_height * 2); CommonSettings.GFX3D_Renderer_TextureDeposterize = config.textureDeposterize = gtk_toggle_button_get_active(wPosterize); CommonSettings.GFX3D_Renderer_TextureSmoothing = config.textureSmoothing = gtk_toggle_button_get_active(wSmoothing); CommonSettings.GFX3D_Renderer_TextureScalingFactor = config.textureUpscale = scale; @@ -2140,7 +2169,7 @@ static void Printscreen(GSimpleAction *action, GVariant *parameter, gpointer use const gchar *dir; gchar *filename = NULL, *filen = NULL; GError *error = NULL; - u8 rgb[256 * 384 * 4]; + u8 *rgb = (u8*)malloc(real_framebuffer_width * real_framebuffer_height * 2 * 4); static int seq = 0; gint H, W; @@ -2149,11 +2178,11 @@ static void Printscreen(GSimpleAction *action, GVariant *parameter, gpointer use // return; if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) { - W = screen_size[nds_screen.orientation].width; - H = screen_size[nds_screen.orientation].height; + W = real_framebuffer_width; + H = real_framebuffer_height * 2; } else { - W = screen_size[nds_screen.orientation].height; - H = screen_size[nds_screen.orientation].width; + W = real_framebuffer_height * 2; + H = real_framebuffer_width; } gpu_screen_to_rgb((u32*)rgb); @@ -2190,7 +2219,7 @@ static void Printscreen(GSimpleAction *action, GVariant *parameter, gpointer use seq--; } - //free(rgb); + free(rgb); g_object_unref(screenshot); g_free(filename); g_free(filen); @@ -3026,8 +3055,18 @@ common_gtk_main(GApplication *app, gpointer user_data) memset(&nds_screen, 0, sizeof(nds_screen)); nds_screen.orientation = ORIENT_VERTICAL; + gpu_scale_factor = config.gpuScaleFactor; + if(gpu_scale_factor < GPU_SCALE_FACTOR_MIN) + gpu_scale_factor = GPU_SCALE_FACTOR_MIN; + if(gpu_scale_factor > GPU_SCALE_FACTOR_MAX) + gpu_scale_factor = GPU_SCALE_FACTOR_MAX; + config.gpuScaleFactor = gpu_scale_factor; + real_framebuffer_width = GPU_FRAMEBUFFER_NATIVE_WIDTH * gpu_scale_factor; + real_framebuffer_height = GPU_FRAMEBUFFER_NATIVE_HEIGHT * gpu_scale_factor; + g_printerr("Using %d threads for video filter.\n", CommonSettings.num_cores); - video = new VideoFilter(256, 384, VideoFilterTypeID_None, CommonSettings.num_cores); + GPU->SetCustomFramebufferSize(real_framebuffer_width, real_framebuffer_height); + video = new VideoFilter(real_framebuffer_width, real_framebuffer_height * 2, VideoFilterTypeID_None, CommonSettings.num_cores); /* Fetch the main elements from the window */ GtkBuilder *builder = gtk_builder_new_from_resource("/org/desmume/DeSmuME/main.ui"); diff --git a/desmume/src/frontend/posix/gtk/sdl_3Demu.cpp b/desmume/src/frontend/posix/gtk/sdl_3Demu.cpp index fb05b157c..39c5d0d57 100644 --- a/desmume/src/frontend/posix/gtk/sdl_3Demu.cpp +++ b/desmume/src/frontend/posix/gtk/sdl_3Demu.cpp @@ -28,6 +28,9 @@ static bool sdl_init(void) { return is_sdl_initialized(); } static SDL_Window *win = NULL; static SDL_GLContext ctx = NULL; +extern int real_framebuffer_width; +extern int real_framebuffer_height; + bool deinit_sdl_3Demu(void) { bool ret = false; @@ -60,7 +63,8 @@ bool init_sdl_3Demu(void) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - win = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 256, 192, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); + win = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, real_framebuffer_width, + real_framebuffer_height, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); if (!win) { fprintf(stderr, "SDL: Failed to create a window: %s\n", SDL_GetError()); return false;