diff options
author | Benjamin Otte <otte.benjamin@googlemail.com> | 2023-04-03 14:27:24 +0000 |
---|---|---|
committer | Benjamin Otte <otte.benjamin@googlemail.com> | 2023-04-03 14:27:24 +0000 |
commit | 362bdaa8526bbf4892c1781d33d92eb3c2203163 (patch) | |
tree | 34786718f3a84cc8fd73b0eb4f2af498505a78f6 | |
parent | 79b0e594cd21c75209aab973b17ced3788a21bfe (diff) | |
parent | 5c27a0dd2bd2a1ea15e583b4447f6160d7079814 (diff) | |
download | gtk+-362bdaa8526bbf4892c1781d33d92eb3c2203163.tar.gz |
Merge branch 'gbsneto/vulkan-layout-fixes' into 'main'
Vulkan fractional scale support, image layout and clip region fixes, cleanups
See merge request GNOME/gtk!5783
-rw-r--r-- | gdk/gdkvulkancontext.c | 19 | ||||
-rw-r--r-- | gsk/vulkan/gskvulkanbuffer.c | 2 | ||||
-rw-r--r-- | gsk/vulkan/gskvulkanglyphcache.c | 4 | ||||
-rw-r--r-- | gsk/vulkan/gskvulkanimage.c | 7 | ||||
-rw-r--r-- | gsk/vulkan/gskvulkanrender.c | 18 | ||||
-rw-r--r-- | gsk/vulkan/gskvulkanrenderer.c | 72 | ||||
-rw-r--r-- | gsk/vulkan/gskvulkanrenderpass.c | 8 |
7 files changed, 91 insertions, 39 deletions
diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 3f669bfc4d..f1f41ce6c9 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -26,6 +26,7 @@ #include "gdkdisplayprivate.h" #include <glib/gi18n-lib.h> +#include <math.h> /** * GdkVulkanContext: @@ -339,8 +340,10 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context, */ if (capabilities.currentExtent.width == -1 || capabilities.currentExtent.height == -1) { - capabilities.currentExtent.width = MAX (1, gdk_surface_get_width (surface) * gdk_surface_get_scale_factor (surface)); - capabilities.currentExtent.height = MAX (1, gdk_surface_get_height (surface) * gdk_surface_get_scale_factor (surface)); + double scale = gdk_surface_get_scale (surface); + + capabilities.currentExtent.width = MAX (1, (int) ceil (gdk_surface_get_width (surface) * scale)); + capabilities.currentExtent.height = MAX (1, (int) ceil (gdk_surface_get_height (surface) * scale)); } res = GDK_VK_CHECK (vkCreateSwapchainKHR, device, @@ -475,10 +478,10 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context, VkPresentRegionsKHR *regionsptr = VK_NULL_HANDLE; VkPresentRegionsKHR regions; VkRectLayerKHR *rectangles; + double scale; int n_regions; - int scale; - scale = gdk_surface_get_scale_factor (surface); + scale = gdk_surface_get_scale (surface); n_regions = cairo_region_num_rectangles (painted); rectangles = g_alloca (sizeof (VkRectLayerKHR) * n_regions); @@ -490,10 +493,10 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context, rectangles[i] = (VkRectLayerKHR) { .layer = 0, - .offset.x = r.x * scale, - .offset.y = r.y * scale, - .extent.width = r.width * scale, - .extent.height = r.height * scale, + .offset.x = (int) floor (r.x * scale), + .offset.y = (int) floor (r.y * scale), + .extent.width = (int) ceil (r.width * scale), + .extent.height = (int) ceil (r.height * scale), }; } diff --git a/gsk/vulkan/gskvulkanbuffer.c b/gsk/vulkan/gskvulkanbuffer.c index b73907faea..21ce89bd31 100644 --- a/gsk/vulkan/gskvulkanbuffer.c +++ b/gsk/vulkan/gskvulkanbuffer.c @@ -46,7 +46,7 @@ gsk_vulkan_buffer_new_internal (GdkVulkanContext *context, self->memory = gsk_vulkan_memory_new (context, requirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - size); + requirements.size); GSK_VK_CHECK (vkBindBufferMemory, gdk_vulkan_context_get_device (context), self->vk_buffer, diff --git a/gsk/vulkan/gskvulkanglyphcache.c b/gsk/vulkan/gskvulkanglyphcache.c index 15db38d9aa..ab623b9445 100644 --- a/gsk/vulkan/gskvulkanglyphcache.c +++ b/gsk/vulkan/gskvulkanglyphcache.c @@ -261,8 +261,8 @@ render_glyph (Atlas *atlas, PangoGlyphInfo gi; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - value->draw_width * key->scale / 1024, - value->draw_height * key->scale / 1024); + ceil (value->draw_width * key->scale / 1024.0), + ceil (value->draw_height * key->scale / 1024.0)); cairo_surface_set_device_scale (surface, key->scale / 1024.0, key->scale / 1024.0); cr = cairo_create (surface); diff --git a/gsk/vulkan/gskvulkanimage.c b/gsk/vulkan/gskvulkanimage.c index b74eb76fb0..075e2501f4 100644 --- a/gsk/vulkan/gskvulkanimage.c +++ b/gsk/vulkan/gskvulkanimage.c @@ -355,7 +355,7 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GskVulkanUploader *uploader, .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = gsk_vulkan_buffer_get_buffer(staging), + .buffer = gsk_vulkan_buffer_get_buffer (staging), .offset = 0, .size = buffer_size, }); @@ -570,13 +570,12 @@ gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context, { GskVulkanImage *self; - self = gsk_vulkan_image_new (context, width, height, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_UNDEFINED, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); @@ -723,6 +722,8 @@ gsk_vulkan_image_upload_regions (GskVulkanImage *self, } bufferImageCopy[i].bufferOffset = offset; + bufferImageCopy[i].bufferRowLength = regions[i].width; + bufferImageCopy[i].bufferImageHeight = regions[i].height; bufferImageCopy[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferImageCopy[i].imageSubresource.mipLevel = 0; bufferImageCopy[i].imageSubresource.baseArrayLayer = 0; diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index 3264daa2b8..586678c2e4 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -31,7 +31,7 @@ struct _GskVulkanRender GskRenderer *renderer; GdkVulkanContext *vulkan; - int scale_factor; + double scale; graphene_rect_t viewport; cairo_region_t *clip; @@ -68,21 +68,21 @@ gsk_vulkan_render_setup (GskVulkanRender *self, const graphene_rect_t *rect, const cairo_region_t *clip) { - GdkSurface *window = gsk_renderer_get_surface (self->renderer); + GdkSurface *surface = gsk_renderer_get_surface (self->renderer); self->target = g_object_ref (target); if (rect) { self->viewport = *rect; - self->scale_factor = 1; + self->scale = 1.0; } else { - self->scale_factor = gdk_surface_get_scale_factor (gsk_renderer_get_surface (self->renderer)); + self->scale = gdk_surface_get_scale (surface); self->viewport = GRAPHENE_RECT_INIT (0, 0, - gdk_surface_get_width (window) * self->scale_factor, - gdk_surface_get_height (window) * self->scale_factor); + (int) ceil (gdk_surface_get_width (surface) * self->scale), + (int) ceil (gdk_surface_get_height (surface) * self->scale)); } if (clip) { @@ -340,12 +340,12 @@ gsk_vulkan_render_add_node (GskVulkanRender *self, GskVulkanRenderPass *pass; graphene_matrix_t mv; - graphene_matrix_init_scale (&mv, self->scale_factor, self->scale_factor, 1.0); + graphene_matrix_init_scale (&mv, self->scale, self->scale, 1.0); pass = gsk_vulkan_render_pass_new (self->vulkan, self->target, - self->scale_factor, - self->scale_factor, + self->scale, + self->scale, &mv, &self->viewport, self->clip, diff --git a/gsk/vulkan/gskvulkanrenderer.c b/gsk/vulkan/gskvulkanrenderer.c index 8f4fa13bf5..71ec47b543 100644 --- a/gsk/vulkan/gskvulkanrenderer.c +++ b/gsk/vulkan/gskvulkanrenderer.c @@ -70,6 +70,55 @@ struct _GskVulkanRendererClass G_DEFINE_TYPE (GskVulkanRenderer, gsk_vulkan_renderer, GSK_TYPE_RENDERER) +static cairo_region_t * +get_render_region (GskVulkanRenderer *self) +{ + const cairo_region_t *damage; + cairo_region_t *render_region; + cairo_region_t *scaled_damage; + GdkRectangle whole_surface; + GdkRectangle extents; + GdkSurface *surface; + double scale; + + render_region = NULL; + surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self->vulkan)); + scale = gdk_surface_get_scale (surface); + + whole_surface.x = 0; + whole_surface.y = 0; + whole_surface.width = gdk_surface_get_width (surface); + whole_surface.height = gdk_surface_get_height (surface); + + damage = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->vulkan)); + scaled_damage = cairo_region_create (); + for (int i = 0; i < cairo_region_num_rectangles (damage); i++) + { + cairo_rectangle_int_t rect; + cairo_region_get_rectangle (damage, i, &rect); + cairo_region_union_rectangle (scaled_damage, &(cairo_rectangle_int_t) { + .x = (int) floor (rect.x * scale), + .y = (int) floor (rect.y * scale), + .width = (int) ceil ((rect.x + rect.width) * scale) - floor (rect.x * scale), + .height = (int) ceil ((rect.y + rect.height) * scale) - floor (rect.y * scale), + }); + } + + if (cairo_region_contains_rectangle (scaled_damage, &whole_surface) == CAIRO_REGION_OVERLAP_IN) + goto out; + + cairo_region_get_extents (scaled_damage, &extents); + if (gdk_rectangle_equal (&extents, &whole_surface)) + goto out; + + render_region = cairo_region_create_rectangle (&extents); + +out: + g_clear_pointer (&scaled_damage, cairo_region_destroy); + + return g_steal_pointer (&render_region); +} + static void gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self) { @@ -89,7 +138,7 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, GskVulkanRenderer *self) { GdkSurface *window; - int scale_factor; + double scale; gsize width, height; guint i; @@ -99,9 +148,9 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, self->targets = g_new (GskVulkanImage *, self->n_targets); window = gsk_renderer_get_surface (GSK_RENDERER (self)); - scale_factor = gdk_surface_get_scale_factor (window); - width = gdk_surface_get_width (window) * scale_factor; - height = gdk_surface_get_height (window) * scale_factor; + scale = gdk_surface_get_scale (window); + width = (int) ceil (gdk_surface_get_width (window) * scale); + height = (int) ceil (gdk_surface_get_height (window) * scale); for (i = 0; i < self->n_targets; i++) { @@ -200,11 +249,8 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer, ceil (viewport->size.height)); gsk_vulkan_render_reset (render, image, viewport, NULL); - gsk_vulkan_render_add_node (render, root); - gsk_vulkan_render_upload (render); - gsk_vulkan_render_draw (render); texture = gsk_vulkan_render_download_target (render); @@ -239,11 +285,12 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); GskVulkanRender *render; - const cairo_region_t *clip; + cairo_region_t *render_region; #ifdef G_ENABLE_DEBUG GskProfiler *profiler; gint64 cpu_time; #endif + uint32_t draw_index; #ifdef G_ENABLE_DEBUG profiler = gsk_renderer_get_profiler (renderer); @@ -256,13 +303,12 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->vulkan), region); render = self->render; - clip = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->vulkan)); - gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)], NULL, clip); + render_region = get_render_region (self); + draw_index = gdk_vulkan_context_get_draw_index (self->vulkan); + gsk_vulkan_render_reset (render, self->targets[draw_index], NULL, render_region); gsk_vulkan_render_add_node (render, root); - gsk_vulkan_render_upload (render); - gsk_vulkan_render_draw (render); #ifdef G_ENABLE_DEBUG @@ -275,6 +321,8 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, #endif gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->vulkan)); + + g_clear_pointer (&render_region, cairo_region_destroy); } static void diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 458d2b1fa4..24432ddd06 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -2258,8 +2258,8 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, 0, 1, &(VkRect2D) { - { rect.x * self->scale_x, rect.y * self->scale_y }, - { rect.width * self->scale_x, rect.height * self->scale_y } + { rect.x, rect.y }, + { rect.width, rect.height } }); vkCmdBeginRenderPass (command_buffer, @@ -2268,8 +2268,8 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, .renderPass = self->render_pass, .framebuffer = gsk_vulkan_render_get_framebuffer (render, self->target), .renderArea = { - { rect.x * self->scale_x, rect.y * self->scale_y }, - { rect.width * self->scale_x, rect.height * self->scale_y } + { rect.x, rect.y }, + { rect.width, rect.height } }, .clearValueCount = 1, .pClearValues = (VkClearValue [1]) { |