[gnome-shell] st-texture-cache: Separate 'scale' to 'paint_scale' and 'resource_scale'



commit 420697693b2f659fd7faccdc5c675f25494f00e0
Author: Marco Trevisan (Treviño) <mail 3v1n0 net>
Date:   Thu May 11 06:25:00 2017 +0200

    st-texture-cache: Separate 'scale' to 'paint_scale' and 'resource_scale'
    
    Instead of just passing a scale when getting a cached icon, pass both a
    'paint_scale', the scale of which the icon will be painted on the
    stage, and a 'resource_scale', the scale of the resource used for
    painting.
    
    In effect, the texture size will use the scale 'paint_scale * resource_scale'
    in a ceiled value while the size of the actor will use 'paint_scale' when
    determining the size.
    this would load a bigger texture, but the downscaling would keep the visual
    quality.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
    https://bugzilla.gnome.org/show_bug.cgi?id=765011

 js/gdm/loginDialog.js          |   3 +-
 src/st/st-icon.c               |   6 ++-
 src/st/st-texture-cache.c      | 112 +++++++++++++++++++++++++++--------------
 src/st/st-texture-cache.h      |  15 ++++--
 src/st/st-theme-node-drawing.c |  37 ++++++++++----
 5 files changed, 117 insertions(+), 56 deletions(-)
---
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index 8ea1a86a2..bf7577c36 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -782,7 +782,8 @@ var LoginDialog = GObject.registerClass({
             let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
             this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
                                                                        -1, _LOGO_ICON_HEIGHT,
-                                                                       scaleFactor));
+                                                                       scaleFactor,
+                                                                       1));
         }
     }
 
diff --git a/src/st/st-icon.c b/src/st/st-icon.c
index b9c92c86c..9242d6b4e 100644
--- a/src/st/st-icon.c
+++ b/src/st/st-icon.c
@@ -393,14 +393,16 @@ st_icon_update (StIcon *icon)
                                                          theme_node,
                                                          priv->gicon,
                                                          priv->icon_size,
