From dc276380254be96426c9180ab4e0fd3b083ba051 Mon Sep 17 00:00:00 2001 From: Quantum Date: Sat, 28 Aug 2021 18:08:46 -0400 Subject: [PATCH] [client] egl: implement loading and saving of filter order --- client/renderers/EGL/filter.h | 3 + client/renderers/EGL/filter_downscale.c | 1 + client/renderers/EGL/filter_ffx_cas.c | 1 + client/renderers/EGL/filter_ffx_fsr1.c | 1 + client/renderers/EGL/postprocess.c | 88 ++++++++++++++++++++++++- 5 files changed, 93 insertions(+), 1 deletion(-) diff --git a/client/renderers/EGL/filter.h b/client/renderers/EGL/filter.h index f8c65901..5a9a75fe 100644 --- a/client/renderers/EGL/filter.h +++ b/client/renderers/EGL/filter.h @@ -31,6 +31,9 @@ typedef struct EGL_Filter EGL_Filter; typedef struct EGL_FilterOps { + /* the identifier of this filter */ + const char * id; + /* the friendly name of this filter */ const char * name; diff --git a/client/renderers/EGL/filter_downscale.c b/client/renderers/EGL/filter_downscale.c index b649ccf0..b60c8fc7 100644 --- a/client/renderers/EGL/filter_downscale.c +++ b/client/renderers/EGL/filter_downscale.c @@ -417,6 +417,7 @@ static GLuint egl_filterDownscaleRun(EGL_Filter * filter, EGL_Model * model, EGL_FilterOps egl_filterDownscaleOps = { + .id = "downscale", .name = "Downscaler", .type = EGL_FILTER_TYPE_DOWNSCALE, .earlyInit = egl_filterDownscaleEarlyInit, diff --git a/client/renderers/EGL/filter_ffx_cas.c b/client/renderers/EGL/filter_ffx_cas.c index 623d3e9b..fab9bf55 100644 --- a/client/renderers/EGL/filter_ffx_cas.c +++ b/client/renderers/EGL/filter_ffx_cas.c @@ -279,6 +279,7 @@ static GLuint egl_filterFFXCASRun(EGL_Filter * filter, EGL_Model * model, EGL_FilterOps egl_filterFFXCASOps = { + .id = "ffxCAS", .name = "AMD FidelityFX CAS", .type = EGL_FILTER_TYPE_EFFECT, .earlyInit = egl_filterFFXCASEarlyInit, diff --git a/client/renderers/EGL/filter_ffx_fsr1.c b/client/renderers/EGL/filter_ffx_fsr1.c index d90509eb..1282b364 100644 --- a/client/renderers/EGL/filter_ffx_fsr1.c +++ b/client/renderers/EGL/filter_ffx_fsr1.c @@ -414,6 +414,7 @@ static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter, EGL_Model * model, EGL_FilterOps egl_filterFFXFSR1Ops = { + .id = "ffxFSR1", .name = "AMD FidelityFX FSR", .type = EGL_FILTER_TYPE_UPSCALE, .earlyInit = egl_filterFFXFSR1EarlyInit, diff --git a/client/renderers/EGL/postprocess.c b/client/renderers/EGL/postprocess.c index db2877be..cbecadf7 100644 --- a/client/renderers/EGL/postprocess.c +++ b/client/renderers/EGL/postprocess.c @@ -18,6 +18,7 @@ * Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define _GNU_SOURCE #include "postprocess.h" #include "filters.h" #include "app.h" @@ -25,6 +26,7 @@ #include #include +#include #include #include #include @@ -62,7 +64,20 @@ struct EGL_PostProcess void egl_postProcessEarlyInit(void) { - for(int i = 0; i < ARRAY_LENGTH(EGL_Filters); ++i) + static struct Option options[] = + { + { + .module = "eglFilter", + .name = "order", + .description = "The order of filters to use", + .type = OPTION_TYPE_STRING, + .value.x_string = "" + }, + { 0 } + }; + option_register(options); + + for (int i = 0; i < ARRAY_LENGTH(EGL_Filters); ++i) EGL_Filters[i]->earlyInit(); } @@ -138,6 +153,22 @@ static bool savePreset(struct EGL_PostProcess * this, const char * name) vector_forEach(filter, &this->filters) egl_filterSaveState(filter); + size_t orderLen = 0; + vector_forEach(filter, &this->filters) + orderLen += strlen(filter->ops.id) + 1; + + char order[orderLen]; + char * p = order; + vector_forEach(filter, &this->filters) + { + strcpy(p, filter->ops.id); + p += strlen(filter->ops.id); + *p++ = ';'; + } + if (p > order) + p[-1] = '\0'; + option_set_string("eglFilter", "order", order); + char * path; alloc_sprintf(&path, "%s/%s", this->presetDir, name); if (!path) @@ -167,6 +198,59 @@ static bool savePreset(struct EGL_PostProcess * this, const char * name) return true; } +static int stringListIndex(StringList list, const char * str) +{ + unsigned int count = stringlist_count(list); + for (unsigned int i = 0; i < count; ++i) + if (strcmp(stringlist_at(list, i), str) == 0) + return i; + return INT_MAX; +} + +static int compareFilterOrder(const void * a_, const void * b_, void * opaque) +{ + const EGL_Filter * a = *(const EGL_Filter **)a_; + const EGL_Filter * b = *(const EGL_Filter **)b_; + StringList order = opaque; + + return stringListIndex(order, a->ops.id) - stringListIndex(order, b->ops.id); +} + +static void reorderFilters(struct EGL_PostProcess * this) +{ + StringList order = stringlist_new(false); + if (!order) + { + DEBUG_ERROR("Failed to allocate memory"); + return; + } + + char * orderStr = strdup(option_get_string("eglFilter", "order")); + if (!orderStr) + { + DEBUG_ERROR("Failed to allocate memory"); + stringlist_free(&order); + return; + } + + char * p = orderStr; + while (*p) + { + stringlist_push(order, p); + char * end = strchr(p, ';'); + if (!end) + break; + *end = '\0'; + p = end + 1; + } + + qsort_r(vector_data(&this->filters), vector_size(&this->filters), + sizeof(EGL_Filter *), compareFilterOrder, order); + + stringlist_free(&order); + free(orderStr); +} + static void loadPreset(struct EGL_PostProcess * this, const char * name) { char * path; @@ -194,6 +278,7 @@ static void loadPreset(struct EGL_PostProcess * this, const char * name) EGL_Filter * filter; vector_forEach(filter, &this->filters) egl_filterLoadState(filter); + reorderFilters(this); } static void createPreset(struct EGL_PostProcess * this) @@ -408,6 +493,7 @@ bool egl_postProcessInit(EGL_PostProcess ** pp) egl_modelSetDefault(this->model, false); loadPresetList(this); + reorderFilters(this); app_overlayConfigRegisterTab("EGL Filters", configUI, this); *pp = this;