diff --git a/.gitignore b/.gitignore index 1751df64bf..d7e042e383 100644 --- a/.gitignore +++ b/.gitignore @@ -188,3 +188,6 @@ gfx/common/wayland/xdg-decoration-unstable-v1.h gfx/common/wayland/xdg-decoration-unstable-v1.c gfx/common/wayland/xdg-shell.c gfx/common/wayland/xdg-shell.h + +# DINGUX +*.opk diff --git a/Makefile.common b/Makefile.common index d16715567d..df2a896cc2 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1183,6 +1183,10 @@ ifeq ($(TARGET), retroarch_orbis) frontend/drivers/platform_orbis.o endif +ifeq ($(DINGUX), 1) + OBJ += dingux/dingux_utils.o +endif + ifeq ($(HAVE_WAYLAND), 1) OBJ += gfx/drivers_context/wayland_ctx.o \ input/common/wayland_common.o \ @@ -2328,7 +2332,7 @@ endif ### Android Play Feature Delivery ### ### (Play Store build core ### ### downloader) ### -###############WIP################### +##################################### ifeq ($(ANDROID), 1) OBJ += play_feature_delivery/play_feature_delivery.o endif diff --git a/Makefile.dingux b/Makefile.dingux index a15d641193..1043eaa3f0 100644 --- a/Makefile.dingux +++ b/Makefile.dingux @@ -4,6 +4,7 @@ PACKAGE_NAME = retroarch DEBUG ?= 0 +DINGUX = 1 HAVE_SCREENSHOTS = 1 HAVE_REWIND = 1 HAVE_7ZIP = 1 diff --git a/Makefile.rg350 b/Makefile.rg350 new file mode 100644 index 0000000000..518f02ad02 --- /dev/null +++ b/Makefile.rg350 @@ -0,0 +1,189 @@ +TOOLCHAIN_DIR=/opt/gcw0-toolchain/usr/bin +CC = $(TOOLCHAIN_DIR)/mipsel-gcw0-linux-uclibc-gcc +CXX = $(TOOLCHAIN_DIR)/mipsel-gcw0-linux-uclibc-g++ +PACKAGE_NAME = retroarch + +DEBUG ?= 0 + +DINGUX = 1 +HAVE_SCREENSHOTS = 0 +HAVE_REWIND = 1 +HAVE_7ZIP = 1 +HAVE_AL = 1 +# ALSA freezes when switching back from menu +HAVE_ALSA = 0 +HAVE_DSP_FILTER = 1 +HAVE_VIDEO_FILTER = 1 +HAVE_STATIC_VIDEO_FILTERS = 1 +HAVE_STATIC_AUDIO_FILTERS = 1 +HAVE_FILTERS_BUILTIN = 1 +HAVE_BUILTINMBEDTLS = 1 +HAVE_BUILTINZLIB = 1 +HAVE_C99 = 1 +HAVE_CC = 1 +HAVE_CC_RESAMPLER = 1 +HAVE_CHD = 1 +HAVE_COMMAND = 1 +HAVE_CXX = 1 +HAVE_DR_MP3 = 1 +HAVE_DYNAMIC = 1 +HAVE_EGL = 0 +HAVE_FREETYPE = 0 +HAVE_GDI = 1 +HAVE_GETADDRINFO = 1 +HAVE_GETOPT_LONG = 1 +HAVE_GLSL = 0 +HAVE_HID = 1 +HAVE_IBXM = 1 +HAVE_IMAGEVIEWER = 1 +HAVE_LANGEXTRA = 0 +HAVE_LIBRETRODB = 1 +HAVE_MENU = 1 +HAVE_MENU_COMMON = 1 +HAVE_GFX_WIDGETS = 0 +HAVE_MMAP = 1 +HAVE_OPENDINGUX_FBDEV = 0 +HAVE_OPENGL = 0 +HAVE_OPENGL1 = 0 +HAVE_OPENGLES = 0 +HAVE_OPENGLES3 = 0 +HAVE_OPENGL_CORE = 0 +HAVE_OPENSSL = 1 +HAVE_OVERLAY = 0 +HAVE_RBMP = 1 +HAVE_RJPEG = 1 +HAVE_RPILED = 1 +HAVE_RPNG = 1 +HAVE_RUNAHEAD = 1 +HAVE_SDL_DINGUX = 1 +HAVE_SHADERPIPELINE = 0 +HAVE_STB_FONT = 0 +HAVE_STB_IMAGE = 1 +HAVE_STB_VORBIS = 1 +HAVE_STDIN_CMD = 1 +HAVE_STRCASESTR = 1 +HAVE_THREADS = 1 +HAVE_UDEV = 1 +HAVE_RGUI = 1 +HAVE_MATERIALUI = 0 +HAVE_XMB = 0 +HAVE_OZONE = 0 +HAVE_ZLIB = 1 +HAVE_CONFIGFILE = 1 +HAVE_PATCH = 1 +HAVE_CHEATS = 1 + +OS = Linux +TARGET = retroarch +OPK_NAME = retroarch_rg350.opk + +OBJ := +LINK := $(CXX) +DEF_FLAGS := -march=mips32 -mtune=mips32r2 -mhard-float -ffast-math -fomit-frame-pointer -fdata-sections +DEF_FLAGS += -I. -Ideps -Ideps/stb -DDINGUX=1 -MMD +DEF_FLAGS += -Wall -Wno-unused-variable +DEF_FLAGS += -std=gnu99 -D_GNU_SOURCE +LIBS := -ldl -lz -lrt -lcrypto -lssl -ludev -pthread +CFLAGS := +CXXFLAGS := -fno-exceptions -fno-rtti -std=c++11 -D__STDC_CONSTANT_MACROS +ASFLAGS := +LDFLAGS := -flto +INCLUDE_DIRS = -I/opt/gcw0-toolchain/usr/mipsel-gcw0-linux-uclibc/sysroot/usr/include +LIBRARY_DIRS = -L/opt/gcw0-toolchain/usr/mipsel-gcw0-linux-uclibc/sysroot/usr/lib +DEFINES := -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64 -UHAVE_STATIC_DUMMY +DEFINES += -DHAVE_C99=1 -DHAVE_CXX=1 +DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1 +DEFINES += -DHAVE_AL=1 +DEFINES += -DHAVE_FILTERS_BUILTIN +DEFINES += -DHAVE_UDEV=1 + +SDL_DINGUX_CFLAGS := $(shell /opt/gcw0-toolchain/usr/mipsel-gcw0-linux-uclibc/sysroot/usr/bin/sdl-config --cflags) +SDL_DINGUX_LIBS := $(shell /opt/gcw0-toolchain/usr/mipsel-gcw0-linux-uclibc/sysroot/usr/bin/sdl-config --libs) +FREETYPE_CFLAGS := $(shell /opt/gcw0-toolchain/usr/mipsel-gcw0-linux-uclibc/sysroot/usr/bin/freetype-config --cflags) +FREETYPE_LIBS := $(shell /opt/gcw0-toolchain/usr/mipsel-gcw0-linux-uclibc/sysroot/usr/bin/freetype-config --libs) +AL_LIBS := -lopenal +MMAP_LIBS = -lc + +OBJDIR_BASE := obj-unix + +ifeq ($(DEBUG), 1) + OBJDIR := $(OBJDIR_BASE)/debug + DEF_FLAGS += -O0 -g -DDEBUG -D_DEBUG +else + OBJDIR := $(OBJDIR_BASE)/release + DEF_FLAGS += -O2 -DNDEBUG +endif + +include Makefile.common + +DEF_FLAGS += $(INCLUDE_DIRS) +CFLAGS += $(DEF_FLAGS) +CXXFLAGS += $(DEF_FLAGS) + +HEADERS = $(wildcard */*/*.h) $(wildcard */*.h) $(wildcard *.h) + +Q := @ + +RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ)) + +define DESKTOP_ENTRY +[Desktop Entry] +Name=retroarch +Comment=Retroarch +Exec=retroarch +Terminal=false +Type=Application +StartupNotify=true +Icon=retroarch +Categories=emulators; +X-OD-NeedsDownscaling=true +endef +export DESKTOP_ENTRY + +all: $(TARGET) opk + +-include $(RARCH_OBJ:.o=.d) + +SYMBOL_MAP := -Wl,-Map=output.map + +$(TARGET): $(RARCH_OBJ) + @$(if $(Q), $(shell echo echo LD $@),) + $(LINK) -o $@ $(RARCH_OBJ) $(LIBS) $(LDFLAGS) $(LIBRARY_DIRS) + +$(OBJDIR)/%.o: %.c + @mkdir -p $(dir $@) + @$(if $(Q), $(shell echo echo CC $<),) + $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $< + +$(OBJDIR)/%.o: %.cpp + @mkdir -p $(dir $@) + @$(if $(Q), $(shell echo echo CXX $<),) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES) -MMD -c -o $@ $< + +$(OBJDIR)/%.o: %.m + @mkdir -p $(dir $@) + @$(if $(Q), $(shell echo echo OBJC $<),) + $(CXX) $(OBJCFLAGS) $(DEFINES) -MMD -c -o $@ $< + +$(OBJDIR)/%.o: %.S $(HEADERS) + @mkdir -p $(dir $@) + @$(if $(Q), $(shell echo echo AS $<),) + $(CC) $(CFLAGS) $(ASFLAGS) $(DEFINES) -c -o $@ $< + +clean: + rm -rf $(OBJDIR_BASE) + rm -f $(TARGET) + rm -f *.d + rm -rf $(OPK_NAME) + +opk: $(TARGET) + echo "$$DESKTOP_ENTRY" > default.gcw0.desktop + rm -f $(OPK_NAME) + cp media/ico_src/icon32.png retroarch.png + $(TOOLCHAIN_DIR)/mksquashfs retroarch default.gcw0.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports + rm -f default.gcw0.desktop retroarch.png + +.PHONY: all clean opk + +print-%: + @echo '$*=$($*)' diff --git a/config.def.h b/config.def.h index e499f59495..6da2493a3c 100644 --- a/config.def.h +++ b/config.def.h @@ -177,8 +177,9 @@ /* To start in Fullscreen, or not. */ -#ifdef HAVE_STEAM -/* Start in fullscreen mode for Steam build */ +#if defined(HAVE_STEAM) || defined(DINGUX) +/* Start in fullscreen mode for Steam and + * Dingux builds */ #define DEFAULT_FULLSCREEN true #else #define DEFAULT_FULLSCREEN false @@ -199,8 +200,13 @@ /* Fullscreen resolution. A value of 0 uses the desktop * resolution. */ +#if defined(DINGUX) +#define DEFAULT_FULLSCREEN_X 320 +#define DEFAULT_FULLSCREEN_Y 240 +#else #define DEFAULT_FULLSCREEN_X 0 #define DEFAULT_FULLSCREEN_Y 0 +#endif /* Number of threads to use for video recording */ #define DEFAULT_VIDEO_RECORD_THREADS 2 @@ -355,6 +361,12 @@ #define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_CORE #endif +#if defined(DINGUX) +/* Enables aspect ratio correction (1:1 PAR) when + * using the IPU hardware scaler in Dingux devices */ +#define DEFAULT_DINGUX_IPU_KEEP_ASPECT true +#endif + /* Save configuration file on exit. */ #define DEFAULT_CONFIG_SAVE_ON_EXIT true diff --git a/configuration.c b/configuration.c index f5f0898b14..ed2ff4137f 100644 --- a/configuration.c +++ b/configuration.c @@ -522,10 +522,9 @@ static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_ANDROI static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_NULL; #endif -#if defined(_3DS) && defined(HAVE_RGUI) +#if (defined(_3DS) || defined(DINGUX)) && defined(HAVE_RGUI) static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI; -#else -#if defined(HAVE_MATERIALUI) && defined(RARCH_MOBILE) +#elif defined(HAVE_MATERIALUI) && defined(RARCH_MOBILE) static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_MATERIALUI; #elif defined(HAVE_OZONE) static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_OZONE; @@ -536,7 +535,6 @@ static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI; #else static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_NULL; #endif -#endif /* All config related settings go here. */ @@ -1458,6 +1456,9 @@ static struct config_bool_setting *populate_settings_bool( SETTING_BOOL("video_smooth", &settings->bools.video_smooth, true, DEFAULT_VIDEO_SMOOTH, false); SETTING_BOOL("video_ctx_scaling", &settings->bools.video_ctx_scaling, true, DEFAULT_VIDEO_CTX_SCALING, false); SETTING_BOOL("video_force_aspect", &settings->bools.video_force_aspect, true, DEFAULT_FORCE_ASPECT, false); +#if defined(DINGUX) + SETTING_BOOL("video_dingux_ipu_keep_aspect", &settings->bools.video_dingux_ipu_keep_aspect, true, DEFAULT_DINGUX_IPU_KEEP_ASPECT, false); +#endif SETTING_BOOL("video_threaded", video_driver_get_threaded(), true, DEFAULT_VIDEO_THREADED, false); SETTING_BOOL("video_shared_context", &settings->bools.video_shared_context, true, DEFAULT_VIDEO_SHARED_CONTEXT, false); SETTING_BOOL("auto_screenshot_filename", &settings->bools.auto_screenshot_filename, true, DEFAULT_AUTO_SCREENSHOT_FILENAME, false); diff --git a/configuration.h b/configuration.h index da6bec10b7..1ef32db9a8 100644 --- a/configuration.h +++ b/configuration.h @@ -455,6 +455,7 @@ typedef struct settings bool video_force_aspect; bool video_crop_overscan; bool video_aspect_ratio_auto; + bool video_dingux_ipu_keep_aspect; bool video_scale_integer; bool video_shader_enable; bool video_shader_watch_files; diff --git a/dingux/dingux_utils.c b/dingux/dingux_utils.c new file mode 100644 index 0000000000..f7c6ce46d6 --- /dev/null +++ b/dingux/dingux_utils.c @@ -0,0 +1,97 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * Copyright (C) 2019-2020 - James Leaver + * + * 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 . + */ + +#include +#include + +#include "dingux_utils.h" + +#define DINGUX_ALLOW_DOWNSCALING_FILE "/sys/devices/platform/jz-lcd.0/allow_downscaling" +#define DINGUX_KEEP_ASPECT_RATIO_FILE "/sys/devices/platform/jz-lcd.0/keep_aspect_ratio" +#define DINGUX_BATTERY_CAPACITY_FILE "/sys/class/power_supply/battery/capacity" + +/* Enables/disables downscaling when using + * the IPU hardware scaler */ +bool dingux_ipu_set_downscaling_enable(bool enable) +{ + const char *path = DINGUX_ALLOW_DOWNSCALING_FILE; + const char *enable_str = enable ? "1" : "0"; + + /* Check whether file exists */ + if (!path_is_valid(path)) + return false; + + /* Write enable state to file */ + return filestream_write_file( + path, enable_str, 1); +} + +/* Enables/disables aspect ratio correction + * (1:1 PAR) when using the IPU hardware + * scaler (disabling this will stretch the + * image to the full screen dimensions) */ +bool dingux_ipu_set_aspect_ratio_enable(bool enable) +{ + const char *path = DINGUX_KEEP_ASPECT_RATIO_FILE; + const char *enable_str = enable ? "1" : "0"; + + /* Check whether file exists */ + if (!path_is_valid(path)) + return false; + + /* Write enable state to file */ + return filestream_write_file( + path, enable_str, 1); +} + +/* Fetches internal battery level */ +int dingux_get_battery_level(void) +{ + const char *path = DINGUX_BATTERY_CAPACITY_FILE; + int64_t file_len = 0; + char *file_buf = NULL; + int battery_level = 0; + + /* Check whether file exists */ + if (!path_is_valid(path)) + goto error; + + /* Read file */ + if (!filestream_read_file(path, (void**)&file_buf, &file_len) || + (file_len == 0)) + goto error; + + /* Convert to integer */ + if (file_buf) + { + battery_level = atoi(file_buf); + + free(file_buf); + file_buf = NULL; + } + + return battery_level; + +error: + if (file_buf) + { + free(file_buf); + file_buf = NULL; + } + + return -1; +} diff --git a/dingux/dingux_utils.h b/dingux/dingux_utils.h new file mode 100644 index 0000000000..12bfd18b20 --- /dev/null +++ b/dingux/dingux_utils.h @@ -0,0 +1,43 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * Copyright (C) 2019-2020 - James Leaver + * + * 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 . + */ + +#ifndef _DINGUX_UTILS_H +#define _DINGUX_UTILS_H + +#include +#include + +#include + +RETRO_BEGIN_DECLS + +/* Enables/disables downscaling when using + * the IPU hardware scaler */ +bool dingux_ipu_set_downscaling_enable(bool enable); + +/* Enables/disables aspect ratio correction + * (1:1 PAR) when using the IPU hardware + * scaler (disabling this will stretch the + * image to the full screen dimensions) */ +bool dingux_ipu_set_aspect_ratio_enable(bool enable); + +/* Fetches internal battery level */ +int dingux_get_battery_level(void); + +RETRO_END_DECLS + +#endif diff --git a/file_path_special.c b/file_path_special.c index 76a5ebebd9..2e4fa2a791 100644 --- a/file_path_special.c +++ b/file_path_special.c @@ -103,6 +103,14 @@ bool fill_pathname_application_data(char *s, size_t len) "Library/Application Support/RetroArch", len); return true; } +#elif defined(DINGUX) + const char *appdata = getenv("HOME"); + + if (appdata) + { + fill_pathname_join(s, appdata, "/.retroarch", len); + return true; + } #elif !defined(RARCH_CONSOLE) const char *xdg = getenv("XDG_CONFIG_HOME"); const char *appdata = getenv("HOME"); diff --git a/frontend/drivers/platform_unix.c b/frontend/drivers/platform_unix.c index 057c87abba..0ea769a5c0 100644 --- a/frontend/drivers/platform_unix.c +++ b/frontend/drivers/platform_unix.c @@ -56,6 +56,10 @@ #include #endif +#if defined(DINGUX) +#include "../../dingux/dingux_utils.h" +#endif + #include #include #include @@ -121,6 +125,7 @@ static char unix_cpu_model_name[64] = {0}; /* /proc/meminfo parameters */ #define PROC_MEMINFO_PATH "/proc/meminfo" +#define PROC_MEMINFO_MEM_TOTAL_TAG "MemTotal:" #define PROC_MEMINFO_MEM_AVAILABLE_TAG "MemAvailable:" #define PROC_MEMINFO_MEM_FREE_TAG "MemFree:" #define PROC_MEMINFO_BUFFERS_TAG "Buffers:" @@ -1176,7 +1181,7 @@ static enum frontend_powerstate frontend_unix_get_powerstate( { enum frontend_powerstate ret = FRONTEND_POWERSTATE_NONE; -#ifdef ANDROID +#if defined(ANDROID) jint powerstate = ret; jint battery_level = 0; JNIEnv *env = jni_thread_getenv(); @@ -1195,6 +1200,25 @@ static enum frontend_powerstate frontend_unix_get_powerstate( *percent = battery_level; ret = (enum frontend_powerstate)powerstate; +#elif defined(DINGUX) + /* Dingux seems to have limited battery + * reporting capability - if we get a valid + * integer here, just assume that state is + * FRONTEND_POWERSTATE_ON_POWER_SOURCE + * (since most dingux devices are not meant + * to be used while charging...) */ + int battery_level = dingux_get_battery_level(); + + if (battery_level < 0) + *percent = -1; + else + { + *percent = battery_level; + ret = FRONTEND_POWERSTATE_ON_POWER_SOURCE; + } + + /* 'Time left' reporting is unsupported */ + *seconds = -1; #else if (frontend_unix_powerstate_check_acpi_sysfs(&ret, seconds, percent)) return ret; @@ -1737,7 +1761,11 @@ static void frontend_unix_get_env(int *argc, else if (home) { strlcpy(base_path, home, sizeof(base_path)); +#if defined(DINGUX) + strlcat(base_path, "/.retroarch", sizeof(base_path)); +#else strlcat(base_path, "/.config/retroarch", sizeof(base_path)); +#endif } else strcpy_literal(base_path, "retroarch"); @@ -2030,7 +2058,11 @@ static int frontend_unix_parse_drive_list(void *data, bool load_content) else if (home) { strlcpy(base_path, home, sizeof(base_path)); +#if defined(DINGUX) + strlcat(base_path, "/.retroarch", sizeof(base_path)); +#else strlcat(base_path, "/.config/retroarch", sizeof(base_path)); +#endif } if(!string_is_empty(base_path)) @@ -2141,9 +2173,42 @@ static void frontend_unix_exitspawn(char *s, size_t len, char *args) static uint64_t frontend_unix_get_mem_total(void) { +#if defined(DINGUX) + char line[256]; + unsigned long mem_total = 0; + FILE* meminfo_file = NULL; + + line[0] = '\0'; + + /* Open /proc/meminfo */ + meminfo_file = fopen(PROC_MEMINFO_PATH, "r"); + + if (!meminfo_file) + return 0; + + /* Parse lines + * (Note: virtual filesystem, so don't have to + * worry about buffering file reads) */ + while (fgets(line, sizeof(line), meminfo_file)) + { + if (string_starts_with_size(line, PROC_MEMINFO_MEM_TOTAL_TAG, + STRLEN_CONST(PROC_MEMINFO_MEM_TOTAL_TAG))) + { + sscanf(line, PROC_MEMINFO_MEM_TOTAL_TAG " %lu kB", &mem_total); + break; + } + } + + /* Close /proc/meminfo */ + fclose(meminfo_file); + meminfo_file = NULL; + + return (uint64_t)mem_total * 1024; +#else uint64_t pages = sysconf(_SC_PHYS_PAGES); uint64_t page_size = sysconf(_SC_PAGE_SIZE); return pages * page_size; +#endif } static uint64_t frontend_unix_get_mem_free(void) diff --git a/gfx/drivers/sdl_dingux_gfx.c b/gfx/drivers/sdl_dingux_gfx.c index aa4fe6d874..10791cc6e2 100644 --- a/gfx/drivers/sdl_dingux_gfx.c +++ b/gfx/drivers/sdl_dingux_gfx.c @@ -18,10 +18,14 @@ #include #include +#include +#include + #include #include #include -#include "../../verbosity.h" +#include +#include #ifdef HAVE_CONFIG_H #include "../../config.h" @@ -31,50 +35,259 @@ #include "../../menu/menu_driver.h" #endif -#include -#include +#include "../../dingux/dingux_utils.h" +#include "../../verbosity.h" +#include "../../gfx/drivers_font_renderer/bitmap.h" #include "../../configuration.h" #include "../../retroarch.h" #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) +#define SDL_DINGUX_MENU_WIDTH 320 +#define SDL_DINGUX_MENU_HEIGHT 240 + +#define SDL_DINGUX_NUM_FONT_GLYPHS 256 + #define VERBOSE 0 typedef struct sdl_dingux_video { - bool rgb; + SDL_Surface *screen; + uint32_t font_colour32; + uint16_t font_colour16; + uint16_t menu_texture[SDL_DINGUX_MENU_WIDTH * SDL_DINGUX_MENU_HEIGHT]; + bool font_lut[SDL_DINGUX_NUM_FONT_GLYPHS][FONT_WIDTH * FONT_HEIGHT]; + bool rgb32; + bool vsync; bool menu_active; bool was_in_menu; bool quitting; - char menu_frame[320*240*32]; - SDL_Surface *screen; } sdl_dingux_video_t; +static void sdl_dingux_init_font_color(sdl_dingux_video_t *vid) +{ + settings_t *settings = config_get_ptr(); + uint32_t red = 0xFF; + uint32_t green = 0xFF; + uint32_t blue = 0xFF; + + if (settings) + { + red = (uint32_t)((settings->floats.video_msg_color_r * 255.0f) + 0.5f) & 0xFF; + green = (uint32_t)((settings->floats.video_msg_color_g * 255.0f) + 0.5f) & 0xFF; + blue = (uint32_t)((settings->floats.video_msg_color_b * 255.0f) + 0.5f) & 0xFF; + } + + /* Convert to XRGB8888 */ + vid->font_colour32 = (red << 16) | (green << 8) | blue; + + /* Convert to RGB565 */ + red = red >> 3; + green = green >> 3; + blue = blue >> 3; + + vid->font_colour16 = (red << 11) | (green << 6) | blue; +} + +static void sdl_dingux_init_font_lut(sdl_dingux_video_t *vid) +{ + size_t symbol_index; + size_t i, j; + + /* Loop over all possible characters */ + for (symbol_index = 0; + symbol_index < SDL_DINGUX_NUM_FONT_GLYPHS; + symbol_index++) + { + for (j = 0; j < FONT_HEIGHT; j++) + { + for (i = 0; i < FONT_WIDTH; i++) + { + uint8_t rem = 1 << ((i + j * FONT_WIDTH) & 7); + unsigned offset = (i + j * FONT_WIDTH) >> 3; + + /* LUT value is 'true' if specified glyph + * position contains a pixel */ + vid->font_lut[symbol_index][i + (j * FONT_WIDTH)] = + (bitmap_bin[FONT_OFFSET(symbol_index) + offset] & rem) > 0; + } + } + } +} + +static void sdl_dingux_blit_text16( + sdl_dingux_video_t *vid, + unsigned x, unsigned y, + const char *str) +{ + uint16_t *screen_buf = (uint16_t*)vid->screen->pixels; + /* 16 bit - divide pitch by 2 */ + uint16_t screen_stride = (uint16_t)(vid->screen->pitch >> 1); + uint16_t screen_width = vid->screen->w; + uint16_t screen_height = vid->screen->h; + uint16_t shadow_color_buf[2] = {0}; + uint16_t color_buf[2]; + + color_buf[0] = vid->font_colour16; + color_buf[1] = 0; + + /* Check for out of bounds y coordinates */ + if (y + FONT_HEIGHT + 1 >= screen_height) + return; + + while (!string_is_empty(str)) + { + /* Check for out of bounds x coordinates */ + if (x + FONT_WIDTH_STRIDE + 1 >= screen_width) + return; + + /* Deal with spaces first, for efficiency */ + if (*str == ' ') + str++; + else + { + uint16_t i, j; + uint32_t symbol = utf8_walk(&str); + + /* Stupid hack: 'oe' ligatures are not really + * standard extended ASCII, so we have to waste + * CPU cycles performing a conversion from the + * unicode values... */ + if (symbol == 339) /* Latin small ligature oe */ + symbol = 156; + if (symbol == 338) /* Latin capital ligature oe */ + symbol = 140; + + if (symbol >= SDL_DINGUX_NUM_FONT_GLYPHS) + continue; + + for (j = 0; j < FONT_HEIGHT; j++) + { + uint32_t buff_offset = ((y + j) * screen_stride) + x; + + for (i = 0; i < FONT_WIDTH; i++) + { + if (vid->font_lut[symbol][i + (j * FONT_WIDTH)]) + { + uint16_t *screen_buf_ptr = screen_buf + buff_offset + i; + + /* Text pixel + right shadow */ + memcpy(screen_buf_ptr, color_buf, sizeof(uint16_t)); + + /* Bottom shadow */ + screen_buf_ptr += screen_stride; + memcpy(screen_buf_ptr, shadow_color_buf, sizeof(uint16_t)); + } + } + } + } + + x += FONT_WIDTH_STRIDE; + } +} + +static void sdl_dingux_blit_text32( + sdl_dingux_video_t *vid, + unsigned x, unsigned y, + const char *str) +{ + uint32_t *screen_buf = (uint32_t*)vid->screen->pixels; + /* 32 bit - divide pitch by 4 */ + uint32_t screen_stride = (uint32_t)(vid->screen->pitch >> 2); + uint32_t screen_width = vid->screen->w; + uint32_t screen_height = vid->screen->h; + uint32_t shadow_color_buf[2] = {0}; + uint32_t color_buf[2]; + + color_buf[0] = vid->font_colour32; + color_buf[1] = 0; + + /* Check for out of bounds y coordinates */ + if (y + FONT_HEIGHT + 1 >= screen_height) + return; + + while (!string_is_empty(str)) + { + /* Check for out of bounds x coordinates */ + if (x + FONT_WIDTH_STRIDE + 1 >= screen_width) + return; + + /* Deal with spaces first, for efficiency */ + if (*str == ' ') + str++; + else + { + uint32_t i, j; + uint32_t symbol = utf8_walk(&str); + + /* Stupid hack: 'oe' ligatures are not really + * standard extended ASCII, so we have to waste + * CPU cycles performing a conversion from the + * unicode values... */ + if (symbol == 339) /* Latin small ligature oe */ + symbol = 156; + if (symbol == 338) /* Latin capital ligature oe */ + symbol = 140; + + if (symbol >= SDL_DINGUX_NUM_FONT_GLYPHS) + continue; + + for (j = 0; j < FONT_HEIGHT; j++) + { + uint32_t buff_offset = ((y + j) * screen_stride) + x; + + for (i = 0; i < FONT_WIDTH; i++) + { + if (vid->font_lut[symbol][i + (j * FONT_WIDTH)]) + { + uint32_t *screen_buf_ptr = screen_buf + buff_offset + i; + + /* Text pixel + right shadow */ + memcpy(screen_buf_ptr, color_buf, sizeof(uint32_t)); + + /* Bottom shadow */ + screen_buf_ptr += screen_stride; + memcpy(screen_buf_ptr, shadow_color_buf, sizeof(uint32_t)); + } + } + } + } + + x += FONT_WIDTH_STRIDE; + } +} + static void sdl_dingux_gfx_free(void *data) { sdl_dingux_video_t *vid = (sdl_dingux_video_t*)data; + if (!vid) return; SDL_QuitSubSystem(SDL_INIT_VIDEO); + /* It is good manners to leave IPU aspect + * ratio scaling enabled when shutting down */ + dingux_ipu_set_aspect_ratio_enable(true); + free(vid); } static void *sdl_dingux_gfx_init(const video_info_t *video, input_driver_t **input, void **input_data) { - sdl_dingux_video_t *vid = NULL; - settings_t *settings = config_get_ptr(); + sdl_dingux_video_t *vid = NULL; + settings_t *settings = config_get_ptr(); + bool ipu_keep_aspect = settings->bools.video_dingux_ipu_keep_aspect; + const char *input_joypad_driver = settings->arrays.input_joypad_driver; + uint32_t surface_flags = (video->vsync) ? + (SDL_HWSURFACE | SDL_TRIPLEBUF | SDL_FULLSCREEN) : + (SDL_HWSURFACE | SDL_FULLSCREEN); - FILE* f = fopen("/sys/devices/platform/jz-lcd.0/allow_downscaling", "w"); - if (f) - { - fprintf(f, "%d", 1); - fclose(f); - } + dingux_ipu_set_downscaling_enable(true); + dingux_ipu_set_aspect_ratio_enable(ipu_keep_aspect); if (SDL_WasInit(0) == 0) { @@ -88,19 +301,34 @@ static void *sdl_dingux_gfx_init(const video_info_t *video, if (!vid) return NULL; -#ifdef VERBOSE - printf("sdl_dingux_gfx_init video %dx%d rgb32 %d smooth %d input_scale %u force_aspect %d fullscreen %d\n", - video->width, video->height, video->rgb32, video->smooth, video->input_scale, video->force_aspect, video->fullscreen); +#if defined(VERBOSE) + RARCH_LOG("[sdl_dingux_gfx_init]\n" + " video %dx%d\n" + " rgb32 %d\n" + " smooth %d\n" + " input_scale %u\n" + " force_aspect %d\n" + " fullscreen %d\n" + " vsync %d\n" + " flags %u\n", + video->width, video->height, (int)video->rgb32, (int)video->smooth, + video->input_scale, (int)video->force_aspect, (int)video->fullscreen, + (int)video->vsync, surface_flags); #endif - vid->screen = SDL_SetVideoMode(320, 240, video->rgb32 ? 32 : 16, SDL_HWSURFACE | SDL_TRIPLEBUF | SDL_FULLSCREEN); + vid->screen = SDL_SetVideoMode( + SDL_DINGUX_MENU_WIDTH, SDL_DINGUX_MENU_HEIGHT, + video->rgb32 ? 32 : 16, + surface_flags); + if (!vid->screen) { RARCH_ERR("[SDL1]: Failed to init SDL surface: %s\n", SDL_GetError()); goto error; } - vid->rgb = video->rgb32; + vid->vsync = video->vsync; + vid->rgb32 = video->rgb32; vid->menu_active = false; vid->was_in_menu = false; @@ -108,21 +336,24 @@ static void *sdl_dingux_gfx_init(const video_info_t *video, if (input && input_data) { - void *sdl_input = input_driver_init_wrap(&input_sdl, - settings->arrays.input_joypad_driver); + void *sdl_input = input_driver_init_wrap( + &input_sdl, input_joypad_driver); if (sdl_input) { - *input = &input_sdl; + *input = &input_sdl; *input_data = sdl_input; } else { - *input = NULL; + *input = NULL; *input_data = NULL; } } + sdl_dingux_init_font_color(vid); + sdl_dingux_init_font_lut(vid); + return vid; error: @@ -130,47 +361,75 @@ error: return NULL; } -static void clear_screen(void* data) -{ - sdl_dingux_video_t* vid = (sdl_dingux_video_t*)data; - SDL_FillRect(vid->screen, 0, 0); - SDL_Flip(vid->screen); - SDL_FillRect(vid->screen, 0, 0); - SDL_Flip(vid->screen); - SDL_FillRect(vid->screen, 0, 0); - SDL_Flip(vid->screen); -} - static void sdl_dingux_set_output( sdl_dingux_video_t* vid, - int width, int height, int pitch, bool rgb) + int width, int height, int pitch, bool rgb32) { -#ifdef VERBOSE - printf("sdl_dingux_set_output current w %d h %d pitch %d new_w %d new_h %d pitch %d rgb %d\n", - vid->screen->w, vid->screen->h, vid->screen->pitch, width, height, pitch, (int)vid->rgb); + uint32_t surface_flags = (vid->vsync) ? + (SDL_HWSURFACE | SDL_TRIPLEBUF | SDL_FULLSCREEN) : + (SDL_HWSURFACE | SDL_FULLSCREEN); + +#if defined(VERBOSE) + RARCH_LOG("[sdl_dingux_set_output]\n" + " current w %d h %d pitch %d\n" + " new_w %d new_h %d pitch %d\n" + " rgb32 %d\n" + " vsync %d\n" + " flags %u\n", + vid->screen->w, vid->screen->h, vid->screen->pitch, + width, height, pitch, + (int)rgb32, (int)vid->vsync, surface_flags); #endif - vid->screen = SDL_SetVideoMode(width, height, rgb ? 32 : 16, SDL_HWSURFACE | SDL_TRIPLEBUF | SDL_FULLSCREEN); - if (!vid->screen) - RARCH_ERR("[SDL1]: Failed to init SDL surface: %s\n", SDL_GetError()); + vid->screen = SDL_SetVideoMode( + width, height, rgb32 ? 32 : 16, + surface_flags); + + if (!vid->screen) + RARCH_ERR("[SDL1]: Failed to init SDL surface: %s\n", SDL_GetError()); } -static void blit(uint32_t* d, uint32_t* s, int width, int height, int pitch) +static void sdl_dingux_blit_frame16(uint16_t* dst, uint16_t* src, + unsigned width, unsigned height, + unsigned dst_pitch, unsigned src_pitch) { - unsigned i; - int skip = pitch/4 - width; - for (i = 0; i < height; i++) + uint16_t *in_ptr = src; + uint16_t *out_ptr = dst; + /* 16 bit - divide pitch by 2 */ + uint16_t in_stride = (uint16_t)(src_pitch >> 1); + uint16_t out_stride = (uint16_t)(dst_pitch >> 1); + size_t y; + + for (y = 0; y < height; y++) { - unsigned j; - for (j = 0; j < width; j++) - *(d++) = *(s++); - s += skip; + memcpy(out_ptr, in_ptr, width * sizeof(uint16_t)); + in_ptr += in_stride; + out_ptr += out_stride; } } -static bool sdl_dingux_gfx_frame(void *data, const void *frame, unsigned width, - unsigned height, uint64_t frame_count, - unsigned pitch, const char *msg, video_frame_info_t *video_info) +static void sdl_dingux_blit_frame32(uint32_t* dst, uint32_t* src, + unsigned width, unsigned height, + unsigned dst_pitch, unsigned src_pitch) +{ + uint32_t *in_ptr = src; + uint32_t *out_ptr = dst; + /* 32 bit - divide pitch by 4 */ + uint32_t in_stride = (uint32_t)(src_pitch >> 2); + uint32_t out_stride = (uint32_t)(dst_pitch >> 2); + size_t y; + + for (y = 0; y < height; y++) + { + memcpy(out_ptr, in_ptr, width * sizeof(uint32_t)); + in_ptr += in_stride; + out_ptr += out_stride; + } +} + +static bool sdl_dingux_gfx_frame(void *data, const void *frame, + unsigned width, unsigned height, uint64_t frame_count, + unsigned pitch, const char *msg, video_frame_info_t *video_info) { sdl_dingux_video_t* vid = (sdl_dingux_video_t*)data; #ifdef HAVE_MENU @@ -180,8 +439,13 @@ static bool sdl_dingux_gfx_frame(void *data, const void *frame, unsigned width, if (unlikely(!frame)) return true; - if (unlikely((vid->screen->w != width || vid->screen->h != height) && !vid->menu_active)) - sdl_dingux_set_output(vid, width, height, pitch, vid->rgb); + /* Update video mode if width/height have changed */ + if (unlikely( + ((vid->screen->w != width) || + (vid->screen->h != height)) && + !vid->menu_active)) + sdl_dingux_set_output(vid, width, height, + pitch, vid->rgb32); #ifdef HAVE_MENU menu_driver_frame(menu_is_alive, video_info); @@ -189,22 +453,66 @@ static bool sdl_dingux_gfx_frame(void *data, const void *frame, unsigned width, if (likely(!vid->menu_active)) { - blit((uint32_t*)vid->screen->pixels, - (uint32_t*)frame, - vid->rgb ? width : width/2, height, pitch); - if (unlikely(vid->was_in_menu)) - vid->was_in_menu = false; + /* Must always lock SDL surface before + * manipulating raw pixel buffer */ + if (SDL_MUSTLOCK(vid->screen)) + SDL_LockSurface(vid->screen); + + /* Blit frame to SDL surface */ + if (vid->rgb32) + sdl_dingux_blit_frame32( + (uint32_t*)vid->screen->pixels, + (uint32_t*)frame, + width, height, + vid->screen->pitch, pitch); + else + sdl_dingux_blit_frame16( + (uint16_t*)vid->screen->pixels, + (uint16_t*)frame, + width, height, + vid->screen->pitch, pitch); + + vid->was_in_menu = false; } else { + /* If this is the first frame that the menu + * is active, update video mode */ if (!vid->was_in_menu) { - sdl_dingux_set_output(vid, 320, 240, 320*2, false); + sdl_dingux_set_output(vid, + SDL_DINGUX_MENU_WIDTH, SDL_DINGUX_MENU_HEIGHT, + SDL_DINGUX_MENU_WIDTH * sizeof(uint16_t), false); + vid->was_in_menu = true; } - memcpy(vid->screen->pixels, vid->menu_frame, 320*240*2); + + if (SDL_MUSTLOCK(vid->screen)) + SDL_LockSurface(vid->screen); + + /* Fast copy of menu texture to SDL surface */ + memcpy(vid->screen->pixels, vid->menu_texture, + SDL_DINGUX_MENU_WIDTH * SDL_DINGUX_MENU_HEIGHT * sizeof(uint16_t)); } + /* Print OSD text, if required */ + if (msg) + { + /* If menu is active, colour depth is overriden + * to 16 bit */ + if (vid->rgb32 && !vid->menu_active) + sdl_dingux_blit_text32(vid, FONT_WIDTH_STRIDE, + vid->screen->h - (FONT_HEIGHT + FONT_WIDTH_STRIDE), msg); + else + sdl_dingux_blit_text16(vid, FONT_WIDTH_STRIDE, + vid->screen->h - (FONT_HEIGHT + FONT_WIDTH_STRIDE), msg); + } + + /* Pixel manipulation complete - unlock + * SDL surface */ + if (SDL_MUSTLOCK(vid->screen)) + SDL_UnlockSurface(vid->screen); + SDL_Flip(vid->screen); return true; @@ -222,14 +530,36 @@ static void sdl_dingux_set_texture_enable(void *data, bool state, bool full_scre static void sdl_dingux_set_texture_frame(void *data, const void *frame, bool rgb32, unsigned width, unsigned height, float alpha) { - sdl_dingux_video_t *vid = (sdl_dingux_video_t*)data; + sdl_dingux_video_t *vid = (sdl_dingux_video_t*)data; - int len = width * height * 2; - memcpy(vid->menu_frame, frame, len); + if (unlikely( + rgb32 || + (width > SDL_DINGUX_MENU_WIDTH) || + (height > SDL_DINGUX_MENU_HEIGHT))) + return; + + memcpy(vid->menu_texture, frame, width * height * sizeof(uint16_t)); } +static void sdl_dingux_gfx_set_nonblock_state(void *data, bool toggle, + bool adaptive_vsync_enabled, unsigned swap_interval) +{ + sdl_dingux_video_t *vid = (sdl_dingux_video_t*)data; + bool vsync = !toggle; -static void sdl_dingux_gfx_set_nonblock_state(void *a, bool b, bool c, unsigned d) { } + if (!vid || !vid->screen) + return; + + /* Check whether vsync status has changed */ + if (vid->vsync != vsync) + { + vid->vsync = vsync; + + /* Update video mode */ + sdl_dingux_set_output(vid, vid->screen->w, vid->screen->h, + vid->screen->pitch, vid->rgb32); + } +} static void sdl_dingux_gfx_check_window(sdl_dingux_video_t *vid) { @@ -249,26 +579,48 @@ static void sdl_dingux_gfx_check_window(sdl_dingux_video_t *vid) static bool sdl_dingux_gfx_alive(void *data) { sdl_dingux_video_t *vid = (sdl_dingux_video_t*)data; + sdl_dingux_gfx_check_window(vid); return !vid->quitting; } -static bool sdl_dingux_gfx_focus(void *data) { return true; } -static bool sdl_dingux_gfx_suppress_screensaver(void *data, bool enable) { return false; } -static bool sdl_dingux_gfx_has_windowed(void *data) { return false; } +static bool sdl_dingux_gfx_focus(void *data) +{ + return true; +} + +static bool sdl_dingux_gfx_suppress_screensaver(void *data, bool enable) +{ + return false; +} + +static bool sdl_dingux_gfx_has_windowed(void *data) +{ + return false; +} static void sdl_dingux_gfx_viewport_info(void *data, struct video_viewport *vp) { sdl_dingux_video_t *vid = (sdl_dingux_video_t*)data; + vp->x = 0; vp->y = 0; vp->width = vp->full_width = vid->screen->w; vp->height = vp->full_height = vid->screen->h; } -static void sdl_dingux_set_filtering(void *data, unsigned index, bool smooth, bool ctx_scaling) { } -static void sdl_dingux_apply_state_changes(void *data) { } -static uint32_t sdl_dingux_get_flags(void *data) { return 0; } +static void sdl_dingux_set_filtering(void *data, unsigned index, bool smooth, bool ctx_scaling) +{ +} + +static void sdl_dingux_apply_state_changes(void *data) +{ +} + +static uint32_t sdl_dingux_get_flags(void *data) +{ + return 0; +} static const video_poke_interface_t sdl_dingux_poke_interface = { sdl_dingux_get_flags, @@ -287,16 +639,23 @@ static const video_poke_interface_t sdl_dingux_poke_interface = { sdl_dingux_set_texture_frame, sdl_dingux_set_texture_enable, NULL, - NULL,//sdl_show_mouse, - NULL,//sdl_grab_mouse_toggle, - NULL, /* get_current_shader */ - NULL, /* get_current_software_framebuffer */ - NULL /* get_hw_render_interface */ + NULL, /* sdl_show_mouse */ + NULL, /* sdl_grab_mouse_toggle */ + NULL, /* get_current_shader */ + NULL, /* get_current_software_framebuffer */ + NULL /* get_hw_render_interface */ }; -static void sdl_dingux_get_poke_interface(void *data, const video_poke_interface_t **iface) { *iface = &sdl_dingux_poke_interface; } +static void sdl_dingux_get_poke_interface(void *data, const video_poke_interface_t **iface) +{ + *iface = &sdl_dingux_poke_interface; +} + static bool sdl_dingux_gfx_set_shader(void *data, - enum rarch_shader_type type, const char *path) { return false; } + enum rarch_shader_type type, const char *path) +{ + return false; +} video_driver_t video_sdl_dingux = { sdl_dingux_gfx_init, diff --git a/griffin/griffin.c b/griffin/griffin.c index a9ca778302..78c2a47e7c 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -1151,6 +1151,10 @@ FRONTEND #include "../frontend/drivers/platform_dos.c" #endif +#if defined(DINGUX) +#include "../dingux/dingux_utils.c" +#endif + #include "../core_info.c" #include "../core_backup.c" diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index bf954e0434..c4dc885a06 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -2996,6 +2996,12 @@ MSG_HASH( MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO_INDEX, "aspect_ratio_index" ) +#if defined(DINGUX) +MSG_HASH( + MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_KEEP_ASPECT, + "video_dingux_ipu_keep_aspect" + ) +#endif MSG_HASH( MENU_ENUM_LABEL_VIDEO_BLACK_FRAME_INSERTION, "video_black_frame_insertion" @@ -3016,6 +3022,10 @@ MSG_HASH( MENU_ENUM_LABEL_VIDEO_FILTER, "video_filter" ) +MSG_HASH( + MENU_ENUM_LABEL_VIDEO_FILTER_REMOVE, + "video_filter_remove" + ) MSG_HASH( MENU_ENUM_LABEL_VIDEO_FILTER_DIR, "video_filter_dir" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 26d70206a6..0b6cd3d0cf 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -1368,6 +1368,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_FILTER, "Apply a CPU-powered video filter.\nNOTE: Might come at a high performance cost. Some video filters might only work for cores that use 32bit or 16bit color." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_REMOVE, + "Remove Video Filter" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_FILTER_REMOVE, + "Unload any active CPU-powered video filter." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_NOTCH_WRITE_OVER, "Enable fullscreen over notch in Android devices" @@ -1579,6 +1587,16 @@ MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_ASPECT_RATIO, "Floating point value for video aspect ratio (width / height), used if the Aspect Ratio is set to 'Custom Aspect Ratio'." ) +#if defined(DINGUX) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_IPU_KEEP_ASPECT, + "Keep Aspect Ratio" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_DINGUX_IPU_KEEP_ASPECT, + "Maintain 1:1 pixel aspect ratios when scaling content via the internal IPU. If disabled, images will be stretched to fill the entire display." + ) +#endif MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_VIEWPORT_CUSTOM_X, "Custom Aspect Ratio (X Position)" diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 1bc68fb2b5..ed00c4f0ac 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -1932,8 +1932,8 @@ static int default_action_ok_load_content_from_playlist_from_menu(const char *_p return 0; } -DEFAULT_ACTION_OK_SET(action_ok_set_path_audiofilter, ACTION_OK_SET_PATH_VIDEO_FILTER, MSG_UNKNOWN) -DEFAULT_ACTION_OK_SET(action_ok_set_path_videofilter, ACTION_OK_SET_PATH_AUDIO_FILTER, MSG_UNKNOWN) +DEFAULT_ACTION_OK_SET(action_ok_set_path_audiofilter, ACTION_OK_SET_PATH_AUDIO_FILTER, MSG_UNKNOWN) +DEFAULT_ACTION_OK_SET(action_ok_set_path_videofilter, ACTION_OK_SET_PATH_VIDEO_FILTER, MSG_UNKNOWN) DEFAULT_ACTION_OK_SET(action_ok_set_path_overlay, ACTION_OK_SET_PATH_OVERLAY, MSG_UNKNOWN) #ifdef HAVE_VIDEO_LAYOUT DEFAULT_ACTION_OK_SET(action_ok_set_path_video_layout,ACTION_OK_SET_PATH_VIDEO_LAYOUT, MSG_UNKNOWN) @@ -2966,6 +2966,30 @@ static int action_ok_shader_preset_remove_game(const char *path, } #endif +static int action_ok_video_filter_remove(const char *path, + const char *label, unsigned type, size_t idx, size_t entry_idx) +{ + settings_t *settings = config_get_ptr(); + + if (!settings) + menu_cbs_exit(); + + if (!string_is_empty(settings->paths.path_softfilter_plugin)) + { + bool refresh = false; + + /* Unload video filter */ + settings->paths.path_softfilter_plugin[0] = '\0'; + command_event(CMD_EVENT_REINIT, NULL); + + /* Refresh menu */ + menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh); + menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL); + } + + return 0; +} + #ifdef HAVE_CHEATS static void menu_input_st_string_cb_cheat_file_save_as( void *userdata, const char *str) @@ -7987,6 +8011,9 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs, case MENU_SETTING_ACTION_CORE_LOCK: BIND_ACTION_OK(cbs, action_ok_core_lock); break; + case MENU_SETTING_ACTION_VIDEO_FILTER_REMOVE: + BIND_ACTION_OK(cbs, action_ok_video_filter_remove); + break; default: return -1; } diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index 4971bb10cf..c459686fd1 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -110,10 +110,21 @@ static int action_start_video_filter_file_load( settings_t *settings = config_get_ptr(); if (!settings) - return -1; + return menu_cbs_exit(); + + if (!string_is_empty(settings->paths.path_softfilter_plugin)) + { + bool refresh = false; + + /* Unload video filter */ + settings->paths.path_softfilter_plugin[0] = '\0'; + command_event(CMD_EVENT_REINIT, NULL); + + /* Refresh menu */ + menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh); + menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL); + } - settings->paths.path_softfilter_plugin[0] = '\0'; - command_event(CMD_EVENT_REINIT, NULL); return 0; } diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index edc4f7249d..ee8ba7b356 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -358,6 +358,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_quit_press_twice, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_onscreen_notifications_enable, MENU_ENUM_SUBLABEL_VIDEO_FONT_ENABLE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_crop_overscan, MENU_ENUM_SUBLABEL_VIDEO_CROP_OVERSCAN) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_filter, MENU_ENUM_SUBLABEL_VIDEO_FILTER) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_filter_remove, MENU_ENUM_SUBLABEL_VIDEO_FILTER_REMOVE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_nickname, MENU_ENUM_SUBLABEL_NETPLAY_NICKNAME) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_username, MENU_ENUM_SUBLABEL_CHEEVOS_USERNAME) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_password, MENU_ENUM_SUBLABEL_CHEEVOS_PASSWORD) @@ -806,6 +807,9 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_quick_menu, DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_core_information, MENU_ENUM_SUBLABEL_CORE_INFORMATION) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_disc_information, MENU_ENUM_SUBLABEL_DISC_INFORMATION) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_aspect_ratio, MENU_ENUM_SUBLABEL_VIDEO_ASPECT_RATIO) +#if defined(DINGUX) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_dingux_ipu_keep_aspect, MENU_ENUM_SUBLABEL_VIDEO_DINGUX_IPU_KEEP_ASPECT) +#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) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_viewport_custom_x, MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_X) @@ -1798,6 +1802,11 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_aspect_ratio); break; +#if defined(DINGUX) + case MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_KEEP_ASPECT: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_dingux_ipu_keep_aspect); + break; +#endif case MENU_ENUM_LABEL_CORE_INFORMATION: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_information); break; @@ -3196,6 +3205,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_FILTER: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_filter); break; + case MENU_ENUM_LABEL_VIDEO_FILTER_REMOVE: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_filter_remove); + break; case MENU_ENUM_LABEL_VIDEO_CROP_OVERSCAN: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_crop_overscan); break; diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index 37a76ed29b..823a05ee49 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -9773,6 +9773,7 @@ static void materialui_list_insert( break; case MENU_SETTING_ACTION_CORE_DELETE: case MENU_SETTING_ACTION_CORE_DELETE_BACKUP: + case MENU_SETTING_ACTION_VIDEO_FILTER_REMOVE: node->icon_texture_index = MUI_TEXTURE_REMOVE; node->icon_type = MUI_ICON_TYPE_INTERNAL; break; diff --git a/menu/drivers/ozone/ozone_texture.c b/menu/drivers/ozone/ozone_texture.c index d7fcdb023c..1b43d6d1cd 100644 --- a/menu/drivers/ozone/ozone_texture.c +++ b/menu/drivers/ozone/ozone_texture.c @@ -248,6 +248,7 @@ uintptr_t ozone_entries_icon_get_texture(ozone_handle_t *ozone, case MENU_ENUM_LABEL_CORE_DELETE: case MENU_ENUM_LABEL_DELETE_PLAYLIST: case MENU_ENUM_LABEL_CORE_DELETE_BACKUP_LIST: + case MENU_ENUM_LABEL_VIDEO_FILTER_REMOVE: return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_CLOSE]; case MENU_ENUM_LABEL_CORE_LOCK: return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_CORE]; diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 3d94265d3b..09484165c1 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -1054,6 +1054,32 @@ static uint16_t argb32_to_bgra4444(uint32_t col) return (b << 12) | (g << 8) | (r << 4) | a; } +/* DINGUX SDL */ +static uint16_t argb32_to_rgb565(uint32_t col) +{ + /* Extract colour components */ + unsigned a = (col >> 24) & 0xff; + unsigned r = (col >> 16) & 0xff; + unsigned g = (col >> 8) & 0xff; + unsigned b = col & 0xff; + if (a < 0xff) + { + /* RGB565 has no alpha component - as with PS2 colour conversion, + * have to darken each RGB value according to the alpha component + * of the input colour... */ + float a_factor = (float)a * (1.0 / 255.0); + r = (unsigned)(((float)r * a_factor) + 0.5) & 0xff; + g = (unsigned)(((float)g * a_factor) + 0.5) & 0xff; + b = (unsigned)(((float)b * a_factor) + 0.5) & 0xff; + } + /* Convert from 8 bit to 5 bit */ + r = r >> 3; + g = g >> 3; + b = b >> 3; + /* Return final value */ + return (r << 11) | (g << 6) | b; +} + /* All other platforms */ static uint16_t argb32_to_rgba4444(uint32_t col) { @@ -1077,16 +1103,18 @@ static void rgui_set_pixel_format_function(void) return; } - if ( string_is_equal(driver_ident, "ps2")) /* PS2 */ + if ( string_is_equal(driver_ident, "ps2")) /* PS2 */ argb32_to_pixel_platform_format = argb32_to_abgr1555; - else if (string_is_equal(driver_ident, "gx")) /* GEKKO */ + else if (string_is_equal(driver_ident, "gx")) /* GEKKO */ argb32_to_pixel_platform_format = argb32_to_rgb5a3; - else if (string_is_equal(driver_ident, "psp1")) /* PSP */ + else if (string_is_equal(driver_ident, "psp1")) /* PSP */ argb32_to_pixel_platform_format = argb32_to_abgr4444; - else if (string_is_equal(driver_ident, "d3d10") || /* D3D10/11/12 */ + else if (string_is_equal(driver_ident, "d3d10") || /* D3D10/11/12 */ string_is_equal(driver_ident, "d3d11") || string_is_equal(driver_ident, "d3d12")) argb32_to_pixel_platform_format = argb32_to_bgra4444; + else if (string_is_equal(driver_ident, "sdl_dingux")) /* DINGUX SDL */ + argb32_to_pixel_platform_format = argb32_to_rgb565; else argb32_to_pixel_platform_format = argb32_to_rgba4444; } @@ -2302,12 +2330,16 @@ static void load_custom_theme(rgui_t *rgui, rgui_theme_t *theme_colors, const ch unsigned particle_color = 0; config_file_t *conf = NULL; const char *wallpaper_key = NULL; - settings_t *settings = config_get_ptr(); bool success = false; - unsigned rgui_aspect_ratio = settings->uints.menu_rgui_aspect_ratio; +#if defined(DINGUX) + unsigned aspect_ratio = RGUI_ASPECT_RATIO_4_3; +#else + settings_t *settings = config_get_ptr(); + unsigned aspect_ratio = settings->uints.menu_rgui_aspect_ratio; +#endif /* Determine which type of wallpaper to load */ - switch (rgui_aspect_ratio) + switch (aspect_ratio) { case RGUI_ASPECT_RATIO_16_9: case RGUI_ASPECT_RATIO_16_9_CENTRE: @@ -4250,7 +4282,11 @@ static void rgui_update_menu_viewport(rgui_t *rgui) #if !defined(GEKKO) bool do_integer_scaling = false; settings_t *settings = config_get_ptr(); +#if defined(DINGUX) + unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE; +#else unsigned aspect_ratio_lock = settings ? settings->uints.menu_rgui_aspect_ratio_lock : 0; +#endif if (!settings) return; @@ -4373,13 +4409,22 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui, bool delay_update) * the usual 426, since the last two bits of the * width value must be zero... */ unsigned max_frame_buf_width = 424; +#elif defined(DINGUX) + /* Dingux devices use a fixed framebuffer size + * of 320x240 */ + unsigned max_frame_buf_width = 320; #else struct video_viewport vp; unsigned max_frame_buf_width = RGUI_MAX_FB_WIDTH; #endif +#if defined(DINGUX) + unsigned aspect_ratio = RGUI_ASPECT_RATIO_4_3; + unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE; +#else settings_t *settings = config_get_ptr(); - unsigned rgui_aspect_ratio = settings->uints.menu_rgui_aspect_ratio; + unsigned aspect_ratio = settings->uints.menu_rgui_aspect_ratio; unsigned aspect_ratio_lock = settings->uints.menu_rgui_aspect_ratio_lock; +#endif rgui_framebuffer_free(); rgui_background_free(); @@ -4388,7 +4433,7 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui, bool delay_update) rgui_thumbnail_free(&mini_left_thumbnail); /* Cache new aspect ratio */ - rgui->menu_aspect_ratio = rgui_aspect_ratio; + rgui->menu_aspect_ratio = aspect_ratio; /* Set frame buffer dimensions: */ @@ -4399,6 +4444,10 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui, bool delay_update) * values */ gfx_display_get_fb_size(&fb_width, &fb_height, &fb_pitch); rgui_frame_buf.height = fb_height; +#elif defined(DINGUX) + /* Dingux devices use a fixed framebuffer size + * of 320x240 */ + rgui_frame_buf.height = 240; #else /* If window height is less than RGUI default * height of 240, allow the frame buffer to @@ -4494,14 +4543,14 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui, bool delay_update) * - Must be less than max_frame_buf_width * (note that this is a redundant safety * check - it can never actually happen...) - * - On platforms other than the Wii, must + * - On platforms other than Wii and dingux, must * be less than window width but greater than * defined minimum width */ rgui_frame_buf.width = (rgui_frame_buf.width > max_frame_buf_width) ? max_frame_buf_width : rgui_frame_buf.width; base_term_width = (base_term_width > rgui_frame_buf.width) ? rgui_frame_buf.width : base_term_width; -#if !defined(GEKKO) +#if !(defined(GEKKO) || defined(DINGUX)) if (vp.full_width < rgui_frame_buf.width) { rgui_frame_buf.width = (vp.full_width > RGUI_MIN_FB_WIDTH) ? @@ -4665,7 +4714,11 @@ static void *rgui_init(void **userdata, bool video_is_threaded) rgui_t *rgui = NULL; settings_t *settings = config_get_ptr(); gfx_display_t *p_disp = disp_get_ptr(); +#if defined(DINGUX) + unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE; +#else unsigned aspect_ratio_lock = settings->uints.menu_rgui_aspect_ratio_lock; +#endif menu_handle_t *menu = (menu_handle_t*)calloc(1, sizeof(*menu)); if (!menu) @@ -4822,7 +4875,11 @@ static void rgui_set_texture(void) unsigned fb_width, fb_height; settings_t *settings = config_get_ptr(); gfx_display_t *p_disp = disp_get_ptr(); +#if defined(DINGUX) + unsigned internal_upscale_level = RGUI_UPSCALE_NONE; +#else unsigned internal_upscale_level = settings->uints.menu_rgui_internal_upscale_level; +#endif /* Framebuffer is dirty and needs to be updated? */ if (!p_disp->framebuf_dirty) @@ -5263,8 +5320,12 @@ static void rgui_populate_entries(void *data, const char *label, unsigned k) { rgui_t *rgui = (rgui_t*)data; +#if defined(DINGUX) + unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE; +#else settings_t *settings = config_get_ptr(); unsigned aspect_ratio_lock = settings->uints.menu_rgui_aspect_ratio_lock; +#endif if (!rgui) return; @@ -5423,7 +5484,13 @@ static void rgui_frame(void *data, video_frame_info_t *video_info) settings_t *settings = config_get_ptr(); bool bg_filler_thickness_enable = settings->bools.menu_rgui_background_filler_thickness_enable; bool border_filler_thickness_enable = settings->bools.menu_rgui_border_filler_thickness_enable; +#if defined(DINGUX) + unsigned aspect_ratio = RGUI_ASPECT_RATIO_4_3; + unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE; +#else + unsigned aspect_ratio = settings->uints.menu_rgui_aspect_ratio; unsigned aspect_ratio_lock = settings->uints.menu_rgui_aspect_ratio_lock; +#endif bool border_filler_enable = settings->bools.menu_rgui_border_filler_enable; unsigned video_width = video_info->width; unsigned video_height = video_info->height; @@ -5500,7 +5567,7 @@ static void rgui_frame(void *data, video_frame_info_t *video_info) * the next instance of rgui_render() */ /* > Check for changes in aspect ratio */ - if (settings->uints.menu_rgui_aspect_ratio != rgui->menu_aspect_ratio) + if (aspect_ratio != rgui->menu_aspect_ratio) { /* If user changes aspect ratio directly after opening * the video scaling settings menu, then all bets are off @@ -5617,7 +5684,11 @@ static void rgui_toggle(void *userdata, bool menu_on) { rgui_t *rgui = (rgui_t*)userdata; settings_t *settings = config_get_ptr(); +#if defined(DINGUX) + unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE; +#else unsigned aspect_ratio_lock = settings ? settings->uints.menu_rgui_aspect_ratio_lock : 0; +#endif /* TODO/FIXME - when we close RetroArch, this function * gets called and settings is NULL at this point. diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index e491c233f5..c9b7987213 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -2699,6 +2699,7 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb, case MENU_ENUM_LABEL_CORE_DELETE: case MENU_ENUM_LABEL_DELETE_PLAYLIST: case MENU_ENUM_LABEL_CORE_DELETE_BACKUP_LIST: + case MENU_ENUM_LABEL_VIDEO_FILTER_REMOVE: return xmb->textures.list[XMB_TEXTURE_CLOSE]; case MENU_ENUM_LABEL_CORE_LOCK: return xmb->textures.list[XMB_TEXTURE_CORE]; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index afe81c1d57..3b77e09c52 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -5633,6 +5633,7 @@ unsigned menu_displaylist_build_list( break; case DISPLAYLIST_VIDEO_SETTINGS_LIST: { + settings_t *settings = config_get_ptr(); gfx_ctx_flags_t flags; if (video_display_server_get_flags(&flags)) @@ -5702,6 +5703,14 @@ unsigned menu_displaylist_build_list( MENU_ENUM_LABEL_VIDEO_FILTER, PARSE_ONLY_PATH, false) == 0) count++; + + if (!string_is_empty(settings->paths.path_softfilter_plugin)) + if (menu_entries_append_enum(list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_REMOVE), + msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_FILTER_REMOVE), + MENU_ENUM_LABEL_VIDEO_FILTER_REMOVE, + MENU_SETTING_ACTION_VIDEO_FILTER_REMOVE, 0, 0)) + count++; #endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_NOTCH_WRITE_OVER, @@ -7347,45 +7356,58 @@ unsigned menu_displaylist_build_list( case DISPLAYLIST_VIDEO_SCALING_SETTINGS_LIST: { settings_t *settings = config_get_ptr(); - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER, - PARSE_ONLY_BOOL, false) == 0) - count++; - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO_INDEX, - PARSE_ONLY_UINT, false) == 0) - count++; - switch (settings->uints.video_aspect_ratio_idx) + +#if defined(DINGUX) + if (string_is_equal(settings->arrays.video_driver, "sdl_dingux")) { - case ASPECT_RATIO_CONFIG: - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO, - PARSE_ONLY_FLOAT, false) == 0) - count++; - break; - case ASPECT_RATIO_CUSTOM: - if (!settings->bools.video_scale_integer) - { + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_KEEP_ASPECT, + PARSE_ONLY_BOOL, false) == 0) + count++; + } + else +#endif + { + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER, + PARSE_ONLY_BOOL, false) == 0) + count++; + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO_INDEX, + PARSE_ONLY_UINT, false) == 0) + count++; + switch (settings->uints.video_aspect_ratio_idx) + { + case ASPECT_RATIO_CONFIG: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_X, - PARSE_ONLY_INT, false) == 0) + MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO, + PARSE_ONLY_FLOAT, false) == 0) + count++; + break; + case ASPECT_RATIO_CUSTOM: + if (!settings->bools.video_scale_integer) + { + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_X, + PARSE_ONLY_INT, false) == 0) + count++; + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_Y, + PARSE_ONLY_INT, false) == 0) + count++; + } + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_WIDTH, + PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_Y, - PARSE_ONLY_INT, false) == 0) + MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_HEIGHT, + PARSE_ONLY_UINT, false) == 0) count++; - } - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_WIDTH, - PARSE_ONLY_UINT, false) == 0) - count++; - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_HEIGHT, - PARSE_ONLY_UINT, false) == 0) - count++; - break; - default: - break; + break; + default: + break; + } } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, diff --git a/menu/menu_driver.h b/menu/menu_driver.h index 84566bf6d5..0a31bce6fd 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -220,6 +220,8 @@ enum menu_settings_type MENU_SETTING_ACTION_CORE_DELETE_BACKUP, MENU_SETTING_ITEM_CORE_DELETE_BACKUP, + MENU_SETTING_ACTION_VIDEO_FILTER_REMOVE, + MENU_SETTINGS_LAST }; diff --git a/menu/menu_setting.c b/menu/menu_setting.c index ec64fef6cd..ab37f5cc9f 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -118,6 +118,10 @@ #include <3ds/services/cfgu.h> #endif +#if defined(DINGUX) +#include "../dingux/dingux_utils.h" +#endif + #if defined(ANDROID) #include "../play_feature_delivery/play_feature_delivery.h" #endif @@ -7124,6 +7128,11 @@ static void general_write_handler(rarch_setting_t *setting) case MENU_ENUM_LABEL_VIDEO_CTX_SCALING: video_driver_set_filtering(1, settings->bools.video_ctx_scaling, settings->bools.video_ctx_scaling); break; +#if defined(DINGUX) + case MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_KEEP_ASPECT: + dingux_ipu_set_aspect_ratio_enable(*setting->value.target.boolean); + break; +#endif case MENU_ENUM_LABEL_VIDEO_ROTATION: { rarch_system_info_t *system = runloop_get_system_info(); @@ -10332,6 +10341,7 @@ static bool setting_append_list( END_SUB_GROUP(list, list_info, parent_group); START_SUB_GROUP(list, list_info, "Aspect", &group_info, &subgroup_info, parent_group); + CONFIG_UINT( list, list_info, &settings->uints.video_aspect_ratio_idx, @@ -10479,6 +10489,26 @@ static bool setting_append_list( CMD_EVENT_VIDEO_APPLY_STATE_CHANGES); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED); +#if defined(DINGUX) + if (string_is_equal(settings->arrays.video_driver, "sdl_dingux")) + { + CONFIG_BOOL( + list, list_info, + &settings->bools.video_dingux_ipu_keep_aspect, + MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_KEEP_ASPECT, + MENU_ENUM_LABEL_VALUE_VIDEO_DINGUX_IPU_KEEP_ASPECT, + DEFAULT_DINGUX_IPU_KEEP_ASPECT, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + } +#endif + END_SUB_GROUP(list, list_info, parent_group); START_SUB_GROUP(list, list_info, "Scaling", &group_info, &subgroup_info, parent_group); @@ -13805,6 +13835,7 @@ static bool setting_append_list( (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX; } +#if !defined(DINGUX) CONFIG_UINT( list, list_info, &settings->uints.menu_rgui_aspect_ratio, @@ -13841,6 +13872,7 @@ static bool setting_append_list( menu_settings_list_current_add_range(list, list_info, 0, RGUI_ASPECT_RATIO_LOCK_LAST-1, 1, true, true); #endif (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX; +#endif CONFIG_UINT( list, list_info, diff --git a/msg_hash.h b/msg_hash.h index 460c0f66a4..2ff99df6de 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -2169,6 +2169,7 @@ enum msg_hash_enums MENU_LABEL(RECORDING_OUTPUT_DIRECTORY), MENU_LABEL(RECORDING_CONFIG_DIRECTORY), MENU_LABEL(VIDEO_FILTER), + MENU_LABEL(VIDEO_FILTER_REMOVE), MENU_LABEL(PAL60_ENABLE), MENU_LABEL(CONTENT_HISTORY_PATH), @@ -2328,6 +2329,9 @@ enum msg_hash_enums MENU_LABEL(VIDEO_FORCE_ASPECT), MENU_LABEL(VIDEO_ASPECT_RATIO_AUTO), MENU_LABEL(VIDEO_ASPECT_RATIO_INDEX), +#if defined(DINGUX) + MENU_LABEL(VIDEO_DINGUX_IPU_KEEP_ASPECT), +#endif MENU_LABEL(VIDEO_VFILTER), MENU_LABEL(VIDEO_GPU_RECORD), MENU_LABEL(RECORD_USE_OUTPUT_DIRECTORY),