diff --git a/gdk/gdkmemoryformat.c b/gdk/gdkmemoryformat.c index 01b1859224..ff9072345d 100644 --- a/gdk/gdkmemoryformat.c +++ b/gdk/gdkmemoryformat.c @@ -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); } diff --git a/gsk/gpu/gskgpucolorizeop.c b/gsk/gpu/gskgpucolorizeop.c index cef2a1b507..ebaace467c 100644 --- a/gsk/gpu/gskgpucolorizeop.c +++ b/gsk/gpu/gskgpucolorizeop.c @@ -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); } diff --git a/gsk/gpu/gskgpuframe.c b/gsk/gpu/gskgpuframe.c index 9fab9e537f..28e27f0acd 100644 --- a/gsk/gpu/gskgpuframe.c +++ b/gsk/gpu/gskgpuframe.c @@ -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 diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 40b4844155..49702a7762 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -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, diff --git a/gsk/gpu/gskgpurenderer.c b/gsk/gpu/gskgpurenderer.c index d6a8d1ead5..205d9dbf0e 100644 --- a/gsk/gpu/gskgpurenderer.c +++ b/gsk/gpu/gskgpurenderer.c @@ -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); diff --git a/gsk/gpu/gskgputextureop.c b/gsk/gpu/gskgputextureop.c index ed5db59e77..01ff7c743d 100644 --- a/gsk/gpu/gskgputextureop.c +++ b/gsk/gpu/gskgputextureop.c @@ -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 = { diff --git a/gsk/gpu/gskvulkandevice.c b/gsk/gpu/gskvulkandevice.c index 9cea4d2748..352321a4fd 100644 --- a/gsk/gpu/gskvulkandevice.c +++ b/gsk/gpu/gskvulkandevice.c @@ -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); diff --git a/gsk/gpu/gskvulkanframe.c b/gsk/gpu/gskvulkanframe.c index f15abb8e7e..cdce76fa46 100644 --- a/gsk/gpu/gskvulkanframe.c +++ b/gsk/gpu/gskvulkanframe.c @@ -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); diff --git a/gsk/gskrectprivate.h b/gsk/gskrectprivate.h index 1c07b2a63d..a20b1e6da3 100644 --- a/gsk/gskrectprivate.h +++ b/gsk/gskrectprivate.h @@ -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) { diff --git a/tools/gtk-rendernode-tool-benchmark.c b/tools/gtk-rendernode-tool-benchmark.c index f7c5654f09..fe4b88c81c 100644 --- a/tools/gtk-rendernode-tool-benchmark.c +++ b/tools/gtk-rendernode-tool-benchmark.c @@ -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);