Merge branch 'wip/otte/for-main' into 'main'

vulkan: Actually return the preferred memory format

See merge request GNOME/gtk!7713
This commit is contained in:
Benjamin Otte 2024-09-15 08:19:53 +00:00
commit f2e75529cb
10 changed files with 178 additions and 103 deletions

View File

@ -325,6 +325,26 @@ ADD_ALPHA_FUNC(r8g8b8_to_b8g8r8a8, 0, 1, 2, 2, 1, 0, 3)
ADD_ALPHA_FUNC(r8g8b8_to_a8r8g8b8, 0, 1, 2, 1, 2, 3, 0)
ADD_ALPHA_FUNC(r8g8b8_to_a8b8g8r8, 0, 1, 2, 3, 2, 1, 0)
#define SWAP_FUNC(name, R, G, B, A) \
static void \
name (guchar *dest, \
const guchar *src, \
gsize n) \
{ \
for (; n > 0; n--) \
{ \
dest[0] = src[R]; \
dest[1] = src[G]; \
dest[2] = src[B]; \
dest[3] = src[A]; \
dest += 4; \
src += 4; \
} \
}
SWAP_FUNC(r8g8b8a8_to_b8g8r8a8, 2, 1, 0, 3)
SWAP_FUNC(b8g8r8a8_to_r8g8b8a8, 2, 1, 0, 3)
#define MIPMAP_FUNC(SumType, DataType, n_units) \
static void \
gdk_mipmap_ ## DataType ## _ ## n_units ## _nearest (guchar *dest, \
@ -2032,6 +2052,12 @@ get_fast_conversion_func (GdkMemoryFormat dest_format,
return r8g8b8a8_to_a8r8g8b8_premultiplied;
else if (src_format == GDK_MEMORY_B8G8R8A8 && dest_format == GDK_MEMORY_A8R8G8B8_PREMULTIPLIED)
return r8g8b8a8_to_a8b8g8r8_premultiplied;
else if ((src_format == GDK_MEMORY_B8G8R8A8 && dest_format == GDK_MEMORY_R8G8B8A8) ||
(src_format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED))
return b8g8r8a8_to_r8g8b8a8;
else if ((src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_B8G8R8A8) ||
(src_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED && dest_format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED))
return r8g8b8a8_to_b8g8r8a8;
else if (src_format == GDK_MEMORY_R8G8B8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
return r8g8b8_to_r8g8b8a8;
else if (src_format == GDK_MEMORY_B8G8R8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
@ -2092,16 +2118,41 @@ gdk_memory_convert_generic (gpointer data)
gint64 before = GDK_PROFILER_CURRENT_TIME;
gsize rows;
convert_func = gdk_color_state_get_convert_to (mc->src_cs, mc->dest_cs);
if (!convert_func)
convert_func2 = gdk_color_state_get_convert_from (mc->dest_cs, mc->src_cs);
if (!convert_func && !convert_func2)
if (gdk_color_state_equal (mc->src_cs, mc->dest_cs))
{
GdkColorState *connection = GDK_COLOR_STATE_REC2100_LINEAR;
convert_func = gdk_color_state_get_convert_to (mc->src_cs, connection);
convert_func2 = gdk_color_state_get_convert_from (mc->dest_cs, connection);
FastConversionFunc func;
func = get_fast_conversion_func (mc->dest_format, mc->src_format);
if (func != NULL)
{
n = 1;
for (y = g_atomic_int_add (&mc->rows_done, n);
y < mc->height;
y = g_atomic_int_add (&mc->rows_done, n))
{
const guchar *src_data = mc->src_data + y * mc->src_stride;
guchar *dest_data = mc->dest_data + y * mc->dest_stride;
func (dest_data, src_data, mc->width);
}
return;
}
}
else
{
convert_func = gdk_color_state_get_convert_to (mc->src_cs, mc->dest_cs);
if (!convert_func)
convert_func2 = gdk_color_state_get_convert_from (mc->dest_cs, mc->src_cs);
if (!convert_func && !convert_func2)
{
GdkColorState *connection = GDK_COLOR_STATE_REC2100_LINEAR;
convert_func = gdk_color_state_get_convert_to (mc->src_cs, connection);
convert_func2 = gdk_color_state_get_convert_from (mc->dest_cs, connection);
}
}
if (convert_func)
@ -2205,26 +2256,6 @@ gdk_memory_convert (guchar *dest_data,
return;
}
if (gdk_color_state_equal (dest_cs, src_cs))
{
FastConversionFunc func;
func = get_fast_conversion_func (dest_format, src_format);
if (func != NULL)
{
gsize y;
for (y = 0; y < height; y++)
{
func (dest_data, src_data, width);
src_data += src_stride;
dest_data += dest_stride;
}
return;
}
}
gdk_parallel_task_run (gdk_memory_convert_generic, &mc);
}

View File

@ -24,6 +24,7 @@ gsk_gpu_colorize_op_print_instance (GskGpuShaderOp *shader,
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image (string, shader->images[0]);
gsk_gpu_print_rect (string, instance->tex_rect);
gsk_gpu_print_rgba (string, instance->color);
}

View File

@ -95,9 +95,20 @@ gsk_gpu_frame_default_end (GskGpuFrame *self,
gdk_draw_context_end_frame_full (context);
}
static gboolean
gsk_gpu_frame_is_clean (GskGpuFrame *self)
{
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
return gsk_gpu_ops_get_size (&priv->ops) == 0;
}
static void
gsk_gpu_frame_cleanup (GskGpuFrame *self)
{
if (gsk_gpu_frame_is_clean (self))
return;
GSK_GPU_FRAME_GET_CLASS (self)->cleanup (self);
}
@ -615,13 +626,21 @@ gsk_gpu_frame_write_storage_buffer (GskGpuFrame *self,
gboolean
gsk_gpu_frame_is_busy (GskGpuFrame *self)
{
if (gsk_gpu_frame_is_clean (self))
return FALSE;
return GSK_GPU_FRAME_GET_CLASS (self)->is_busy (self);
}
void
gsk_gpu_frame_wait (GskGpuFrame *self)
{
if (gsk_gpu_frame_is_clean (self))
return;
GSK_GPU_FRAME_GET_CLASS (self)->wait (self);
gsk_gpu_frame_cleanup (self);
}
static void

View File

@ -288,26 +288,6 @@ gsk_gpu_node_processor_color_states_explicit (GskGpuNodeProcessor *self,
alt_premultiplied);
}
static void
rect_round_to_pixels (const graphene_rect_t *src,
const graphene_vec2_t *pixel_scale,
const graphene_point_t *pixel_offset,
graphene_rect_t *dest)
{
float x, y, xscale, yscale;
xscale = graphene_vec2_get_x (pixel_scale);
yscale = graphene_vec2_get_y (pixel_scale);
x = floorf ((src->origin.x + pixel_offset->x) * xscale);
y = floorf ((src->origin.y + pixel_offset->y) * yscale);
*dest = GRAPHENE_RECT_INIT (
x / xscale - pixel_offset->x,
y / yscale - pixel_offset->y,
(ceilf ((src->origin.x + pixel_offset->x + src->size.width) * xscale) - x) / xscale,
(ceilf ((src->origin.y + pixel_offset->y + src->size.height) * yscale) - y) / yscale);
}
static GskGpuImage *
gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
GskGpuFrame *frame,
@ -828,7 +808,7 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self,
if (!gsk_rect_intersection (clip_bounds, &node->bounds, &clip))
return NULL;
}
rect_round_to_pixels (&clip, &self->scale, &self->offset, &clip);
gsk_rect_snap_to_grid (&clip, &self->scale, &self->offset, &clip);
return gsk_gpu_get_node_as_image (self->frame,
flags,
@ -866,7 +846,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
if (!gsk_rect_intersection (rect, &clip_rect, &intermediate_rect))
return;
rect_round_to_pixels (&intermediate_rect, &self->scale, &self->offset, &intermediate_rect);
gsk_rect_snap_to_grid (&intermediate_rect, &self->scale, &self->offset, &intermediate_rect);
intermediate = gsk_gpu_node_processor_init_draw (&other,
self->frame,
@ -941,7 +921,7 @@ gsk_gpu_node_processor_add_cairo_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clipped_bounds))
return;
rect_round_to_pixels (&clipped_bounds, &self->scale, &self->offset, &clipped_bounds);
gsk_rect_snap_to_grid (&clipped_bounds, &self->scale, &self->offset, &clipped_bounds);
gsk_gpu_node_processor_sync_globals (self, 0);
@ -1263,7 +1243,7 @@ gsk_gpu_node_processor_add_rounded_clip_node_with_mask (GskGpuNodeProcessor *sel
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
gsk_rect_snap_to_grid (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child_image = gsk_gpu_node_processor_get_node_as_image (self,
0,
@ -2130,7 +2110,7 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip))
return;
rect_round_to_pixels (&clip, &self->scale, &self->offset, &rounded_clip);
gsk_rect_snap_to_grid (&clip, &self->scale, &self->offset, &rounded_clip);
image = gsk_gpu_get_texture_tiles_as_image (self->frame,
self->ccs,
@ -2260,7 +2240,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
gsk_gpu_node_processor_get_clip_bounds (self, &clip_bounds);
/* first round to pixel boundaries, so we make sure the full pixels are covered */
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
gsk_rect_snap_to_grid (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
/* then expand by half a pixel so that pixels needed for eventual linear
* filtering are available */
graphene_rect_inset (&clip_bounds, -0.5, -0.5);
@ -2501,7 +2481,7 @@ gsk_gpu_node_processor_add_gradient_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &bounds))
return;
rect_round_to_pixels (&bounds, &self->scale, &self->offset, &bounds);
gsk_rect_snap_to_grid (&bounds, &self->scale, &self->offset, &bounds);
image = gsk_gpu_node_processor_init_draw (&other,
self->frame,
@ -3429,7 +3409,7 @@ gsk_gpu_node_processor_add_fill_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
gsk_rect_snap_to_grid (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child = gsk_fill_node_get_child (node);
@ -3532,7 +3512,7 @@ gsk_gpu_node_processor_add_stroke_node (GskGpuNodeProcessor *self,
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
return;
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
gsk_rect_snap_to_grid (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
child = gsk_stroke_node_get_child (node);
@ -4378,7 +4358,7 @@ gsk_gpu_node_processor_process (GskGpuFrame *frame,
if (!gsk_gpu_node_processor_clip_node_bounds (&self, node, &clip_bounds))
continue;
rect_round_to_pixels (&clip_bounds, &self.scale, &self.offset, &clip_bounds);
gsk_rect_snap_to_grid (&clip_bounds, &self.scale, &self.offset, &clip_bounds);
image = gsk_gpu_get_node_as_image (self.frame,
0,
ccs,

View File

@ -72,6 +72,42 @@ gsk_gpu_renderer_create_frame (GskGpuRenderer *self)
return result;
}
static GskGpuFrame *
gsk_gpu_renderer_get_frame (GskGpuRenderer *self)
{
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
GskGpuFrame *earliest_frame = NULL;
gint64 earliest_time = G_MAXINT64;
guint i;
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
gint64 timestamp;
if (priv->frames[i] == NULL)
{
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
return priv->frames[i];
}
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
return priv->frames[i];
timestamp = gsk_gpu_frame_get_timestamp (priv->frames[i]);
if (timestamp < earliest_time)
{
earliest_time = timestamp;
earliest_frame = priv->frames[i];
}
}
g_assert (earliest_frame);
gsk_gpu_frame_wait (earliest_frame);
return earliest_frame;
}
static void
gsk_gpu_renderer_dmabuf_downloader_close (GdkDmabufDownloader *downloader)
{
@ -116,7 +152,7 @@ gsk_gpu_renderer_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
gsk_gpu_renderer_make_current (self);
frame = gsk_gpu_renderer_create_frame (self);
frame = gsk_gpu_renderer_get_frame (self);
gsk_gpu_frame_download_texture (frame,
g_get_monotonic_time (),
@ -126,7 +162,7 @@ gsk_gpu_renderer_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
data,
stride);
g_object_unref (frame);
gsk_gpu_frame_wait (frame);
}
static void
@ -164,42 +200,6 @@ get_render_region (GskGpuRenderer *self)
return scaled_damage;
}
static GskGpuFrame *
gsk_gpu_renderer_get_frame (GskGpuRenderer *self)
{
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
GskGpuFrame *earliest_frame = NULL;
gint64 earliest_time = G_MAXINT64;
guint i;
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
gint64 timestamp;
if (priv->frames[i] == NULL)
{
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
return priv->frames[i];
}
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
return priv->frames[i];
timestamp = gsk_gpu_frame_get_timestamp (priv->frames[i]);
if (timestamp < earliest_time)
{
earliest_time = timestamp;
earliest_frame = priv->frames[i];
}
}
g_assert (earliest_frame);
gsk_gpu_frame_wait (earliest_frame);
return earliest_frame;
}
static gboolean
gsk_gpu_renderer_realize (GskRenderer *renderer,
GdkDisplay *display,
@ -313,7 +313,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self,
gsk_gpu_image_get_width (image),
gsk_gpu_image_get_height (image)
});
frame = gsk_gpu_renderer_create_frame (self);
frame = gsk_gpu_renderer_get_frame (self);
gsk_gpu_frame_render (frame,
g_get_monotonic_time (),
image,
@ -325,7 +325,7 @@ gsk_gpu_renderer_fallback_render_texture (GskGpuRenderer *self,
image_width,
image_height),
&texture);
g_object_unref (frame);
gsk_gpu_frame_wait (frame);
g_assert (texture);
gdk_texture_downloader_init (&downloader, texture);
@ -384,7 +384,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer,
else
color_state = GDK_COLOR_STATE_SRGB;
frame = gsk_gpu_renderer_create_frame (self);
frame = gsk_gpu_renderer_get_frame (self);
clip_region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
0, 0,
@ -402,7 +402,7 @@ gsk_gpu_renderer_render_texture (GskRenderer *renderer,
&rounded_viewport,
&texture);
g_object_unref (frame);
gsk_gpu_frame_wait (frame);
g_object_unref (image);
gsk_gpu_device_queue_gc (priv->device);

View File

@ -24,6 +24,7 @@ gsk_gpu_texture_op_print_instance (GskGpuShaderOp *shader,
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image (string, shader->images[0]);
gsk_gpu_print_rect (string, instance->tex_rect);
}
static const GskGpuShaderOpClass GSK_GPU_TEXTURE_OP_CLASS = {

View File

@ -1076,7 +1076,10 @@ gsk_vulkan_device_find_allocator (GskVulkanDevice *self,
found = MIN (i, found);
if ((properties.memoryTypes[i].propertyFlags & desired_flags) == desired_flags)
break;
{
found = i;
break;
}
}
g_assert (found < properties.memoryTypeCount);

View File

@ -115,7 +115,6 @@ gsk_vulkan_frame_setup (GskGpuFrame *frame)
GSK_VK_CHECK (vkCreateFence, vk_device,
&(VkFenceCreateInfo) {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.flags = VK_FENCE_CREATE_SIGNALED_BIT
},
NULL,
&self->vk_fence);

View File

@ -160,6 +160,45 @@ gsk_rect_coverage (const graphene_rect_t *r1,
*res = r;
}
/**
* gsk_rect_snap_to_grid:
* @src: rectangle to snap
* @grid_scale: the scale of the grid
* @grid_offset: the offset of the grid
* @dest: target to snap to. Can be identical to source
*
* Snaps @src to the grid specified by the given scale
* and offset.
* Grid points to snap to will be at the given offset and
* then spaced apart by the inverse of the given scale,
* ie an offset of 0.5 and a scale of 3 will snap to
* (..., 0.1667, 0.5, 0.8333, 1.1667, 1.5, ...).
*
* Snapping is done by growing the rectangle.
*
* Note that floating point rounding issues might result
* in the snapping not being perfectly exact.
**/
static inline void
gsk_rect_snap_to_grid (const graphene_rect_t *src,
const graphene_vec2_t *grid_scale,
const graphene_point_t *grid_offset,
graphene_rect_t *dest)
{
float x, y, xscale, yscale;
xscale = graphene_vec2_get_x (grid_scale);
yscale = graphene_vec2_get_y (grid_scale);
x = floorf ((src->origin.x + grid_offset->x) * xscale);
y = floorf ((src->origin.y + grid_offset->y) * yscale);
*dest = GRAPHENE_RECT_INIT (
x / xscale - grid_offset->x,
y / yscale - grid_offset->y,
(ceilf ((src->origin.x + grid_offset->x + src->size.width) * xscale) - x) / xscale,
(ceilf ((src->origin.y + grid_offset->y + src->size.height) * yscale) - y) / yscale);
}
static inline gboolean G_GNUC_PURE
gsk_rect_is_empty (const graphene_rect_t *rect)
{

View File

@ -62,6 +62,8 @@ benchmark_node (GskRenderNode *node,
gsize stride;
downloader = gdk_texture_downloader_new (texture);
gdk_texture_downloader_set_format (downloader, gdk_texture_get_format (texture));
gdk_texture_downloader_set_color_state (downloader, gdk_texture_get_color_state (texture));
bytes = gdk_texture_downloader_download_bytes (downloader, &stride);
g_bytes_unref (bytes);
gdk_texture_downloader_free (downloader);