From 697f2b8e95a4dcb6ca8ed0cf38e835fbe34bf85b Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 1 Nov 2023 06:04:14 +0100 Subject: [PATCH] gpu: Add blitting support Add GSK_GPU_IMAGE_NO_BLIT flag for textures that can't be blitted from. Use a blit op to do image copies otherwise. --- gsk/gpu/gskgpublitop.c | 2 + gsk/gpu/gskgpunodeprocessor.c | 93 ++++++++++++++++++++--------------- gsk/gpu/gskgputypesprivate.h | 1 + gsk/gpu/gskvulkanimage.c | 29 ++++++++--- 4 files changed, 76 insertions(+), 49 deletions(-) diff --git a/gsk/gpu/gskgpublitop.c b/gsk/gpu/gskgpublitop.c index 170feb5d82..1129fcd4d3 100644 --- a/gsk/gpu/gskgpublitop.c +++ b/gsk/gpu/gskgpublitop.c @@ -209,6 +209,8 @@ gsk_gpu_blit_op (GskGpuFrame *frame, { GskGpuBlitOp *self; + g_assert ((gsk_gpu_image_get_flags (src_image) & GSK_GPU_IMAGE_NO_BLIT) == 0); + self = (GskGpuBlitOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_BLIT_OP_CLASS); self->src_image = g_object_ref (src_image); diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 6ada4e49a8..4f79a5b958 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -4,6 +4,7 @@ #include "gskgpuborderopprivate.h" #include "gskgpuboxshadowopprivate.h" +#include "gskgpublitopprivate.h" #include "gskgpubluropprivate.h" #include "gskgpuclearopprivate.h" #include "gskgpuclipprivate.h" @@ -571,9 +572,6 @@ gsk_gpu_node_processor_ensure_image (GskGpuNodeProcessor *self, GskGpuImageFlags flags, missing_flags; GskGpuImage *copy; gsize width, height; - GskGpuNodeProcessor other; - graphene_rect_t rect; - guint32 descriptor; g_assert ((required_flags & disallowed_flags) == 0); g_assert ((required_flags & (GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_STRAIGHT_ALPHA)) == 0); @@ -593,50 +591,63 @@ gsk_gpu_node_processor_ensure_image (GskGpuNodeProcessor *self, gdk_memory_format_get_depth (gsk_gpu_image_get_format (image)), width, height); - rect = GRAPHENE_RECT_INIT (0, 0, width, height); - descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT); - - gsk_gpu_node_processor_init (&other, - self->frame, - self->desc, - copy, - &(cairo_rectangle_int_t) { 0, 0, width, height }, - &rect); - - gsk_gpu_render_pass_begin_op (other.frame, - copy, - &(cairo_rectangle_int_t) { 0, 0, width, height }, - GSK_RENDER_PASS_OFFSCREEN); - - gsk_gpu_node_processor_sync_globals (&other, 0); - - if (flags & GSK_GPU_IMAGE_STRAIGHT_ALPHA) + if ((flags & (GSK_GPU_IMAGE_NO_BLIT | GSK_GPU_IMAGE_STRAIGHT_ALPHA)) == 0) { - gsk_gpu_straight_alpha_op (other.frame, - gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &rect), - self->desc, - descriptor, - &rect, - &other.offset, - &rect); + gsk_gpu_blit_op (self->frame, + image, + copy, + &(cairo_rectangle_int_t) { 0, 0, width, height }, + &(cairo_rectangle_int_t) { 0, 0, width, height }, + GSK_GPU_BLIT_NEAREST); } else { - gsk_gpu_texture_op (other.frame, - gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &rect), - self->desc, - descriptor, - &rect, - &other.offset, - &rect); + GskGpuNodeProcessor other; + graphene_rect_t rect = GRAPHENE_RECT_INIT (0, 0, width, height); + guint32 descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT); + + gsk_gpu_node_processor_init (&other, + self->frame, + self->desc, + copy, + &(cairo_rectangle_int_t) { 0, 0, width, height }, + &rect); + + gsk_gpu_render_pass_begin_op (other.frame, + copy, + &(cairo_rectangle_int_t) { 0, 0, width, height }, + GSK_RENDER_PASS_OFFSCREEN); + + gsk_gpu_node_processor_sync_globals (&other, 0); + + if (flags & GSK_GPU_IMAGE_STRAIGHT_ALPHA) + { + gsk_gpu_straight_alpha_op (other.frame, + gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &rect), + self->desc, + descriptor, + &rect, + &other.offset, + &rect); + } + else + { + gsk_gpu_texture_op (other.frame, + gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &rect), + self->desc, + descriptor, + &rect, + &other.offset, + &rect); + } + + gsk_gpu_render_pass_end_op (other.frame, + copy, + GSK_RENDER_PASS_OFFSCREEN); + + gsk_gpu_node_processor_finish (&other); } - gsk_gpu_render_pass_end_op (other.frame, - image, - GSK_RENDER_PASS_OFFSCREEN); - - gsk_gpu_node_processor_finish (&other); - g_object_unref (image); return copy; diff --git a/gsk/gpu/gskgputypesprivate.h b/gsk/gpu/gskgputypesprivate.h index 23d0873507..cf099155e8 100644 --- a/gsk/gpu/gskgputypesprivate.h +++ b/gsk/gpu/gskgputypesprivate.h @@ -20,6 +20,7 @@ typedef enum { GSK_GPU_IMAGE_EXTERNAL = (1 << 0), GSK_GPU_IMAGE_TOGGLE_REF = (1 << 1), GSK_GPU_IMAGE_STRAIGHT_ALPHA = (1 << 2), + GSK_GPU_IMAGE_NO_BLIT = (1 << 3), } GskGpuImageFlags; typedef enum { diff --git a/gsk/gpu/gskvulkanimage.c b/gsk/gpu/gskvulkanimage.c index 813fc2f8c3..763d5ca7c3 100644 --- a/gsk/gpu/gskvulkanimage.c +++ b/gsk/gpu/gskvulkanimage.c @@ -458,7 +458,8 @@ gsk_vulkan_device_supports_format (GskVulkanDevice *device, VkImageTiling tiling, VkImageUsageFlags usage, gsize width, - gsize height) + gsize height, + GskGpuImageFlags *out_flags) { VkDrmFormatModifierPropertiesEXT drm_mod_properties[100]; VkDrmFormatModifierPropertiesListEXT drm_properties; @@ -545,6 +546,10 @@ gsk_vulkan_device_supports_format (GskVulkanDevice *device, image_properties.imageFormatProperties.maxExtent.height < height) return FALSE; + *out_flags = 0; + if ((features & VK_FORMAT_FEATURE_BLIT_SRC_BIT) == 0) + *out_flags |= GSK_GPU_IMAGE_NO_BLIT; + return TRUE; } @@ -593,6 +598,7 @@ gsk_vulkan_image_new (GskVulkanDevice *device, GskVulkanImage *self; VkDevice vk_device; const GskMemoryFormatInfo *vk_format; + GskGpuImageFlags flags; g_assert (width > 0 && height > 0); @@ -613,7 +619,8 @@ gsk_vulkan_image_new (GskVulkanDevice *device, vk_format->format, 0, 1, tiling, usage, - width, height)) + width, height, + &flags)) break; if (tiling != VK_IMAGE_TILING_OPTIMAL && @@ -621,7 +628,8 @@ gsk_vulkan_image_new (GskVulkanDevice *device, vk_format->format, 0, 1, VK_IMAGE_TILING_OPTIMAL, usage, - width, height)) + width, height, + &flags)) { tiling = VK_IMAGE_TILING_OPTIMAL; break; @@ -650,7 +658,7 @@ gsk_vulkan_image_new (GskVulkanDevice *device, self->vk_access = access; gsk_gpu_image_setup (GSK_GPU_IMAGE (self), - vk_format->flags, + flags | vk_format->flags, format, width, height); GSK_VK_CHECK (vkCreateImage, vk_device, @@ -664,7 +672,8 @@ gsk_vulkan_image_new (GskVulkanDevice *device, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = tiling, - .usage = usage, + .usage = usage | + (flags & GSK_GPU_IMAGE_NO_BLIT ? 0 : VK_IMAGE_USAGE_TRANSFER_SRC_BIT), .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .initialLayout = self->vk_image_layout, }, @@ -857,6 +866,7 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device, gsize width, height; const GdkDmabuf *dmabuf; VkResult res; + GskGpuImageFlags flags; gboolean is_yuv; if (!gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_DMABUF)) @@ -895,7 +905,8 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device, dmabuf->n_planes, VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, VK_IMAGE_USAGE_SAMPLED_BIT, - width, height)) + width, height, + &flags)) { GDK_DEBUG (DMABUF, "Vulkan driver does not support format %.4s::%016llx with %u planes", (char *) &dmabuf->fourcc, (unsigned long long) dmabuf->modifier, dmabuf->n_planes); @@ -923,7 +934,8 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, - .usage = VK_IMAGE_USAGE_SAMPLED_BIT, + .usage = VK_IMAGE_USAGE_SAMPLED_BIT | + (flags & GSK_GPU_IMAGE_NO_BLIT ? 0 : VK_IMAGE_USAGE_TRANSFER_SRC_BIT), .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .initialLayout = self->vk_image_layout, .pNext = &(VkExternalMemoryImageCreateInfo) { @@ -964,8 +976,9 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device, } gsk_gpu_image_setup (GSK_GPU_IMAGE (self), + flags | (gdk_memory_format_alpha (gdk_texture_get_format (texture)) == GDK_MEMORY_ALPHA_STRAIGHT ? GSK_GPU_IMAGE_STRAIGHT_ALPHA : 0) | - (is_yuv ? GSK_GPU_IMAGE_EXTERNAL : 0), + (is_yuv ? (GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT) : 0), gdk_texture_get_format (texture), width, height); gsk_gpu_image_toggle_ref_texture (GSK_GPU_IMAGE (self), texture);