diff --git a/gsk/gpu/gskgpucache.c b/gsk/gpu/gskgpucache.c index 211b54bf85..49823e0f17 100644 --- a/gsk/gpu/gskgpucache.c +++ b/gsk/gpu/gskgpucache.c @@ -39,6 +39,7 @@ struct _GskGpuCache GObject parent_instance; GskGpuDevice *device; + gint64 timestamp; GskGpuCached *first_cached; GskGpuCached *last_cached; @@ -152,10 +153,9 @@ gsk_gpu_cached_new (GskGpuCache *cache, static void gsk_gpu_cached_use (GskGpuCache *self, - GskGpuCached *cached, - gint64 timestamp) + GskGpuCached *cached) { - cached->timestamp = timestamp; + cached->timestamp = self->timestamp; mark_as_stale (cached, FALSE); } @@ -247,6 +247,141 @@ gsk_gpu_cached_atlas_new (GskGpuCache *cache) return self; } +/* This rounds up to the next number that has <= 2 bits set: + * 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, ... + * That is roughly sqrt(2), so it should limit waste + */ +static gsize +round_up_atlas_size (gsize num) +{ + gsize storage = g_bit_storage (num); + + num = num + (((1 << storage) - 1) >> 2); + num &= (((gsize) 7) << storage) >> 2; + + return num; +} + +static gboolean +gsk_gpu_cached_atlas_allocate (GskGpuCachedAtlas *atlas, + gsize width, + gsize height, + gsize *out_x, + gsize *out_y) +{ + gsize i; + gsize waste, slice_waste; + gsize best_slice; + gsize y, best_y; + gboolean can_add_slice; + + best_y = 0; + best_slice = G_MAXSIZE; + can_add_slice = atlas->n_slices < MAX_SLICES_PER_ATLAS; + if (can_add_slice) + waste = height; /* Require less than 100% waste */ + else + waste = G_MAXSIZE; /* Accept any slice, we can't make better ones */ + + for (i = 0, y = 0; i < atlas->n_slices; y += atlas->slices[i].height, i++) + { + if (atlas->slices[i].height < height || ATLAS_SIZE - atlas->slices[i].width < width) + continue; + + slice_waste = atlas->slices[i].height - height; + if (slice_waste < waste) + { + waste = slice_waste; + best_slice = i; + best_y = y; + if (waste == 0) + break; + } + } + + if (best_slice >= i && i == atlas->n_slices) + { + gsize slice_height; + + if (!can_add_slice) + return FALSE; + + slice_height = round_up_atlas_size (MAX (height, 4)); + if (slice_height > ATLAS_SIZE - y) + return FALSE; + + atlas->n_slices++; + if (atlas->n_slices == MAX_SLICES_PER_ATLAS) + slice_height = ATLAS_SIZE - y; + + atlas->slices[i].width = 0; + atlas->slices[i].height = slice_height; + best_y = y; + best_slice = i; + } + + *out_x = atlas->slices[best_slice].width; + *out_y = best_y; + + atlas->slices[best_slice].width += width; + g_assert (atlas->slices[best_slice].width <= ATLAS_SIZE); + + atlas->remaining_pixels -= width * height; + ((GskGpuCached *) atlas)->pixels += width * height; + + return TRUE; +} + +static void +gsk_gpu_cache_ensure_atlas (GskGpuCache *self, + gboolean recreate) +{ + if (self->current_atlas && !recreate) + return; + + if (self->current_atlas) + self->current_atlas->remaining_pixels = 0; + + self->current_atlas = gsk_gpu_cached_atlas_new (self); +} + +GskGpuImage * +gsk_gpu_cache_get_atlas_image (GskGpuCache *self) +{ + gsk_gpu_cache_ensure_atlas (self, FALSE); + + return self->current_atlas->image; +} + +static GskGpuImage * +gsk_gpu_cache_add_atlas_image (GskGpuCache *self, + gsize width, + gsize height, + gsize *out_x, + gsize *out_y) +{ + if (width > MAX_ATLAS_ITEM_SIZE || height > MAX_ATLAS_ITEM_SIZE) + return NULL; + + gsk_gpu_cache_ensure_atlas (self, FALSE); + + if (gsk_gpu_cached_atlas_allocate (self->current_atlas, width, height, out_x, out_y)) + { + gsk_gpu_cached_use (self, (GskGpuCached *) self->current_atlas); + return self->current_atlas->image; + } + + gsk_gpu_cache_ensure_atlas (self, TRUE); + + if (gsk_gpu_cached_atlas_allocate (self->current_atlas, width, height, out_x, out_y)) + { + gsk_gpu_cached_use (self, (GskGpuCached *) self->current_atlas); + return self->current_atlas->image; + } + + return NULL; +} + /* }}} */ /* {{{ CachedTexture */ @@ -552,7 +687,6 @@ GskGpuImage * gsk_gpu_cache_lookup_tile (GskGpuCache *self, GdkTexture *texture, gsize tile_id, - gint64 timestamp, GdkColorState **out_color_state) { GskGpuCachedTile *tile; @@ -568,7 +702,7 @@ gsk_gpu_cache_lookup_tile (GskGpuCache *self, if (tile == NULL) return NULL; - gsk_gpu_cached_use (self, (GskGpuCached *) tile, timestamp); + gsk_gpu_cached_use (self, (GskGpuCached *) tile); *out_color_state = tile->color_state; @@ -577,7 +711,6 @@ gsk_gpu_cache_lookup_tile (GskGpuCache *self, void gsk_gpu_cache_cache_tile (GskGpuCache *self, - gint64 timestamp, GdkTexture *texture, guint tile_id, GskGpuImage *image, @@ -587,7 +720,7 @@ gsk_gpu_cache_cache_tile (GskGpuCache *self, tile = gsk_gpu_cached_tile_new (self, texture, tile_id, image, color_state); - gsk_gpu_cached_use (self, (GskGpuCached *) tile, timestamp); + gsk_gpu_cached_use (self, (GskGpuCached *) tile); } /* }}} */ @@ -674,6 +807,21 @@ static const GskGpuCachedClass GSK_GPU_CACHED_GLYPH_CLASS = /* }}} */ /* {{{ GskGpuCache */ +/* + * gsk_gpu_cache_set_time: + * @self: a `GskGpuCache` + * @timestamp: time in whatever the frameclock uses + * + * Sets the timestamp to use for all following operations. + * Frames should set this when they start drawing. + **/ +void +gsk_gpu_cache_set_time (GskGpuCache *self, + gint64 timestamp) +{ + self->timestamp = timestamp; +} + typedef struct { guint n_items; @@ -841,146 +989,9 @@ gsk_gpu_cache_init (GskGpuCache *self) g_direct_equal); } -/* This rounds up to the next number that has <= 2 bits set: - * 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, ... - * That is roughly sqrt(2), so it should limit waste - */ -static gsize -round_up_atlas_size (gsize num) -{ - gsize storage = g_bit_storage (num); - - num = num + (((1 << storage) - 1) >> 2); - num &= (((gsize) 7) << storage) >> 2; - - return num; -} - -static gboolean -gsk_gpu_cached_atlas_allocate (GskGpuCachedAtlas *atlas, - gsize width, - gsize height, - gsize *out_x, - gsize *out_y) -{ - gsize i; - gsize waste, slice_waste; - gsize best_slice; - gsize y, best_y; - gboolean can_add_slice; - - best_y = 0; - best_slice = G_MAXSIZE; - can_add_slice = atlas->n_slices < MAX_SLICES_PER_ATLAS; - if (can_add_slice) - waste = height; /* Require less than 100% waste */ - else - waste = G_MAXSIZE; /* Accept any slice, we can't make better ones */ - - for (i = 0, y = 0; i < atlas->n_slices; y += atlas->slices[i].height, i++) - { - if (atlas->slices[i].height < height || ATLAS_SIZE - atlas->slices[i].width < width) - continue; - - slice_waste = atlas->slices[i].height - height; - if (slice_waste < waste) - { - waste = slice_waste; - best_slice = i; - best_y = y; - if (waste == 0) - break; - } - } - - if (best_slice >= i && i == atlas->n_slices) - { - gsize slice_height; - - if (!can_add_slice) - return FALSE; - - slice_height = round_up_atlas_size (MAX (height, 4)); - if (slice_height > ATLAS_SIZE - y) - return FALSE; - - atlas->n_slices++; - if (atlas->n_slices == MAX_SLICES_PER_ATLAS) - slice_height = ATLAS_SIZE - y; - - atlas->slices[i].width = 0; - atlas->slices[i].height = slice_height; - best_y = y; - best_slice = i; - } - - *out_x = atlas->slices[best_slice].width; - *out_y = best_y; - - atlas->slices[best_slice].width += width; - g_assert (atlas->slices[best_slice].width <= ATLAS_SIZE); - - atlas->remaining_pixels -= width * height; - ((GskGpuCached *) atlas)->pixels += width * height; - - return TRUE; -} - -static void -gsk_gpu_cache_ensure_atlas (GskGpuCache *self, - gboolean recreate) -{ - if (self->current_atlas && !recreate) - return; - - if (self->current_atlas) - self->current_atlas->remaining_pixels = 0; - - self->current_atlas = gsk_gpu_cached_atlas_new (self); -} - -GskGpuImage * -gsk_gpu_cache_get_atlas_image (GskGpuCache *self) -{ - gsk_gpu_cache_ensure_atlas (self, FALSE); - - return self->current_atlas->image; -} - -static GskGpuImage * -gsk_gpu_cache_add_atlas_image (GskGpuCache *self, - gint64 timestamp, - gsize width, - gsize height, - gsize *out_x, - gsize *out_y) -{ - if (width > MAX_ATLAS_ITEM_SIZE || height > MAX_ATLAS_ITEM_SIZE) - return NULL; - - gsk_gpu_cache_ensure_atlas (self, FALSE); - - if (gsk_gpu_cached_atlas_allocate (self->current_atlas, width, height, out_x, out_y)) - { - gsk_gpu_cached_use (self, (GskGpuCached *) self->current_atlas, timestamp); - return self->current_atlas->image; - } - - gsk_gpu_cache_ensure_atlas (self, TRUE); - - if (gsk_gpu_cached_atlas_allocate (self->current_atlas, width, height, out_x, out_y)) - { - gsk_gpu_cached_use (self, (GskGpuCached *) self->current_atlas, timestamp); - return self->current_atlas->image; - } - - return NULL; -} - GskGpuImage * gsk_gpu_cache_lookup_texture_image (GskGpuCache *self, GdkTexture *texture, - gint64 timestamp, GdkColorState *color_state) { GskGpuCachedTexture *cache; @@ -999,7 +1010,7 @@ gsk_gpu_cache_lookup_texture_image (GskGpuCache *self, if (!cache || !cache->image || gsk_gpu_cached_texture_is_invalid (cache)) return NULL; - gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp); + gsk_gpu_cached_use (self, (GskGpuCached *) cache); return g_object_ref (cache->image); } @@ -1007,7 +1018,6 @@ gsk_gpu_cache_lookup_texture_image (GskGpuCache *self, void gsk_gpu_cache_cache_texture_image (GskGpuCache *self, GdkTexture *texture, - gint64 timestamp, GskGpuImage *image, GdkColorState *color_state) { @@ -1016,7 +1026,7 @@ gsk_gpu_cache_cache_texture_image (GskGpuCache *self, cache = gsk_gpu_cached_texture_new (self, texture, image, color_state); g_return_if_fail (cache != NULL); - gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp); + gsk_gpu_cached_use (self, (GskGpuCached *) cache); } GskGpuImage * @@ -1048,7 +1058,7 @@ gsk_gpu_cache_lookup_glyph_image (GskGpuCache *self, cache = g_hash_table_lookup (self->glyph_cache, &lookup); if (cache) { - gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame)); + gsk_gpu_cached_use (self, (GskGpuCached *) cache); *out_bounds = cache->bounds; *out_origin = cache->origin; @@ -1075,7 +1085,6 @@ gsk_gpu_cache_lookup_glyph_image (GskGpuCache *self, padding = 1; image = gsk_gpu_cache_add_atlas_image (self, - gsk_gpu_frame_get_timestamp (frame), rect.size.width + 2 * padding, rect.size.height + 2 * padding, &atlas_x, &atlas_y); if (image) @@ -1118,7 +1127,7 @@ gsk_gpu_cache_lookup_glyph_image (GskGpuCache *self, cache->origin.y + padding)); g_hash_table_insert (self->glyph_cache, cache, cache); - gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame)); + gsk_gpu_cached_use (self, (GskGpuCached *) cache); *out_bounds = cache->bounds; *out_origin = cache->origin; diff --git a/gsk/gpu/gskgpucacheprivate.h b/gsk/gpu/gskgpucacheprivate.h index 6f448040dc..002756b5b7 100644 --- a/gsk/gpu/gskgpucacheprivate.h +++ b/gsk/gpu/gskgpucacheprivate.h @@ -24,6 +24,8 @@ GType gsk_gpu_cache_get_type (void) G GskGpuCache * gsk_gpu_cache_new (GskGpuDevice *device); +void gsk_gpu_cache_set_time (GskGpuCache *self, + gint64 timestamp); gboolean gsk_gpu_cache_gc (GskGpuCache *self, gint64 cache_timeout, gint64 timestamp); @@ -32,20 +34,16 @@ GskGpuImage * gsk_gpu_cache_get_atlas_image (GskGpuC GskGpuImage * gsk_gpu_cache_lookup_texture_image (GskGpuCache *self, GdkTexture *texture, - gint64 timestamp, GdkColorState *color_state); void gsk_gpu_cache_cache_texture_image (GskGpuCache *self, GdkTexture *texture, - 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, diff --git a/gsk/gpu/gskgpudownloadop.c b/gsk/gpu/gskgpudownloadop.c index 133aafcbfe..182929d9ad 100644 --- a/gsk/gpu/gskgpudownloadop.c +++ b/gsk/gpu/gskgpudownloadop.c @@ -150,7 +150,7 @@ gsk_gpu_download_op_vk_command (GskGpuOp *op, GskGpuCache *cache = gsk_gpu_device_get_cache (device); VkDevice vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (device)); - gsk_gpu_cache_cache_texture_image (cache, self->texture, gsk_gpu_frame_get_timestamp (frame), self->image, NULL); + gsk_gpu_cache_cache_texture_image (cache, self->texture, self->image, NULL); if (gsk_vulkan_device_has_feature (GSK_VULKAN_DEVICE (device), GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT)) { diff --git a/gsk/gpu/gskgpuframe.c b/gsk/gpu/gskgpuframe.c index beb7a981e5..f7ed1083fc 100644 --- a/gsk/gpu/gskgpuframe.c +++ b/gsk/gpu/gskgpuframe.c @@ -445,7 +445,7 @@ gsk_gpu_frame_upload_texture (GskGpuFrame *self, image = GSK_GPU_FRAME_GET_CLASS (self)->upload_texture (self, with_mipmap, texture); if (image) - gsk_gpu_cache_cache_texture_image (gsk_gpu_device_get_cache (priv->device), texture, priv->timestamp, image, NULL); + gsk_gpu_cache_cache_texture_image (gsk_gpu_device_get_cache (priv->device), texture, image, NULL); return image; } @@ -605,6 +605,7 @@ gsk_gpu_frame_record (GskGpuFrame *self, GskRenderPassType pass_type = texture ? GSK_RENDER_PASS_EXPORT : GSK_RENDER_PASS_PRESENT; priv->timestamp = timestamp; + gsk_gpu_cache_set_time (gsk_gpu_device_get_cache (priv->device), timestamp); if (clip) { @@ -725,7 +726,10 @@ gsk_gpu_frame_download_texture (GskGpuFrame *self, GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self); GskGpuImage *image; - image = gsk_gpu_cache_lookup_texture_image (gsk_gpu_device_get_cache (priv->device), texture, timestamp, NULL); + priv->timestamp = timestamp; + gsk_gpu_cache_set_time (gsk_gpu_device_get_cache (priv->device), timestamp); + + image = gsk_gpu_cache_lookup_texture_image (gsk_gpu_device_get_cache (priv->device), texture, NULL); if (image == NULL) image = gsk_gpu_frame_upload_texture (self, FALSE, texture); if (image == NULL) @@ -736,8 +740,6 @@ gsk_gpu_frame_download_texture (GskGpuFrame *self, gsk_gpu_frame_cleanup (self); - priv->timestamp = timestamp; - gsk_gpu_download_op (self, image, FALSE, diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index b5a56a3f9b..5ffe7df433 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -1684,20 +1684,18 @@ gsk_gpu_lookup_texture (GskGpuFrame *frame, { GskGpuCache *cache; GdkColorState *image_cs; - gint64 timestamp; GskGpuImage *image; cache = gsk_gpu_device_get_cache (gsk_gpu_frame_get_device (frame)); - timestamp = gsk_gpu_frame_get_timestamp (frame); - image = gsk_gpu_cache_lookup_texture_image (cache, texture, timestamp, ccs); + image = gsk_gpu_cache_lookup_texture_image (cache, texture, ccs); if (image) { *out_image_cs = ccs; return image; } - image = gsk_gpu_cache_lookup_texture_image (cache, texture, timestamp, NULL); + image = gsk_gpu_cache_lookup_texture_image (cache, texture, NULL); if (image == NULL) image = gsk_gpu_frame_upload_texture (frame, try_mipmap, texture); @@ -1746,7 +1744,6 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self, { GskGpuCache *cache; GskGpuDevice *device; - gint64 timestamp; GskGpuImage *tile; GdkColorState *tile_cs; GskGpuSampler sampler; @@ -1759,7 +1756,6 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self, 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); @@ -1784,7 +1780,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self, !gsk_rect_intersects (&clip_bounds, &tile_rect)) continue; - tile = gsk_gpu_cache_lookup_tile (cache, texture, y * n_width + x, timestamp, &tile_cs); + tile = gsk_gpu_cache_lookup_tile (cache, texture, y * n_width + x, &tile_cs); if (tile == NULL) { @@ -1811,7 +1807,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self, g_assert (tile_cs); } - gsk_gpu_cache_cache_tile (cache, timestamp, texture, y * n_width + x, tile, tile_cs); + gsk_gpu_cache_cache_tile (cache, texture, y * n_width + x, tile, tile_cs); } if (need_mipmap && @@ -1819,7 +1815,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self, { 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); + gsk_gpu_cache_cache_tile (cache, 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); @@ -1922,7 +1918,6 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self, image_cs = self->ccs; gsk_gpu_cache_cache_texture_image (gsk_gpu_device_get_cache (gsk_gpu_frame_get_device (self->frame)), texture, - gsk_gpu_frame_get_timestamp (self->frame), image, image_cs); } @@ -1988,7 +1983,6 @@ gsk_gpu_get_texture_node_as_image (GskGpuFrame *frame, image = gsk_gpu_copy_image (frame, ccs, image, image_cs, FALSE); gsk_gpu_cache_cache_texture_image (gsk_gpu_device_get_cache (gsk_gpu_frame_get_device (frame)), texture, - gsk_gpu_frame_get_timestamp (frame), image, ccs); } @@ -2077,7 +2071,6 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self, image_cs = self->ccs; gsk_gpu_cache_cache_texture_image (gsk_gpu_device_get_cache (gsk_gpu_frame_get_device (self->frame)), texture, - gsk_gpu_frame_get_timestamp (self->frame), image, image_cs); } @@ -2631,6 +2624,17 @@ gsk_gpu_node_processor_add_cross_fade_node (GskGpuNodeProcessor *self, end_child = gsk_cross_fade_node_get_end_child (node); progress = gsk_cross_fade_node_get_progress (node); + if (progress <= 0.0) + { + gsk_gpu_node_processor_add_node (self, start_child); + return; + } + if (progress >= 1.0) + { + gsk_gpu_node_processor_add_node (self, end_child); + return; + } + start_image = gsk_gpu_node_processor_get_node_as_image (self, NULL, start_child, diff --git a/gsk/gpu/gskvulkandevice.c b/gsk/gpu/gskvulkandevice.c index 361f6a66a7..86b9995066 100644 --- a/gsk/gpu/gskvulkandevice.c +++ b/gsk/gpu/gskvulkandevice.c @@ -979,7 +979,7 @@ gsk_vulkan_device_get_vk_pipeline (GskVulkanDevice *self, char *vertex_shader_name, *fragment_shader_name; G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME; const char *clip_name[] = { "NONE", "RECT", "ROUNDED" }; - const char *blend_name[] = { "OVER", "ADD", "CLEAR" }; + const char *blend_name[] = { "NONE", "OVER", "ADD", "CLEAR" }; cache_key = (PipelineCacheKey) { .op_class = op_class,