From c4bb2f5ad7153b171f39a4f95e23fa35818f3108 Mon Sep 17 00:00:00 2001
From: jdgleaver <james@leaver.myzen.co.uk>
Date: Wed, 5 Jun 2019 17:04:23 +0100
Subject: [PATCH] (XMB/Ozone) Add optional thumbnail upscaling

---
 config.def.h                 |  2 +
 configuration.c              |  1 +
 configuration.h              |  1 +
 intl/msg_hash_lbl.h          |  2 +
 intl/msg_hash_us.h           |  8 ++++
 menu/cbs/menu_cbs_ok.c       |  2 +-
 menu/cbs/menu_cbs_sublabel.c |  4 ++
 menu/drivers/materialui.c    |  2 +-
 menu/drivers/ozone/ozone.c   | 12 ++----
 menu/drivers/rgui.c          |  4 +-
 menu/drivers/stripes.c       | 10 ++---
 menu/drivers/xmb.c           | 18 ++++----
 menu/menu_displaylist.c      |  1 +
 menu/menu_setting.c          | 17 ++++++++
 msg_hash.h                   |  1 +
 tasks/task_image.c           | 80 +++++++++++++++++++++++++++++++++++-
 tasks/tasks_internal.h       |  2 +-
 17 files changed, 137 insertions(+), 30 deletions(-)

diff --git a/config.def.h b/config.def.h
index 1613d04ecf..ca556e9caa 100644
--- a/config.def.h
+++ b/config.def.h
@@ -821,6 +821,8 @@ static const unsigned menu_thumbnails_default = 3;
 
 static const unsigned menu_left_thumbnails_default = 0;
 
+static const unsigned menu_thumbnail_upscale_threshold = 0;
+
 static const unsigned menu_timedate_style = 5;
 
 static const bool xmb_vertical_thumbnails = false;
diff --git a/configuration.c b/configuration.c
index 29de8f4491..3afd257805 100644
--- a/configuration.c
+++ b/configuration.c
@@ -1740,6 +1740,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
 #ifdef HAVE_MENU
    SETTING_UINT("dpi_override_value",           &settings->uints.menu_dpi_override_value, true, menu_dpi_override_value, false);
    SETTING_UINT("menu_thumbnails",              &settings->uints.menu_thumbnails, true, menu_thumbnails_default, false);
+   SETTING_UINT("menu_thumbnail_upscale_threshold", &settings->uints.menu_thumbnail_upscale_threshold, true, menu_thumbnail_upscale_threshold, false);
    SETTING_UINT("menu_timedate_style", &settings->uints.menu_timedate_style, true, menu_timedate_style, false);
    SETTING_UINT("menu_ticker_type",             &settings->uints.menu_ticker_type, true, menu_ticker_type, false);
 #ifdef HAVE_RGUI
diff --git a/configuration.h b/configuration.h
index d3c6a1e61d..b98957d165 100644
--- a/configuration.h
+++ b/configuration.h
@@ -457,6 +457,7 @@ typedef struct settings
       unsigned menu_timedate_style;
       unsigned menu_thumbnails;
       unsigned menu_left_thumbnails;
+      unsigned menu_thumbnail_upscale_threshold;
       unsigned menu_rgui_thumbnail_downscaler;
       unsigned menu_rgui_thumbnail_delay;
       unsigned menu_dpi_override_value;
diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h
index 13d2b5d714..8cc91688c5 100644
--- a/intl/msg_hash_lbl.h
+++ b/intl/msg_hash_lbl.h
@@ -1151,6 +1151,8 @@ MSG_HASH(MENU_ENUM_LABEL_LEFT_THUMBNAILS,
       "left thumbnails")
 MSG_HASH(MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS,
       "xmb_vertical_thumbnails")
+MSG_HASH(MENU_ENUM_LABEL_MENU_THUMBNAIL_UPSCALE_THRESHOLD,
+      "menu_thumbnail_upscale_threshold")
 MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER,
       "rgui_thumbnail_downscaler")
 MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DELAY,
diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h
index 4912e6b0b4..87ee4c3b3f 100644
--- a/intl/msg_hash_us.h
+++ b/intl/msg_hash_us.h
@@ -3034,6 +3034,14 @@ MSG_HASH(
     MENU_ENUM_LABEL_VALUE_XMB_VERTICAL_THUMBNAILS,
     "Thumbnails Vertical Disposition"
     )
+MSG_HASH(
+    MENU_ENUM_LABEL_VALUE_MENU_THUMBNAIL_UPSCALE_THRESHOLD,
+    "Thumbnail Upscaling Threshold"
+    )
+MSG_HASH(
+    MENU_ENUM_SUBLABEL_MENU_THUMBNAIL_UPSCALE_THRESHOLD,
+    "Automatically upscale thumbnail images with a width/height smaller than the specified value. Improves picture quality. Has a moderate performance impact."
+    )
 MSG_HASH(
     MENU_ENUM_LABEL_VALUE_MENU_RGUI_INLINE_THUMBNAILS,
     "Show Playlist Thumbnails"
diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c
index 74172cbb81..3464603ba7 100644
--- a/menu/cbs/menu_cbs_ok.c
+++ b/menu/cbs/menu_cbs_ok.c
@@ -1388,7 +1388,7 @@ static int generic_action_ok(const char *path,
                   action_path, sizeof(settings->paths.path_menu_wallpaper));
 
             task_push_image_load(action_path,
-                  video_driver_supports_rgba(),
+                  video_driver_supports_rgba(), 0,
                   menu_display_handle_wallpaper_upload, NULL);
          }
          break;
diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c
index 0df61f1b55..da17b32fa0 100644
--- a/menu/cbs/menu_cbs_sublabel.c
+++ b/menu/cbs/menu_cbs_sublabel.c
@@ -357,6 +357,7 @@ default_sublabel_macro(action_bind_sublabel_thumbnails_rgui,               MENU_
 default_sublabel_macro(action_bind_sublabel_left_thumbnails,               MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS)
 default_sublabel_macro(action_bind_sublabel_left_thumbnails_rgui,          MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS_RGUI)
 default_sublabel_macro(action_bind_sublabel_left_thumbnails_ozone,         MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS_OZONE)
+default_sublabel_macro(action_bind_sublabel_menu_thumbnail_upscale_threshold, MENU_ENUM_SUBLABEL_MENU_THUMBNAIL_UPSCALE_THRESHOLD)
 default_sublabel_macro(action_bind_sublabel_timedate_enable,               MENU_ENUM_SUBLABEL_TIMEDATE_ENABLE)
 default_sublabel_macro(action_bind_sublabel_timedate_style,                MENU_ENUM_SUBLABEL_TIMEDATE_STYLE)
 default_sublabel_macro(action_bind_sublabel_battery_level_enable,          MENU_ENUM_SUBLABEL_BATTERY_LEVEL_ENABLE)
@@ -1719,6 +1720,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
                BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_left_thumbnails);
             }
             break;
+         case MENU_ENUM_LABEL_MENU_THUMBNAIL_UPSCALE_THRESHOLD:
+            BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_thumbnail_upscale_threshold);
+            break;
          case MENU_ENUM_LABEL_MOUSE_ENABLE:
             BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_mouse_enable);
             break;
diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c
index 8ac2baa5d4..fbe6a0795d 100644
--- a/menu/drivers/materialui.c
+++ b/menu/drivers/materialui.c
@@ -1885,7 +1885,7 @@ static void materialui_context_reset(void *data, bool is_threaded)
 
    if (path_is_valid(settings->paths.path_menu_wallpaper))
       task_push_image_load(settings->paths.path_menu_wallpaper,
-            video_driver_supports_rgba(),
+            video_driver_supports_rgba(), 0,
             menu_display_handle_wallpaper_upload, NULL);
 }
 
