summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte.benjamin@googlemail.com>2023-04-03 14:27:24 +0000
committerBenjamin Otte <otte.benjamin@googlemail.com>2023-04-03 14:27:24 +0000
commit362bdaa8526bbf4892c1781d33d92eb3c2203163 (patch)
tree34786718f3a84cc8fd73b0eb4f2af498505a78f6
parent79b0e594cd21c75209aab973b17ced3788a21bfe (diff)
parent5c27a0dd2bd2a1ea15e583b4447f6160d7079814 (diff)
downloadgtk+-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.c19
-rw-r--r--gsk/vulkan/gskvulkanbuffer.c2
-rw-r--r--gsk/vulkan/gskvulkanglyphcache.c4
-rw-r--r--gsk/vulkan/gskvulkanimage.c7
-rw-r--r--gsk/vulkan/gskvulkanrender.c18
-rw-r--r--gsk/vulkan/gskvulkanrenderer.c72
-rw-r--r--gsk/vulkan/gskvulkanrenderpass.c8
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]) {