diff --git a/gsk/gpu/gskgldevice.c b/gsk/gpu/gskgldevice.c index 42813bb56c..e67b30618a 100644 --- a/gsk/gpu/gskgldevice.c +++ b/gsk/gpu/gskgldevice.c @@ -260,7 +260,10 @@ gsk_gl_device_get_for_display (GdkDisplay *display, gdk_gl_context_make_current (context); glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size); - gsk_gpu_device_setup (GSK_GPU_DEVICE (self), display, max_texture_size); + gsk_gpu_device_setup (GSK_GPU_DEVICE (self), + display, + max_texture_size, + GSK_GPU_DEVICE_DEFAULT_TILE_SIZE); self->version_string = gdk_gl_context_get_glsl_version_string (context); self->api = gdk_gl_context_get_api (context); diff --git a/gsk/gpu/gskgpucache.c b/gsk/gpu/gskgpucache.c index 4b1995ae0b..3e65f44fa3 100644 --- a/gsk/gpu/gskgpucache.c +++ b/gsk/gpu/gskgpucache.c @@ -32,6 +32,7 @@ typedef struct _GskGpuCachedClass GskGpuCachedClass; typedef struct _GskGpuCachedAtlas GskGpuCachedAtlas; typedef struct _GskGpuCachedGlyph GskGpuCachedGlyph; typedef struct _GskGpuCachedTexture GskGpuCachedTexture; +typedef struct _GskGpuCachedTile GskGpuCachedTile; struct _GskGpuCache { @@ -44,6 +45,7 @@ struct _GskGpuCache GHashTable *texture_cache; GHashTable *ccs_texture_caches[GDK_COLOR_STATE_N_IDS]; + GHashTable *tile_cache; GHashTable *glyph_cache; GskGpuCachedAtlas *current_atlas; @@ -398,6 +400,185 @@ gsk_gpu_cached_texture_new (GskGpuCache *cache, return self; } +/* }}} */ +/* {{{ CachedTile */ + +struct _GskGpuCachedTile +{ + GskGpuCached parent; + + GdkTexture *texture; + gsize tile_id; + + /* atomic */ int use_count; /* We count the use by the cache (via the linked + * list) and by the texture (via weak ref) + */ + + gsize *dead_pixels_counter; + + GskGpuImage *image; + GdkColorState *color_state; +}; + +static void +gsk_gpu_cached_tile_free (GskGpuCache *cache, + GskGpuCached *cached) +{ + GskGpuCachedTile *self = (GskGpuCachedTile *) cached; + gpointer key, value; + + g_clear_object (&self->image); + g_clear_pointer (&self->color_state, gdk_color_state_unref); + + if (g_hash_table_steal_extended (cache->tile_cache, self, &key, &value)) + { + /* If the texture has been reused already, we put the entry back */ + if ((GskGpuCached *) value != cached) + g_hash_table_insert (cache->tile_cache, key, value); + } + + /* If the cached item itself is still in use by the texture, we leave + * it to the weak ref or render data to free it. + */ + if (g_atomic_int_dec_and_test (&self->use_count)) + { + g_free (self); + return; + } +} + +static inline gboolean +gsk_gpu_cached_tile_is_invalid (GskGpuCachedTile *self) +{ + /* If the use count is less than 2, the orignal texture has died, + * and the memory may have been reused for a new texture, so we + * can't hand out the image that is for the original texture. + */ + return g_atomic_int_get (&self->use_count) < 2; +} + +static gboolean +gsk_gpu_cached_tile_should_collect (GskGpuCache *cache, + GskGpuCached *cached, + gint64 cache_timeout, + gint64 timestamp) +{ + GskGpuCachedTile *self = (GskGpuCachedTile *) cached; + + return gsk_gpu_cached_is_old (cache, cached, cache_timeout, timestamp) || + gsk_gpu_cached_tile_is_invalid (self); +} + +static const GskGpuCachedClass GSK_GPU_CACHED_TILE_CLASS = +{ + sizeof (GskGpuCachedTile), + gsk_gpu_cached_tile_free, + gsk_gpu_cached_tile_should_collect +}; + +/* Note: this function can run in an arbitrary thread, so it can + * only access things atomically + */ +static void +gsk_gpu_cached_tile_destroy_cb (gpointer data) +{ + GskGpuCachedTile *self = data; + + if (!gsk_gpu_cached_tile_is_invalid (self)) + g_atomic_pointer_add (self->dead_pixels_counter, ((GskGpuCached *) self)->pixels); + + if (g_atomic_int_dec_and_test (&self->use_count)) + g_free (self); +} + +static guint +gsk_gpu_cached_tile_hash (gconstpointer data) +{ + const GskGpuCachedTile *self = data; + + return g_direct_hash (self->texture) ^ self->tile_id; +} + +static gboolean +gsk_gpu_cached_tile_equal (gconstpointer data_a, + gconstpointer data_b) +{ + const GskGpuCachedTile *a = data_a; + const GskGpuCachedTile *b = data_b; + + return a->texture == b->texture && + a->tile_id == b->tile_id; +} + +static GskGpuCachedTile * +gsk_gpu_cached_tile_new (GskGpuCache *cache, + GdkTexture *texture, + guint tile_id, + GskGpuImage *image, + GdkColorState *color_state) +{ + GskGpuCachedTile *self; + + self = gsk_gpu_cached_new (cache, &GSK_GPU_CACHED_TILE_CLASS, NULL); + self->texture = texture; + self->tile_id = tile_id; + self->image = g_object_ref (image); + self->color_state = gdk_color_state_ref (color_state); + ((GskGpuCached *)self)->pixels = gsk_gpu_image_get_width (image) * gsk_gpu_image_get_height (image); + self->dead_pixels_counter = &cache->dead_texture_pixels; + self->use_count = 2; + + g_object_weak_ref (G_OBJECT (texture), (GWeakNotify) gsk_gpu_cached_tile_destroy_cb, self); + if (cache->tile_cache == NULL) + cache->tile_cache = g_hash_table_new (gsk_gpu_cached_tile_hash, + gsk_gpu_cached_tile_equal); + g_hash_table_add (cache->tile_cache, self); + + return self; +} + +GskGpuImage * +gsk_gpu_cache_lookup_tile (GskGpuCache *self, + GdkTexture *texture, + gsize tile_id, + gint64 timestamp, + GdkColorState **out_color_state) +{ + GskGpuCachedTile *tile; + GskGpuCachedTile lookup = { + .texture = texture, + .tile_id = tile_id + }; + + if (self->tile_cache == NULL) + return NULL; + + tile = g_hash_table_lookup (self->tile_cache, &lookup); + if (tile == NULL) + return NULL; + + gsk_gpu_cached_use (self, (GskGpuCached *) tile, timestamp); + + *out_color_state = tile->color_state; + + return g_object_ref (tile->image); +} + +void +gsk_gpu_cache_cache_tile (GskGpuCache *self, + gint64 timestamp, + GdkTexture *texture, + guint tile_id, + GskGpuImage *image, + GdkColorState *color_state) +{ + GskGpuCachedTile *tile; + + tile = gsk_gpu_cached_tile_new (self, texture, tile_id, image, color_state); + + gsk_gpu_cached_use (self, (GskGpuCached *) tile, timestamp); +} + /* }}} */ /* {{{ CachedGlyph */ @@ -600,6 +781,7 @@ gsk_gpu_cache_dispose (GObject *object) gsk_gpu_cache_clear_cache (self); g_hash_table_unref (self->glyph_cache); + g_clear_pointer (&self->tile_cache, g_hash_table_unref); g_hash_table_unref (self->texture_cache); G_OBJECT_CLASS (gsk_gpu_cache_parent_class)->dispose (object); diff --git a/gsk/gpu/gskgpucacheprivate.h b/gsk/gpu/gskgpucacheprivate.h index 7d44dd46ea..6f448040dc 100644 --- a/gsk/gpu/gskgpucacheprivate.h +++ b/gsk/gpu/gskgpucacheprivate.h @@ -39,6 +39,17 @@ void gsk_gpu_cache_cache_texture_image (GskGpuC gint64 timestamp, GskGpuImage *image, GdkColorState *color_state); +GskGpuImage * gsk_gpu_cache_lookup_tile (GskGpuCache *self, + GdkTexture *texture, + gsize tile_id, + gint64 timestamp, + GdkColorState **out_color_state); +void gsk_gpu_cache_cache_tile (GskGpuCache *self, + gint64 timestamp, + GdkTexture *texture, + guint tile_id, + GskGpuImage *image, + GdkColorState *color_state); typedef enum { diff --git a/gsk/gpu/gskgpudevice.c b/gsk/gpu/gskgpudevice.c index 61c1c653cf..faaecc47f1 100644 --- a/gsk/gpu/gskgpudevice.c +++ b/gsk/gpu/gskgpudevice.c @@ -22,6 +22,7 @@ struct _GskGpuDevicePrivate { GdkDisplay *display; gsize max_image_size; + gsize tile_size; GskGpuCache *cache; /* we don't own a ref, but manage the cache */ guint cache_gc_source; @@ -142,13 +143,15 @@ gsk_gpu_device_init (GskGpuDevice *self) void gsk_gpu_device_setup (GskGpuDevice *self, GdkDisplay *display, - gsize max_image_size) + gsize max_image_size, + gsize tile_size) { GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self); const char *str; priv->display = g_object_ref (display); priv->max_image_size = max_image_size; + priv->tile_size = tile_size; priv->cache_timeout = CACHE_TIMEOUT; str = g_getenv ("GSK_CACHE_TIMEOUT"); @@ -200,6 +203,19 @@ gsk_gpu_device_get_cache (GskGpuDevice *self) return priv->cache; } +/* + * gsk_gpu_device_get_max_image_size: + * @self: a device + * + * Returns the max image size supported by this device. + * + * This maps to GL_MAX_TEXTURE_SIZE on GL, but Vulkan is more flexible with + * per-format size limits, so this is an estimate and code should still handle + * failures of image creation at smaller sizes. (Besides handling them anyway + * in case of OOM.) + * + * Returns: The maximum size in pixels for creating a GskGpuImage + **/ gsize gsk_gpu_device_get_max_image_size (GskGpuDevice *self) { @@ -208,6 +224,25 @@ gsk_gpu_device_get_max_image_size (GskGpuDevice *self) return priv->max_image_size; } +/* + * gsk_gpu_device_get_tile_size: + * @self: a device + * + * The suggested size for tiling images. This value will be small enough so that + * image creation never fails due to size constraints. It should also not be too + * large to allow efficient caching of tiles and evictions of unused tiles + * (think of an image editor showing only a section of a large image). + * + * Returns: The suggested size of tiles when tiling images. + **/ +gsize +gsk_gpu_device_get_tile_size (GskGpuDevice *self) +{ + GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self); + + return priv->tile_size; +} + GskGpuImage * gsk_gpu_device_create_offscreen_image (GskGpuDevice *self, gboolean with_mipmap, diff --git a/gsk/gpu/gskgpudeviceprivate.h b/gsk/gpu/gskgpudeviceprivate.h index be54efcd72..90b590ec05 100644 --- a/gsk/gpu/gskgpudeviceprivate.h +++ b/gsk/gpu/gskgpudeviceprivate.h @@ -6,6 +6,8 @@ G_BEGIN_DECLS +#define GSK_GPU_DEVICE_DEFAULT_TILE_SIZE 1024 + #define GSK_TYPE_GPU_DEVICE (gsk_gpu_device_get_type ()) #define GSK_GPU_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSK_TYPE_GPU_DEVICE, GskGpuDevice)) #define GSK_GPU_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSK_TYPE_GPU_DEVICE, GskGpuDeviceClass)) @@ -50,12 +52,14 @@ GType gsk_gpu_device_get_type (void) G void gsk_gpu_device_setup (GskGpuDevice *self, GdkDisplay *display, - gsize max_image_size); + gsize max_image_size, + gsize tile_size); void gsk_gpu_device_maybe_gc (GskGpuDevice *self); void gsk_gpu_device_queue_gc (GskGpuDevice *self); GdkDisplay * gsk_gpu_device_get_display (GskGpuDevice *self); GskGpuCache * gsk_gpu_device_get_cache (GskGpuDevice *self); gsize gsk_gpu_device_get_max_image_size (GskGpuDevice *self); +gsize gsk_gpu_device_get_tile_size (GskGpuDevice *self); GskGpuImage * gsk_gpu_device_create_offscreen_image (GskGpuDevice *self, gboolean with_mipmap, diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 2d420a1a25..1d5a9be21d 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -43,8 +43,10 @@ #include "gskprivate.h" #include "gdk/gdkcolorstateprivate.h" +#include "gdk/gdkmemorytextureprivate.h" #include "gdk/gdkrgbaprivate.h" #include "gdk/gdksubsurfaceprivate.h" +#include "gdk/gdktextureprivate.h" /* the epsilon we allow pixels to be off due to rounding errors. * Chosen rather randomly. @@ -1725,6 +1727,163 @@ gsk_gpu_lookup_texture (GskGpuFrame *frame, return image; } +static GskGpuSampler +gsk_gpu_sampler_for_scaling_filter (GskScalingFilter scaling_filter) +{ + switch (scaling_filter) + { + case GSK_SCALING_FILTER_LINEAR: + return GSK_GPU_SAMPLER_DEFAULT; + + case GSK_SCALING_FILTER_NEAREST: + return GSK_GPU_SAMPLER_NEAREST; + + case GSK_SCALING_FILTER_TRILINEAR: + return GSK_GPU_SAMPLER_MIPMAP_DEFAULT; + + default: + g_assert_not_reached (); + return GSK_GPU_SAMPLER_DEFAULT; + } +} + +/* must be set up with BLEND_ADD to avoid seams */ +static void +gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self, + const graphene_rect_t *texture_bounds, + GdkTexture *texture, + GskScalingFilter scaling_filter) +{ + GskGpuCache *cache; + GskGpuDevice *device; + gint64 timestamp; + GskGpuImage *tile; + GdkColorState *tile_cs; + GskGpuSampler sampler; + gboolean need_mipmap; + GdkMemoryTexture *memtex; + GdkTexture *subtex; + float scaled_tile_width, scaled_tile_height; + gsize tile_size, width, height, n_width, n_height, x, y; + graphene_rect_t clip_bounds; + + device = gsk_gpu_frame_get_device (self->frame); + cache = gsk_gpu_device_get_cache (device); + timestamp = gsk_gpu_frame_get_timestamp (self->frame); + sampler = gsk_gpu_sampler_for_scaling_filter (scaling_filter); + need_mipmap = scaling_filter == GSK_SCALING_FILTER_TRILINEAR; + gsk_gpu_node_processor_get_clip_bounds (self, &clip_bounds); + tile_size = gsk_gpu_device_get_tile_size (device); + width = gdk_texture_get_width (texture); + height = gdk_texture_get_height (texture); + n_width = (width + tile_size - 1) / tile_size; + n_height = (height + tile_size - 1) / tile_size; + scaled_tile_width = texture_bounds->size.width * tile_size / width; + scaled_tile_height = texture_bounds->size.height * tile_size / height; + + memtex = NULL; + for (y = 0; y < n_height; y++) + { + for (x = 0; x < n_width; x++) + { + graphene_rect_t tile_rect = GRAPHENE_RECT_INIT (texture_bounds->origin.x + scaled_tile_width * x, + texture_bounds->origin.y + scaled_tile_height * y, + scaled_tile_width, + scaled_tile_height); + if (!gsk_rect_intersection (&tile_rect, texture_bounds, &tile_rect) || + !gsk_rect_intersects (&clip_bounds, &tile_rect)) + continue; + + tile = gsk_gpu_cache_lookup_tile (cache, texture, y * n_width + x, timestamp, &tile_cs); + + if (tile == NULL) + { + if (memtex == NULL) + memtex = gdk_memory_texture_from_texture (texture); + subtex = gdk_memory_texture_new_subtexture (memtex, + x * tile_size, + y * tile_size, + MIN (tile_size, width - x * tile_size), + MIN (tile_size, height - y * tile_size)); + tile = gsk_gpu_upload_texture_op_try (self->frame, need_mipmap, subtex); + g_object_unref (subtex); + if (tile == NULL) + { + g_warning ("failed to create %zux%zu tile for %zux%zu texture. Out of memory?", + tile_size, tile_size, width, height); + goto out; + } + + tile_cs = gdk_texture_get_color_state (texture); + if (gsk_gpu_image_get_flags (tile) & GSK_GPU_IMAGE_SRGB) + { + tile_cs = gdk_color_state_get_no_srgb_tf (tile_cs); + g_assert (tile_cs); + } + + gsk_gpu_cache_cache_tile (cache, timestamp, texture, y * n_width + x, tile, tile_cs); + } + + if (need_mipmap && + (gsk_gpu_image_get_flags (tile) & (GSK_GPU_IMAGE_STRAIGHT_ALPHA | GSK_GPU_IMAGE_CAN_MIPMAP)) != GSK_GPU_IMAGE_CAN_MIPMAP) + { + tile = gsk_gpu_copy_image (self->frame, self->ccs, tile, tile_cs, TRUE); + tile_cs = self->ccs; + gsk_gpu_cache_cache_tile (cache, timestamp, texture, y * n_width + x, tile, tile_cs); + } + if (need_mipmap && !(gsk_gpu_image_get_flags (tile) & GSK_GPU_IMAGE_MIPMAP)) + gsk_gpu_mipmap_op (self->frame, tile); + + gsk_gpu_node_processor_image_op (self, + tile, + tile_cs, + sampler, + &tile_rect, + &tile_rect); + + g_object_unref (tile); + } + } + +out: + g_clear_object (&memtex); +} + +static GskGpuImage * +gsk_gpu_get_texture_tiles_as_image (GskGpuFrame *frame, + GdkColorState *ccs, + const graphene_rect_t *clip_bounds, + const graphene_vec2_t *scale, + const graphene_rect_t *texture_bounds, + GdkTexture *texture, + GskScalingFilter scaling_filter) +{ + GskGpuNodeProcessor self; + GskGpuImage *image; + + image = gsk_gpu_node_processor_init_draw (&self, + frame, + ccs, + gdk_texture_get_depth (texture), + scale, + clip_bounds); + if (image == NULL) + return NULL; + + self.blend = GSK_GPU_BLEND_ADD; + self.pending_globals |= GSK_GPU_GLOBAL_BLEND; + gsk_gpu_node_processor_sync_globals (&self, 0); + + gsk_gpu_node_processor_draw_texture_tiles (&self, + texture_bounds, + texture, + scaling_filter); + + gsk_gpu_node_processor_finish_draw (&self, image); + + return image; +} + static void gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, GskRenderNode *node) @@ -1741,11 +1900,26 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, if (image == NULL) { - GSK_DEBUG (FALLBACK, "Unsupported texture format %u for size %dx%d", - gdk_texture_get_format (texture), - gdk_texture_get_width (texture), - gdk_texture_get_height (texture)); - gsk_gpu_node_processor_add_cairo_node (self, node); + graphene_rect_t clip, rounded_clip; + + if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip)) + return; + rect_round_to_pixels (&clip, &self->scale, &self->offset, &rounded_clip); + + image = gsk_gpu_get_texture_tiles_as_image (self->frame, + self->ccs, + &rounded_clip, + &self->scale, + &node->bounds, + texture, + should_mipmap ? GSK_SCALING_FILTER_TRILINEAR : GSK_SCALING_FILTER_LINEAR); + gsk_gpu_node_processor_image_op (self, + image, + self->ccs, + GSK_GPU_SAMPLER_DEFAULT, + &clip, + &rounded_clip); + g_object_unref (image); return; } @@ -1797,14 +1971,25 @@ gsk_gpu_get_texture_node_as_image (GskGpuFrame *frame, GdkTexture *texture = gsk_texture_node_get_texture (node); GdkColorState *image_cs; GskGpuImage *image; + gboolean should_mipmap; - if (texture_node_should_mipmap (node, frame, scale)) - return gsk_gpu_get_node_as_image_via_offscreen (frame, ccs, clip_bounds, scale, node, out_bounds); - + should_mipmap = texture_node_should_mipmap (node, frame, scale); image = gsk_gpu_lookup_texture (frame, ccs, texture, FALSE, &image_cs); - /* Happens ie for oversized textures */ if (image == NULL) + { + image = gsk_gpu_get_texture_tiles_as_image (frame, + ccs, + clip_bounds, + scale, + &node->bounds, + gsk_texture_node_get_texture (node), + should_mipmap ? GSK_SCALING_FILTER_TRILINEAR : GSK_SCALING_FILTER_LINEAR); + *out_bounds = *clip_bounds; + return image; + } + + if (should_mipmap) return gsk_gpu_get_node_as_image_via_offscreen (frame, ccs, clip_bounds, scale, node, out_bounds); if (!gdk_color_state_equal (ccs, image_cs) || @@ -1833,8 +2018,15 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, guint32 descriptor; gboolean need_mipmap, need_offscreen; - need_offscreen = self->modelview != NULL || - !graphene_vec2_equal (&self->scale, graphene_vec2_one ()); + texture = gsk_texture_scale_node_get_texture (node); + scaling_filter = gsk_texture_scale_node_get_filter (node); + need_mipmap = scaling_filter == GSK_SCALING_FILTER_TRILINEAR; + image = gsk_gpu_lookup_texture (self->frame, self->ccs, texture, need_mipmap, &image_cs); + + need_offscreen = image == NULL || + self->modelview != NULL || + !graphene_vec2_equal (&self->scale, graphene_vec2_one ()); + if (need_offscreen) { GskGpuImage *offscreen; @@ -1853,11 +2045,20 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, return; clip_bounds.size.width = ceilf (clip_bounds.size.width); clip_bounds.size.height = ceilf (clip_bounds.size.height); - offscreen = gsk_gpu_node_processor_create_offscreen (self->frame, - self->ccs, - graphene_vec2_one (), - &clip_bounds, - node); + if (image == NULL) + offscreen = gsk_gpu_get_texture_tiles_as_image (self->frame, + self->ccs, + &clip_bounds, + graphene_vec2_one (), + &node->bounds, + texture, + scaling_filter); + else + offscreen = gsk_gpu_node_processor_create_offscreen (self->frame, + self->ccs, + graphene_vec2_one (), + &clip_bounds, + node); descriptor = gsk_gpu_node_processor_add_image (self, offscreen, GSK_GPU_SAMPLER_DEFAULT); gsk_gpu_texture_op (self->frame, gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds), @@ -1870,22 +2071,6 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, return; } - texture = gsk_texture_scale_node_get_texture (node); - scaling_filter = gsk_texture_scale_node_get_filter (node); - need_mipmap = scaling_filter == GSK_SCALING_FILTER_TRILINEAR; - - image = gsk_gpu_lookup_texture (self->frame, self->ccs, texture, need_mipmap, &image_cs); - - if (image == NULL) - { - GSK_DEBUG (FALLBACK, "Unsupported texture format %u for size %dx%d", - gdk_texture_get_format (texture), - gdk_texture_get_width (texture), - gdk_texture_get_height (texture)); - gsk_gpu_node_processor_add_cairo_node (self, node); - return; - } - if ((gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_STRAIGHT_ALPHA) || (need_mipmap && !(gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_CAN_MIPMAP)) || !gdk_color_state_equal (image_cs, self->ccs)) @@ -1902,24 +2087,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, if (need_mipmap && !(gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_MIPMAP)) gsk_gpu_mipmap_op (self->frame, image); - switch (scaling_filter) - { - case GSK_SCALING_FILTER_LINEAR: - descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT); - break; - - case GSK_SCALING_FILTER_NEAREST: - descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_NEAREST); - break; - - case GSK_SCALING_FILTER_TRILINEAR: - descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_MIPMAP_DEFAULT); - break; - - default: - g_assert_not_reached (); - return; - } + descriptor = gsk_gpu_node_processor_add_image (self, image, gsk_gpu_sampler_for_scaling_filter (scaling_filter)); gsk_gpu_texture_op (self->frame, gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds), diff --git a/gsk/gpu/gskvulkandevice.c b/gsk/gpu/gskvulkandevice.c index da207cde50..80f53a94f2 100644 --- a/gsk/gpu/gskvulkandevice.c +++ b/gsk/gpu/gskvulkandevice.c @@ -575,7 +575,8 @@ gsk_vulkan_device_setup (GskVulkanDevice *self, self->max_immutable_samplers = MIN (self->max_samplers / 3, 32); gsk_gpu_device_setup (GSK_GPU_DEVICE (self), display, - vk_props.properties.limits.maxImageDimension2D); + vk_props.properties.limits.maxImageDimension2D, + GSK_GPU_DEVICE_DEFAULT_TILE_SIZE); } GskGpuDevice *