diff --git a/menu/drivers/ozone/ozone.c b/menu/drivers/ozone/ozone.c
index ad9a85633f..0b2b9cdfd1 100644
--- a/menu/drivers/ozone/ozone.c
+++ b/menu/drivers/ozone/ozone.c
@@ -392,6 +392,7 @@ static void ozone_update_thumbnail_path(void *data, unsigned i, char pos)
 
 static void ozone_update_thumbnail_image(void *data)
 {
+   settings_t *settings             = config_get_ptr();
    ozone_handle_t *ozone            = (ozone_handle_t*)data;
    const char *right_thumbnail_path = NULL;
    const char *left_thumbnail_path  = NULL;
@@ -404,14 +405,14 @@ static void ozone_update_thumbnail_image(void *data)
    bool thumbnails_missing          = false;
 #endif
 
-   if (!ozone)
+   if (!ozone || !settings)
       return;
 
    if (menu_thumbnail_get_path(ozone->thumbnail_path_data, MENU_THUMBNAIL_RIGHT, &right_thumbnail_path))
    {
       if (path_is_valid(right_thumbnail_path))
          task_push_image_load(right_thumbnail_path,
-               supports_rgba,
+               supports_rgba, settings->uints.menu_thumbnail_upscale_threshold,
                menu_display_handle_thumbnail_upload, NULL);
       else
       {
@@ -428,7 +429,7 @@ static void ozone_update_thumbnail_image(void *data)
    {
       if (path_is_valid(left_thumbnail_path))
          task_push_image_load(left_thumbnail_path,
-               supports_rgba,
+               supports_rgba, settings->uints.menu_thumbnail_upscale_threshold,
                menu_display_handle_left_thumbnail_upload, NULL);
       else
       {
@@ -445,11 +446,6 @@ static void ozone_update_thumbnail_image(void *data)
    /* On demand thumbnail downloads */
    if (thumbnails_missing)
    {
-      settings_t *settings = config_get_ptr();
-
-      if (!settings)
-         return;
-
       if (settings->bools.network_on_demand_thumbnails)
       {
          const char *system = NULL;
diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c
index 57990cdfd4..ea49adcb1b 100644
--- a/menu/drivers/rgui.c
+++ b/menu/drivers/rgui.c
@@ -1602,7 +1602,7 @@ static bool request_thumbnail(
          /* Would like to cancel any existing image load tasks
           * here, but can't see how to do it... */
          if(task_push_image_load(thumbnail->path,
-                  video_driver_supports_rgba(),
+                  video_driver_supports_rgba(), 0,
                   (thumbnail_id == MENU_THUMBNAIL_LEFT) ?
             menu_display_handle_left_thumbnail_upload : menu_display_handle_thumbnail_upload, NULL))
          {
@@ -2204,7 +2204,7 @@ end:
              * here - in general, wallpaper is loaded once per session
              * and then forgotten, so performance issues are not a concern */
             task_push_image_load(wallpaper_path,
-                  video_driver_supports_rgba(),
+                  video_driver_supports_rgba(), 0,
                   menu_display_handle_wallpaper_upload, NULL);
       }
    }
diff --git a/menu/drivers/stripes.c b/menu/drivers/stripes.c
index a238a67d2b..b318237c36 100644
--- a/menu/drivers/stripes.c
+++ b/menu/drivers/stripes.c
@@ -1065,7 +1065,7 @@ static void stripes_update_thumbnail_image(void *data)
       {
          if (path_is_valid(stripes->thumbnail_file_path))
             task_push_image_load(stripes->thumbnail_file_path,
-                  supports_rgba,
+                  supports_rgba, 0,
                   menu_display_handle_thumbnail_upload, NULL);
          else
             video_driver_texture_unload(&stripes->thumbnail);
@@ -1078,7 +1078,7 @@ static void stripes_update_thumbnail_image(void *data)
       {
          if (path_is_valid(stripes->left_thumbnail_file_path))
             task_push_image_load(stripes->left_thumbnail_file_path,
-                  supports_rgba,
+                  supports_rgba, 0,
                   menu_display_handle_left_thumbnail_upload, NULL);
          else
             video_driver_texture_unload(&stripes->left_thumbnail);
@@ -1142,7 +1142,7 @@ static void stripes_update_savestate_thumbnail_image(void *data)
 
    if (path_is_valid(stripes->savestate_thumbnail_file_path))
       task_push_image_load(stripes->savestate_thumbnail_file_path,
-            video_driver_supports_rgba(),
+            video_driver_supports_rgba(), 0,
             menu_display_handle_savestate_thumbnail_upload, NULL);
    else
       video_driver_texture_unload(&stripes->savestate_thumbnail);
@@ -1519,7 +1519,7 @@ static void stripes_list_switch_new(stripes_handle_t *stripes,
            if (path_is_valid(path))
            {
               task_push_image_load(path,
-                    video_driver_supports_rgba(),
+                    video_driver_supports_rgba(), 0,
                   menu_display_handle_wallpaper_upload, NULL);
               if (!string_is_empty(stripes->bg_file_path))
                  free(stripes->bg_file_path);
@@ -3681,7 +3681,7 @@ static void stripes_context_reset_background(const char *iconpath)
 
    if (path_is_valid(path))
       task_push_image_load(path,
-            video_driver_supports_rgba(),
+            video_driver_supports_rgba(), 0,
             menu_display_handle_wallpaper_upload, NULL);
 
    if (path)
diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c
index 7842666331..0afd29078e 100644
--- a/menu/drivers/xmb.c
+++ b/menu/drivers/xmb.c
@@ -1008,6 +1008,7 @@ static void xmb_update_savestate_thumbnail_path(void *data, unsigned i)
 
 static void xmb_update_thumbnail_image(void *data)
 {
+   settings_t *settings             = config_get_ptr();
    xmb_handle_t *xmb                = (xmb_handle_t*)data;
    const char *right_thumbnail_path = NULL;
    const char *left_thumbnail_path  = NULL;
@@ -1020,14 +1021,14 @@ static void xmb_update_thumbnail_image(void *data)
    bool thumbnails_missing          = false;
 #endif
 
-   if (!xmb)
+   if (!xmb || !settings)
       return;
 
    if (menu_thumbnail_get_path(xmb->thumbnail_path_data, MENU_THUMBNAIL_RIGHT, &right_thumbnail_path))
    {
       if (path_is_valid(right_thumbnail_path))
          task_push_image_load(right_thumbnail_path,
-               supports_rgba,
+               supports_rgba, settings->uints.menu_thumbnail_upscale_threshold,
                menu_display_handle_thumbnail_upload, NULL);
       else
       {
@@ -1044,7 +1045,7 @@ static void xmb_update_thumbnail_image(void *data)
    {
       if (path_is_valid(left_thumbnail_path))
          task_push_image_load(left_thumbnail_path,
-               supports_rgba,
+               supports_rgba, settings->uints.menu_thumbnail_upscale_threshold,
                menu_display_handle_left_thumbnail_upload, NULL);
       else
       {
@@ -1061,11 +1062,6 @@ static void xmb_update_thumbnail_image(void *data)
    /* On demand thumbnail downloads */
    if (thumbnails_missing)
    {
-      settings_t *settings = config_get_ptr();
-
-      if (!settings)
-         return;
-
       if (settings->bools.network_on_demand_thumbnails)
       {
          const char *system = NULL;
@@ -1234,7 +1230,7 @@ static void xmb_update_savestate_thumbnail_image(void *data)
 
    if (path_is_valid(xmb->savestate_thumbnail_file_path))
       task_push_image_load(xmb->savestate_thumbnail_file_path,
-            video_driver_supports_rgba(),
+            video_driver_supports_rgba(), 0,
             menu_display_handle_savestate_thumbnail_upload, NULL);
    else
       video_driver_texture_unload(&xmb->savestate_thumbnail);
@@ -1690,7 +1686,7 @@ static void xmb_list_switch_new(xmb_handle_t *xmb,
          if (path_is_valid(path))
          {
             task_push_image_load(path,
-                  video_driver_supports_rgba(),
+                  video_driver_supports_rgba(), 0,
                   menu_display_handle_wallpaper_upload, NULL);
             if (!string_is_empty(xmb->bg_file_path))
                free(xmb->bg_file_path);
@@ -5065,7 +5061,7 @@ static void xmb_context_reset_background(const char *iconpath)
 
    if (path_is_valid(path))
       task_push_image_load(path,
-            video_driver_supports_rgba(),
+            video_driver_supports_rgba(), 0,
             menu_display_handle_wallpaper_upload, NULL);
 
 #ifdef ORBIS
diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c
index 47b3c238cc..9188faf6bc 100644
--- a/menu/menu_displaylist.c
+++ b/menu/menu_displaylist.c
@@ -4462,6 +4462,7 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct
                {MENU_ENUM_LABEL_THUMBNAILS,                                   PARSE_ONLY_UINT },
                {MENU_ENUM_LABEL_LEFT_THUMBNAILS,                              PARSE_ONLY_UINT },
                {MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS,                      PARSE_ONLY_BOOL },
+               {MENU_ENUM_LABEL_MENU_THUMBNAIL_UPSCALE_THRESHOLD,             PARSE_ONLY_UINT },
                {MENU_ENUM_LABEL_MENU_RGUI_SWAP_THUMBNAILS,                    PARSE_ONLY_BOOL },
                {MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER,               PARSE_ONLY_UINT },
                {MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DELAY,                    PARSE_ONLY_UINT },
diff --git a/menu/menu_setting.c b/menu/menu_setting.c
index 0bacca3e79..a20374b5de 100644
--- a/menu/menu_setting.c
+++ b/menu/menu_setting.c
@@ -12289,6 +12289,23 @@ static bool setting_append_list(
                   SD_FLAG_NONE);
          }
 
+         if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone"))
+         {
+            CONFIG_UINT(
+                  list, list_info,
+                  &settings->uints.menu_thumbnail_upscale_threshold,
+                  MENU_ENUM_LABEL_MENU_THUMBNAIL_UPSCALE_THRESHOLD,
+                  MENU_ENUM_LABEL_VALUE_MENU_THUMBNAIL_UPSCALE_THRESHOLD,
+                  menu_thumbnail_upscale_threshold,
+                  &group_info,
+                  &subgroup_info,
+                  parent_group,
+                  general_write_handler,
+                  general_read_handler);
+            (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
+            menu_settings_list_current_add_range(list, list_info, 0, 1024, 256, true, true);
+         }
+
          if (string_is_equal(settings->arrays.menu_driver, "rgui"))
          {
             CONFIG_UINT(
diff --git a/msg_hash.h b/msg_hash.h
index 9e8001daa2..8815ccc147 100644
--- a/msg_hash.h
+++ b/msg_hash.h
@@ -935,6 +935,7 @@ enum msg_hash_enums
    MENU_LABEL(LEFT_THUMBNAILS_RGUI),
    MENU_LABEL(LEFT_THUMBNAILS_OZONE),
    MENU_LABEL(XMB_VERTICAL_THUMBNAILS),
+   MENU_LABEL(MENU_THUMBNAIL_UPSCALE_THRESHOLD),
    MENU_LABEL(MENU_RGUI_INLINE_THUMBNAILS),
    MENU_LABEL(MENU_RGUI_SWAP_THUMBNAILS),
    MENU_LABEL(MENU_RGUI_THUMBNAIL_DOWNSCALER),
diff --git a/tasks/task_image.c b/tasks/task_image.c
index 48c1944a67..cbe7fe41e9 100644
--- a/tasks/task_image.c
+++ b/tasks/task_image.c
@@ -49,6 +49,7 @@ struct nbio_image_handle
    int processing_final_state;
    unsigned frame_duration;
    size_t size;
+   unsigned upscale_threshold;
    void *handle;
    transfer_cb_t  cb;
    struct texture_image ti;
@@ -226,6 +227,48 @@ static int cb_nbio_image_thumbnail(void *data, size_t len)
    return 0;
 }
 
+static bool upscale_image(
+      unsigned scale_factor,
+      struct texture_image *image_src,
+      struct texture_image *image_dst)
+{
+   uint32_t x_ratio, y_ratio;
+   unsigned x_src, y_src;
+   unsigned x_dst, y_dst;
+
+   /* Sanity check */
+   if ((scale_factor < 1) || !image_src || !image_dst)
+      return false;
+
+   if (!image_src->pixels || (image_src->width < 1) || (image_src->height < 1))
+      return false;
+
+   /* Get output dimensions */
+   image_dst->width = image_src->width * scale_factor;
+   image_dst->height = image_src->height * scale_factor;
+
+   /* Allocate pixel buffer */
+   image_dst->pixels = (uint32_t*)calloc(image_dst->width * image_dst->height, sizeof(uint32_t));
+   if (!image_dst->pixels)
+      return false;
+
+   /* Perform nearest neighbour resampling */
+   x_ratio = ((image_src->width  << 16) / image_dst->width);
+   y_ratio = ((image_src->height << 16) / image_dst->height);
+
+   for (y_dst = 0; y_dst < image_dst->height; y_dst++)
+   {
+      y_src = (y_dst * y_ratio) >> 16;
+      for (x_dst = 0; x_dst < image_dst->width; x_dst++)
+      {
+         x_src = (x_dst * x_ratio) >> 16;
+         image_dst->pixels[(y_dst * image_dst->width) + x_dst] = image_src->pixels[(y_src * image_src->width) + x_src];
+      }
+   }
+
+   return true;
+}
+
 bool task_image_load_handler(retro_task_t *task)
 {
    nbio_handle_t            *nbio  = (nbio_handle_t*)task->state;
@@ -286,6 +329,40 @@ bool task_image_load_handler(retro_task_t *task)
 
       if (img)
       {
+         /* Upscale image, if required */
+         if (image->upscale_threshold > 0)
+         {
+            if (((image->ti.width > 0) && (image->ti.height > 0)) &&
+                ((image->ti.width  < image->upscale_threshold) ||
+                 (image->ti.height < image->upscale_threshold)))
+            {
+               unsigned min_size                  = (image->ti.width < image->ti.height) ?
+                                                      image->ti.width : image->ti.height;
+               float scale_factor                 = (float)image->upscale_threshold /
+                                                      (float)min_size;
+               unsigned scale_factor_int          = (unsigned)scale_factor;
+               struct texture_image img_resampled = {
+                  0,
+                  0,
+                  NULL,
+                  false
+               };
+
+               if (scale_factor - (float)scale_factor_int > 0.0f)
+                  scale_factor_int += 1;
+
+               if (upscale_image(scale_factor_int, &image->ti, &img_resampled))
+               {
+                  image->ti.width  = img_resampled.width;
+                  image->ti.height = img_resampled.height;
+
+                  if (image->ti.pixels)
+                     free(image->ti.pixels);
+                  image->ti.pixels = img_resampled.pixels;
+               }
+            }
+         }
+
          img->width         = image->ti.width;
          img->height        = image->ti.height;
          img->pixels        = image->ti.pixels;
@@ -301,7 +378,7 @@ bool task_image_load_handler(retro_task_t *task)
 }
 
 bool task_push_image_load(const char *fullpath, 
-      bool supports_rgba,
+      bool supports_rgba, unsigned upscale_threshold,
       retro_task_callback_t cb, void *user_data)
 {
    nbio_handle_t             *nbio   = NULL;
@@ -350,6 +427,7 @@ bool task_push_image_load(const char *fullpath,
    image->processing_final_state     = 0;
    image->frame_duration             = 0;
    image->size                       = 0;
+   image->upscale_threshold          = upscale_threshold;
    image->handle                     = NULL;
 
    image->ti.width                   = 0;
diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h
index e68d7fe219..4a1cd58fde 100644
--- a/tasks/tasks_internal.h
+++ b/tasks/tasks_internal.h
@@ -74,7 +74,7 @@ bool task_push_pl_entry_thumbnail_download(
 #endif
 
 bool task_push_image_load(const char *fullpath,
-      bool supports_rgba,
+      bool supports_rgba, unsigned upscale_threshold,
       retro_task_callback_t cb, void *userdata);
 
 #ifdef HAVE_LIBRETRODB