-                                                         scale);
+                                                         scale,
+                                                         1);
 
   if (priv->pending_texture == NULL && priv->fallback_gicon != NULL)
     priv->pending_texture = st_texture_cache_load_gicon (cache,
                                                          theme_node,
                                                          priv->fallback_gicon,
                                                          priv->icon_size,
-                                                         scale);
+                                                         scale,
+                                                         1);
 
   if (priv->pending_texture)
     {
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
index 967ad9e2e..0075845f8 100644
--- a/src/st/st-texture-cache.c
+++ b/src/st/st-texture-cache.c
@@ -25,6 +25,7 @@
 #include "st-private.h"
 #include "st-settings.h"
 #include <gtk/gtk.h>
+#include <math.h>
 #include <string.h>
 #include <glib.h>
 
@@ -284,7 +285,8 @@ typedef struct {
 
   guint width;
   guint height;
-  guint scale;
+  guint paint_scale;
+  gfloat resource_scale;
   GSList *actors;
 
   GtkIconInfo *icon_info;
@@ -430,7 +432,8 @@ static GdkPixbuf *
 impl_load_pixbuf_file (GFile          *file,
                        int             available_width,
                        int             available_height,
-                       int             scale,
+                       int             paint_scale,
+                       float           resource_scale,
                        GError        **error)
 {
   GdkPixbuf *pixbuf = NULL;
@@ -439,6 +442,7 @@ impl_load_pixbuf_file (GFile          *file,
 
   if (g_file_load_contents (file, NULL, &contents, &size, NULL, error))
     {
+      int scale = ceilf (paint_scale * resource_scale);
       pixbuf = impl_load_pixbuf_data ((const guchar *) contents, size,
                                       available_width, available_height,
                                       scale,
@@ -463,7 +467,9 @@ load_pixbuf_thread (GTask        *result,
   g_assert (data != NULL);
   g_assert (data->file != NULL);
 
-  pixbuf = impl_load_pixbuf_file (data->file, data->width, data->height, data->scale, &error);
+  pixbuf = impl_load_pixbuf_file (data->file, data->width, data->height,
+                                  data->paint_scale, data->resource_scale,
+                                  &error);
 
   if (error != NULL)
     g_task_return_error (result, error);
@@ -869,7 +875,8 @@ ensure_request (StTextureCache        *cache,
  *                            if the icon must not be recolored
  * @icon: the #GIcon to load
  * @size: Size of themed
- * @scale: Scale factor of display
+ * @paint_scale: Scale factor of display
+ * @resource_scale: Resource scale factor
  *
  * This method returns a new #ClutterActor for a given #GIcon. If the
  * icon isn't loaded already, the texture will be filled
@@ -882,12 +889,15 @@ st_texture_cache_load_gicon (StTextureCache    *cache,
                              StThemeNode       *theme_node,
                              GIcon             *icon,
                              gint               size,
-                             gint               scale)
+                             gint               paint_scale,
+                             gfloat             resource_scale)
 {
   AsyncTextureLoadData *request;
   ClutterActor *actor;
+  gint scale;
   char *gicon_string;
   char *key;
+  float actor_size;
   GtkIconTheme *theme;
   GtkIconInfo *info;
   StTextureCachePolicy policy;
@@ -916,7 +926,10 @@ st_texture_cache_load_gicon (StTextureCache    *cache,
   else
     lookup_flags |= GTK_ICON_LOOKUP_DIR_LTR;
 
-  info = gtk_icon_theme_lookup_by_gicon_for_scale (theme, icon, size, scale, lookup_flags);
+  scale = ceilf (paint_scale * resource_scale);
+  info = gtk_icon_theme_lookup_by_gicon_for_scale (theme, icon,
+                                                   size, scale,
+                                                   lookup_flags);
   if (info == NULL)
     return NULL;
 
@@ -945,8 +958,8 @@ st_texture_cache_load_gicon (StTextureCache    *cache,
   g_free (gicon_string);
 
   actor = create_invisible_actor ();
-  clutter_actor_set_size (actor, size * scale, size * scale);
-
+  actor_size = size * paint_scale;
+  clutter_actor_set_size (actor, actor_size, actor_size);
   if (ensure_request (cache, key, policy, &request, actor))
     {
       /* If there's an outstanding request, we've just added ourselves to it */
@@ -964,7 +977,8 @@ st_texture_cache_load_gicon (StTextureCache    *cache,
       request->colors = colors ? st_icon_colors_ref (colors) : NULL;
       request->icon_info = info;
       request->width = request->height = size;
-      request->scale = scale;
+      request->paint_scale = paint_scale;
+      request->resource_scale = resource_scale;
 
       load_texture_async (cache, request);
     }
@@ -1041,7 +1055,8 @@ ensure_monitor_for_file (StTextureCache *cache,
 typedef struct {
   GFile *gfile;
   gint   grid_width, grid_height;
-  gint   scale_factor;
+  gint   paint_scale;
+  gfloat resource_scale;
   ClutterActor *actor;
   GFunc load_callback;
   gpointer load_callback_data;
@@ -1097,9 +1112,9 @@ on_loader_size_prepared (GdkPixbufLoader *loader,
                          gpointer user_data)
 {
   AsyncImageData *data = user_data;
-  gdk_pixbuf_loader_set_size (loader,
-                              width * data->scale_factor,
-                              height * data->scale_factor);
+  int scale = ceilf (data->paint_scale * data->resource_scale);
+
+  gdk_pixbuf_loader_set_size (loader, width * scale, height * scale);
 }
 
 static void
@@ -1112,6 +1127,7 @@ load_sliced_image (GTask        *result,
   GList *res = NULL;
   GdkPixbuf *pix;
   gint width, height, y, x;
+  gint scale_factor;
   GdkPixbufLoader *loader;
   GError *error = NULL;
   gchar *buffer = NULL;
@@ -1143,13 +1159,14 @@ load_sliced_image (GTask        *result,
   pix = gdk_pixbuf_loader_get_pixbuf (loader);
   width = gdk_pixbuf_get_width (pix);
   height = gdk_pixbuf_get_height (pix);
-  for (y = 0; y < height; y += data->grid_height * data->scale_factor)
+  scale_factor = ceilf (data->paint_scale * data->resource_scale);
+  for (y = 0; y < height; y += data->grid_height * scale_factor)
     {
-      for (x = 0; x < width; x += data->grid_width * data->scale_factor)
+      for (x = 0; x < width; x += data->grid_width * scale_factor)
         {
           GdkPixbuf *pixbuf = gdk_pixbuf_new_subpixbuf (pix, x, y,
-                                                        data->grid_width * data->scale_factor,
-                                                        data->grid_height * data->scale_factor);
+                                                        data->grid_width * scale_factor,
+                                                        data->grid_height * scale_factor);
           g_assert (pixbuf != NULL);
           res = g_list_append (res, pixbuf);
         }
@@ -1170,13 +1187,13 @@ load_sliced_image (GTask        *result,
  * @file: A #GFile
  * @grid_width: Width in pixels
  * @grid_height: Height in pixels
- * @scale: Scale factor of the display
+ * @paint_scale: Scale factor of the display
  * @load_callback: (scope async) (nullable): Function called when the image is loaded, or %NULL
  * @user_data: Data to pass to the load callback
  *
  * This function reads a single image file which contains multiple images internally.
  * The image file will be divided using @grid_width and @grid_height;
- * note that the dimensions of the image loaded from @path 
+ * note that the dimensions of the image loaded from @path
  * should be a multiple of the specified grid dimensions.
  *
  * Returns: (transfer none): A new #ClutterActor
@@ -1186,7 +1203,8 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
                                     GFile          *file,
                                     gint            grid_width,
                                     gint            grid_height,
-                                    gint            scale,
+                                    gint            paint_scale,
+                                    gfloat          resource_scale,
                                     GFunc           load_callback,
                                     gpointer        user_data)
 {
@@ -1194,10 +1212,15 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
   GTask *result;
   ClutterActor *actor = clutter_actor_new ();
 
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+  g_assert (paint_scale > 0);
+  g_assert (resource_scale > 0);
+
   data = g_new0 (AsyncImageData, 1);
   data->grid_width = grid_width;
   data->grid_height = grid_height;
-  data->scale_factor = scale;
+  data->paint_scale = paint_scale;
+  data->resource_scale = resource_scale;
   data->gfile = g_object_ref (file);
   data->actor = actor;
   data->load_callback = load_callback;
@@ -1219,7 +1242,8 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
  * @file: a #GFile of the image file from which to create a pixbuf
  * @available_width: available width for the image, can be -1 if not limited
  * @available_height: available height for the image, can be -1 if not limited
- * @scale: scale factor of the display
+ * @paint_scale: scale factor of the display
+ * @resource_scale: Resource scale factor
  *
  * Asynchronously load an image.   Initially, the returned texture will have a natural
  * size of zero.  At some later point, either the image will be loaded successfully
@@ -1232,14 +1256,17 @@ st_texture_cache_load_file_async (StTextureCache *cache,
                                   GFile          *file,
                                   int             available_width,
                                   int             available_height,
-                                  int             scale)
+                                  int             paint_scale,
+                                  gfloat          resource_scale)
 {
   ClutterActor *actor;
   AsyncTextureLoadData *request;
   StTextureCachePolicy policy;
   gchar *key;
+  int scale;
 
-  key = g_strdup_printf (CACHE_PREFIX_FILE "%u", g_file_hash (file));
+  scale = ceilf (paint_scale * resource_scale);
+  key = g_strdup_printf (CACHE_PREFIX_FILE "%u%d", g_file_hash (file), scale);
 
   policy = ST_TEXTURE_CACHE_POLICY_NONE; /* XXX */
 
@@ -1261,7 +1288,8 @@ st_texture_cache_load_file_async (StTextureCache *cache,
       request->policy = policy;
       request->width = available_width;
       request->height = available_height;
-      request->scale = scale;
+      request->paint_scale = paint_scale;
+      request->resource_scale = resource_scale;
 
       load_texture_async (cache, request);
     }
@@ -1277,7 +1305,8 @@ st_texture_cache_load_file_sync_to_cogl_texture (StTextureCache *cache,
                                                  GFile          *file,
                                                  int             available_width,
                                                  int             available_height,
-                                                 int             scale,
+                                                 int             paint_scale,
+                                                 gfloat          resource_scale,
                                                  GError         **error)
 {
   ClutterContent *image;
@@ -1285,14 +1314,15 @@ st_texture_cache_load_file_sync_to_cogl_texture (StTextureCache *cache,
   GdkPixbuf *pixbuf;
   char *key;
 
-  key = g_strdup_printf (CACHE_PREFIX_FILE "%u", g_file_hash (file));
+  key = g_strdup_printf (CACHE_PREFIX_FILE "%u%f", g_file_hash (file), resource_scale);
 
   texdata = NULL;
   image = g_hash_table_lookup (cache->priv->keyed_cache, key);
 
   if (image == NULL)
     {
-      pixbuf = impl_load_pixbuf_file (file, available_width, available_height, scale, error);
+      pixbuf = impl_load_pixbuf_file (file, available_width, available_height,
+                                      paint_scale, resource_scale, error);
       if (!pixbuf)
         goto out;
 
@@ -1325,20 +1355,22 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache        *cache,
                                                   GFile                 *file,
                                                   int                    available_width,
                                                   int                    available_height,
-                                                  int                    scale,
+                                                  int                    paint_scale,
+                                                  gfloat                 resource_scale,
                                                   GError               **error)
 {
   cairo_surface_t *surface;
   GdkPixbuf *pixbuf;
   char *key;
 
-  key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", g_file_hash (file));
+  key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u%f", g_file_hash (file), resource_scale);
 
   surface = g_hash_table_lookup (cache->priv->keyed_surface_cache, key);
 
   if (surface == NULL)
     {
-      pixbuf = impl_load_pixbuf_file (file, available_width, available_height, scale, error);
+      pixbuf = impl_load_pixbuf_file (file, available_width, available_height,
+                                      paint_scale, resource_scale, error);
       if (!pixbuf)
         goto out;
 
@@ -1366,7 +1398,8 @@ out:
  * st_texture_cache_load_file_to_cogl_texture: (skip)
  * @cache: A #StTextureCache
  * @file: A #GFile in supported image format
- * @scale: Scale factor of the display
+ * @paint_scale: Scale factor of the display
+ * @resource_scale: Resource scale factor
  *
  * This function synchronously loads the given file path
  * into a COGL texture.  On error, a warning is emitted
@@ -1377,13 +1410,15 @@ out:
 CoglTexture *
 st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
                                             GFile          *file,
-                                            gint            scale)
+                                            gint            paint_scale,
+                                            gfloat          resource_scale)
 {
   CoglTexture *texture;
   GError *error = NULL;
 
   texture = st_texture_cache_load_file_sync_to_cogl_texture (cache, ST_TEXTURE_CACHE_POLICY_FOREVER,
-                                                             file, -1, -1, scale, &error);
+                                                             file, -1, -1, paint_scale, resource_scale,
+                                                             &error);
 
   if (texture == NULL)
     {
@@ -1400,7 +1435,8 @@ st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
  * st_texture_cache_load_file_to_cairo_surface:
  * @cache: A #StTextureCache
  * @file: A #GFile in supported image format
- * @scale: Scale factor of the display
+ * @paint_scale: Scale factor of the display
+ * @resource_scale: Resource scale factor
  *
  * This function synchronously loads the given file path
  * into a cairo surface.  On error, a warning is emitted
@@ -1411,13 +1447,15 @@ st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
 cairo_surface_t *
 st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
                                              GFile          *file,
-                                             gint            scale)
+                                             gint            paint_scale,
+                                             gfloat          resource_scale)
 {
   cairo_surface_t *surface;
   GError *error = NULL;
 
   surface = st_texture_cache_load_file_sync_to_cairo_surface (cache, ST_TEXTURE_CACHE_POLICY_FOREVER,
-                                                              file, -1, -1, scale, &error);
+                                                              file, -1, -1, paint_scale, resource_scale,
+                                                              &error);
 
   if (surface == NULL)
     {
diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h
index 26f9c30ac..0e0202c50 100644
--- a/src/st/st-texture-cache.h
+++ b/src/st/st-texture-cache.h
@@ -58,7 +58,8 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
                                     GFile          *file,
                                     gint            grid_width,
                                     gint            grid_height,
-                                    gint            scale,
+                                    gint            paint_scale,
+                                    gfloat          resource_scale,
                                     GFunc           load_callback,
                                     gpointer        user_data);
 
@@ -70,21 +71,25 @@ ClutterActor *st_texture_cache_load_gicon (StTextureCache *cache,
                                            StThemeNode    *theme_node,
                                            GIcon          *icon,
                                            gint            size,
-                                           gint            scale);
+                                           gint            paint_scale,
+                                           gfloat          resource_scale);
 
 ClutterActor *st_texture_cache_load_file_async (StTextureCache    *cache,
                                                 GFile             *file,
                                                 int                available_width,
                                                 int                available_height,
-                                                int                scale);
+                                                int                paint_scale,
+                                                gfloat             resource_scale);
 
 CoglTexture     *st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
                                                              GFile          *file,
-                                                             gint            scale);
+                                                             gint            paint_scale,
+                                                             gfloat          resource_scale);
 
 cairo_surface_t *st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
                                                               GFile          *file,
-                                                              gint            scale);
+                                                              gint            paint_scale,
+                                                              gfloat          resource_scale);
 
 /**
  * StTextureCacheLoader: (skip)
diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
index 3aaba3424..9877afdae 100644
--- a/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -650,7 +650,9 @@ create_cairo_pattern_of_background_image (StThemeNode *node,
   texture_cache = st_texture_cache_get_default ();
 
   g_object_get (node->context, "scale-factor", &scale_factor, NULL);
-  surface = st_texture_cache_load_file_to_cairo_surface (texture_cache, file, scale_factor);
+  surface = st_texture_cache_load_file_to_cairo_surface (texture_cache, file,
+                                                         scale_factor,
+                                                         resource_scale);
 
   if (surface == NULL)
     return NULL;
@@ -667,10 +669,18 @@ create_cairo_pattern_of_background_image (StThemeNode *node,
 
   cairo_matrix_init_identity (&matrix);
 
+  if (resource_scale != 1.0)
+    {
+      background_image_width /= resource_scale;
+      background_image_height /= resource_scale;
+
+      cairo_matrix_scale (&matrix, resource_scale, resource_scale);
+    }
+
   get_background_scale (node,
                         width, height,
                         background_image_width, background_image_height,
-                        resource_scale, &scale_w, &scale_h);
+                        &scale_w, &scale_h);
 
   if ((scale_w != 1) || (scale_h != 1))
     cairo_matrix_scale (&matrix, 1.0/scale_w, 1.0/scale_h);
@@ -1323,7 +1333,8 @@ st_theme_node_prerender_background (StThemeNode *node,
   if (interior_path != NULL)
     cairo_path_destroy (interior_path);
 
-  texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, texture_width,
+  texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx,
+                                                         texture_width,
                                                          texture_height,
                                                          CLUTTER_CAIRO_FORMAT_ARGB32,
                                                          rowstride,
@@ -1356,7 +1367,8 @@ st_theme_node_invalidate_border_image (StThemeNode *node)
 }
 
 static gboolean
-st_theme_node_load_border_image (StThemeNode *node)
+st_theme_node_load_border_image (StThemeNode *node,
+                                 gfloat       resource_scale)
 {
   if (node->border_slices_texture == NULL)
     {
@@ -1373,7 +1385,8 @@ st_theme_node_load_border_image (StThemeNode *node)
       g_object_get (node->context, "scale-factor", &scale_factor, NULL);
 
       node->border_slices_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default 
(),
-                                                                                file, scale_factor);
+                                                                                file, scale_factor,
+                                                                                resource_scale);
       if (node->border_slices_texture == NULL)
         goto out;
 
@@ -1393,7 +1406,8 @@ st_theme_node_invalidate_background_image (StThemeNode *node)
 }
 
 static gboolean
-st_theme_node_load_background_image (StThemeNode *node)
+st_theme_node_load_background_image (StThemeNode *node,
+                                     gfloat       resource_scale)
 {
   if (node->background_texture == NULL)
     {
@@ -1409,7 +1423,8 @@ st_theme_node_load_background_image (StThemeNode *node)
 
       background_image_shadow_spec = st_theme_node_get_background_image_shadow (node);
       node->background_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default (),
-                                                                             background_image, scale_factor);
+                                                                             background_image, scale_factor,
+                                                                             resource_scale);
       if (node->background_texture == NULL)
         goto out;
 
@@ -1560,7 +1575,7 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
 
   if (box_shadow_spec && !has_inset_box_shadow)
     {
-      if (st_theme_node_load_border_image (node))
+      if (st_theme_node_load_border_image (node, resource_scale))
         state->box_shadow_pipeline = _st_create_shadow_pipeline (box_shadow_spec,
                                                                  node->border_slices_texture,
                                                                  state->resource_scale);
@@ -1634,7 +1649,7 @@ st_theme_node_update_resources (StThemeNodePaintState *state,
       for (corner_id = 0; corner_id < 4; corner_id++)
         if (state->corner_material[corner_id] == NULL)
           state->corner_material[corner_id] =
-            st_theme_node_lookup_corner (node, width, resource_scale, height, corner_id);
+            st_theme_node_lookup_corner (node, width, height, resource_scale, corner_id);
     }
 
   if (had_box_shadow)
@@ -2635,7 +2650,7 @@ st_theme_node_paint (StThemeNode           *node,
     }
 
   if (state->prerendered_pipeline != NULL ||
-      st_theme_node_load_border_image (node))
+      st_theme_node_load_border_image (node, resource_scale))
     {
       if (state->prerendered_pipeline != NULL)
         {
@@ -2663,7 +2678,7 @@ st_theme_node_paint (StThemeNode           *node,
   st_theme_node_paint_outline (node, framebuffer, box, paint_opacity);
 
   if (state->prerendered_pipeline == NULL &&
-      st_theme_node_load_background_image (node))
+      st_theme_node_load_background_image (node, resource_scale))
     {
       ClutterActorBox background_box;
       ClutterActorBox texture_coords;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]