mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-06 08:40:08 +00:00
Reduce memory consumption of the size request cache.
This patch makes contextual height-for-width request caching optional (the contextual cache is not allocated for widgets that report GTK_SIZE_REQUEST_CONSTANT_SIZE).
This commit is contained in:
parent
887142f1f5
commit
82ae7b77ca
@ -34,27 +34,114 @@
|
|||||||
/* looks for a cached size request for this for_size. If not
|
/* looks for a cached size request for this for_size. If not
|
||||||
* found, returns the oldest entry so it can be overwritten
|
* found, returns the oldest entry so it can be overwritten
|
||||||
*
|
*
|
||||||
* Note that this caching code was directly derived from
|
* Note that this caching code was originally derived from
|
||||||
* the Clutter toolkit.
|
* the Clutter toolkit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* This function checks if 'request_needed' flag is present
|
||||||
|
* and resets the cache state if a request is needed for
|
||||||
|
* a given orientation.
|
||||||
|
*/
|
||||||
|
static SizeRequestCache *
|
||||||
|
init_cache (GtkWidget *widget,
|
||||||
|
GtkSizeGroupMode orientation)
|
||||||
|
{
|
||||||
|
GtkSizeRequestMode mode;
|
||||||
|
SizeRequestCache *cache;
|
||||||
|
|
||||||
|
cache = _gtk_widget_peek_request_cache (widget);
|
||||||
|
|
||||||
|
if (orientation == GTK_SIZE_GROUP_HORIZONTAL &&
|
||||||
|
_gtk_widget_get_width_request_needed (widget))
|
||||||
|
{
|
||||||
|
mode = gtk_widget_get_request_mode (widget);
|
||||||
|
|
||||||
|
if (mode == GTK_SIZE_REQUEST_CONSTANT_SIZE)
|
||||||
|
{
|
||||||
|
if (cache->sizes)
|
||||||
|
{
|
||||||
|
g_slice_free (ContextualSizes, cache->sizes);
|
||||||
|
cache->sizes = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!cache->sizes)
|
||||||
|
cache->sizes = g_slice_new0 (ContextualSizes);
|
||||||
|
|
||||||
|
memset (cache->sizes->widths, 0x0, GTK_SIZE_REQUEST_CACHED_SIZES * sizeof (SizeRequest));
|
||||||
|
cache->sizes->cached_widths = 0;
|
||||||
|
cache->sizes->last_cached_width = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->cached_width.minimum_size = -1;
|
||||||
|
cache->cached_width.natural_size = -1;
|
||||||
|
}
|
||||||
|
else if (orientation == GTK_SIZE_GROUP_VERTICAL &&
|
||||||
|
_gtk_widget_get_height_request_needed (widget))
|
||||||
|
{
|
||||||
|
mode = gtk_widget_get_request_mode (widget);
|
||||||
|
|
||||||
|
if (mode == GTK_SIZE_REQUEST_CONSTANT_SIZE)
|
||||||
|
{
|
||||||
|
if (cache->sizes)
|
||||||
|
{
|
||||||
|
g_slice_free (ContextualSizes, cache->sizes);
|
||||||
|
cache->sizes = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!cache->sizes)
|
||||||
|
cache->sizes = g_slice_new0 (ContextualSizes);
|
||||||
|
|
||||||
|
memset (cache->sizes->heights, 0x0, GTK_SIZE_REQUEST_CACHED_SIZES * sizeof (SizeRequest));
|
||||||
|
cache->sizes->cached_heights = 0;
|
||||||
|
cache->sizes->last_cached_height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->cached_height.minimum_size = -1;
|
||||||
|
cache->cached_height.natural_size = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
get_cached_size (SizeRequestCache *cache,
|
get_cached_size (GtkWidget *widget,
|
||||||
GtkSizeGroupMode orientation,
|
GtkSizeGroupMode orientation,
|
||||||
gint for_size,
|
gint for_size,
|
||||||
SizeRequest **result)
|
CachedSize **result)
|
||||||
{
|
{
|
||||||
guint i, n_sizes;
|
SizeRequestCache *cache;
|
||||||
SizeRequest *cached_sizes;
|
SizeRequest *cached_sizes;
|
||||||
|
guint i, n_sizes;
|
||||||
|
|
||||||
|
cache = init_cache (widget, orientation);
|
||||||
|
|
||||||
|
if (for_size < 0)
|
||||||
|
{
|
||||||
|
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
|
||||||
|
*result = &cache->cached_width;
|
||||||
|
else
|
||||||
|
*result = &cache->cached_height;
|
||||||
|
|
||||||
|
if ((*result)->minimum_size < 0)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
|
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
|
||||||
{
|
{
|
||||||
cached_sizes = cache->widths;
|
cached_sizes = cache->sizes->widths;
|
||||||
n_sizes = cache->cached_widths;
|
n_sizes = cache->sizes->cached_widths;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cached_sizes = cache->heights;
|
cached_sizes = cache->sizes->heights;
|
||||||
n_sizes = cache->cached_widths;
|
n_sizes = cache->sizes->cached_widths;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search for an already cached size */
|
/* Search for an already cached size */
|
||||||
@ -62,7 +149,7 @@ get_cached_size (SizeRequestCache *cache,
|
|||||||
{
|
{
|
||||||
if (cached_sizes[i].for_size == for_size)
|
if (cached_sizes[i].for_size == for_size)
|
||||||
{
|
{
|
||||||
*result = &cached_sizes[i];
|
*result = &cached_sizes[i].cached_size;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,33 +159,35 @@ get_cached_size (SizeRequestCache *cache,
|
|||||||
* and increment the last_cached_width/height right away */
|
* and increment the last_cached_width/height right away */
|
||||||
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
|
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
|
||||||
{
|
{
|
||||||
if (cache->cached_widths < GTK_SIZE_REQUEST_CACHED_SIZES)
|
if (cache->sizes->cached_widths < GTK_SIZE_REQUEST_CACHED_SIZES)
|
||||||
{
|
{
|
||||||
cache->cached_widths++;
|
cache->sizes->cached_widths++;
|
||||||
cache->last_cached_width = cache->cached_widths - 1;
|
cache->sizes->last_cached_width = cache->sizes->cached_widths - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (++cache->last_cached_width == GTK_SIZE_REQUEST_CACHED_SIZES)
|
if (++cache->sizes->last_cached_width == GTK_SIZE_REQUEST_CACHED_SIZES)
|
||||||
cache->last_cached_width = 0;
|
cache->sizes->last_cached_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = &cache->widths[cache->last_cached_width];
|
cache->sizes->widths[cache->sizes->last_cached_width].for_size = for_size;
|
||||||
|
*result = &cache->sizes->widths[cache->sizes->last_cached_width].cached_size;
|
||||||
}
|
}
|
||||||
else /* GTK_SIZE_GROUP_VERTICAL */
|
else /* GTK_SIZE_GROUP_VERTICAL */
|
||||||
{
|
{
|
||||||
if (cache->cached_heights < GTK_SIZE_REQUEST_CACHED_SIZES)
|
if (cache->sizes->cached_heights < GTK_SIZE_REQUEST_CACHED_SIZES)
|
||||||
{
|
{
|
||||||
cache->cached_heights++;
|
cache->sizes->cached_heights++;
|
||||||
cache->last_cached_height = cache->cached_heights - 1;
|
cache->sizes->last_cached_height = cache->sizes->cached_heights - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (++cache->last_cached_height == GTK_SIZE_REQUEST_CACHED_SIZES)
|
if (++cache->sizes->last_cached_height == GTK_SIZE_REQUEST_CACHED_SIZES)
|
||||||
cache->last_cached_height = 0;
|
cache->sizes->last_cached_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = &cache->heights[cache->last_cached_height];
|
cache->sizes->heights[cache->sizes->last_cached_height].for_size = for_size;
|
||||||
|
*result = &cache->sizes->heights[cache->sizes->last_cached_height].cached_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -168,39 +257,11 @@ compute_size_for_orientation (GtkWidget *widget,
|
|||||||
gint *minimum_size,
|
gint *minimum_size,
|
||||||
gint *natural_size)
|
gint *natural_size)
|
||||||
{
|
{
|
||||||
SizeRequestCache *cache;
|
CachedSize *cached_size;
|
||||||
SizeRequest *cached_size;
|
|
||||||
gboolean found_in_cache = FALSE;
|
gboolean found_in_cache = FALSE;
|
||||||
int adjusted_min, adjusted_natural;
|
gint adjusted_min, adjusted_natural;
|
||||||
|
|
||||||
cache = _gtk_widget_peek_request_cache (widget);
|
found_in_cache = get_cached_size (widget, orientation, for_size, &cached_size);
|
||||||
|
|
||||||
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
|
|
||||||
{
|
|
||||||
cached_size = &cache->widths[0];
|
|
||||||
|
|
||||||
if (!_gtk_widget_get_width_request_needed (widget))
|
|
||||||
found_in_cache = get_cached_size (cache, orientation, for_size, &cached_size);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset (cache->widths, 0, GTK_SIZE_REQUEST_CACHED_SIZES * sizeof (SizeRequest));
|
|
||||||
cache->cached_widths = 1;
|
|
||||||
cache->last_cached_width = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cached_size = &cache->heights[0];
|
|
||||||
|
|
||||||
if (!_gtk_widget_get_height_request_needed (widget))
|
|
||||||
found_in_cache = get_cached_size (cache, orientation, for_size, &cached_size);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset (cache->heights, 0, GTK_SIZE_REQUEST_CACHED_SIZES * sizeof (SizeRequest));
|
|
||||||
cache->cached_heights = 1;
|
|
||||||
cache->last_cached_height = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found_in_cache)
|
if (!found_in_cache)
|
||||||
{
|
{
|
||||||
@ -282,7 +343,6 @@ compute_size_for_orientation (GtkWidget *widget,
|
|||||||
|
|
||||||
cached_size->minimum_size = min_size;
|
cached_size->minimum_size = min_size;
|
||||||
cached_size->natural_size = nat_size;
|
cached_size->natural_size = nat_size;
|
||||||
cached_size->for_size = for_size;
|
|
||||||
|
|
||||||
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
|
if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
|
||||||
_gtk_widget_set_width_request_needed (widget, FALSE);
|
_gtk_widget_set_width_request_needed (widget, FALSE);
|
||||||
|
@ -10669,6 +10669,9 @@ gtk_widget_finalize (GObject *object)
|
|||||||
if (priv->context)
|
if (priv->context)
|
||||||
g_object_unref (priv->context);
|
g_object_unref (priv->context);
|
||||||
|
|
||||||
|
if (priv->requests.sizes)
|
||||||
|
g_slice_free (ContextualSizes, priv->requests.sizes);
|
||||||
|
|
||||||
if (g_object_is_floating (object))
|
if (g_object_is_floating (object))
|
||||||
g_warning ("A floating object was finalized. This means that someone\n"
|
g_warning ("A floating object was finalized. This means that someone\n"
|
||||||
"called g_object_unref() on an object that had only a floating\n"
|
"called g_object_unref() on an object that had only a floating\n"
|
||||||
|
@ -34,15 +34,18 @@ G_BEGIN_DECLS
|
|||||||
* (Note this define is limited by the bitfield sizes
|
* (Note this define is limited by the bitfield sizes
|
||||||
* defined on the SizeRequestCache structure).
|
* defined on the SizeRequestCache structure).
|
||||||
*/
|
*/
|
||||||
#define GTK_SIZE_REQUEST_CACHED_SIZES (3)
|
#define GTK_SIZE_REQUEST_CACHED_SIZES (2)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gint minimum_size;
|
||||||
|
gint natural_size;
|
||||||
|
} CachedSize;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/* the size this request is for */
|
/* the size this request is for */
|
||||||
gint for_size;
|
gint for_size;
|
||||||
|
CachedSize cached_size;
|
||||||
gint minimum_size;
|
|
||||||
gint natural_size;
|
|
||||||
} SizeRequest;
|
} SizeRequest;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -53,6 +56,13 @@ typedef struct {
|
|||||||
guint cached_heights : 2;
|
guint cached_heights : 2;
|
||||||
guint last_cached_width : 2;
|
guint last_cached_width : 2;
|
||||||
guint last_cached_height : 2;
|
guint last_cached_height : 2;
|
||||||
|
} ContextualSizes;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ContextualSizes *sizes;
|
||||||
|
|
||||||
|
CachedSize cached_width;
|
||||||
|
CachedSize cached_height;
|
||||||
} SizeRequestCache;
|
} SizeRequestCache;
|
||||||
|
|
||||||
void _gtk_widget_set_visible_flag (GtkWidget *widget,
|
void _gtk_widget_set_visible_flag (GtkWidget *widget,
|
||||||
|
Loading…
Reference in New Issue
Block a user