[gimp] Issue #3781 - Display artifacts on HiDPI when render cache is invalidated
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Issue #3781 - Display artifacts on HiDPI when render cache is invalidated
- Date: Wed, 11 Sep 2019 18:19:45 +0000 (UTC)
commit d710e96d818f7eb7b7aede0c3fdebe5ab58dbd17
Author: Ell <ell_se yahoo com>
Date: Wed Sep 11 21:00:32 2019 +0300
Issue #3781 - Display artifacts on HiDPI when render cache is invalidated
In GimpDisplayShell, scale the render cache by the window's scale
factor, and render its content in device pixels, instead of scaled
application pixels. When painting the cache to the screen, unscale
the cairo context by the same factor, so that it's painted in the
native resolution. Note that the various
gimp_display_shell_render_foo() functions still speak in
application pixels, and the scaling happens internally in
gimp_display_shell_render().
Aside from rendering at native resolution on HiDPI, this also fixes
an issue where grid-like display artifacts would appear when the
render cache was not fully validated due to the non-native scaling.
app/display/gimpdisplayshell-callbacks.c | 5 +++++
app/display/gimpdisplayshell-draw.c | 14 +++++++-----
app/display/gimpdisplayshell-render.c | 38 +++++++++++++++++++++++++++-----
app/display/gimpdisplayshell-render.h | 5 ++---
app/display/gimpdisplayshell-scroll.c | 13 ++++++-----
app/display/gimpdisplayshell.c | 2 ++
app/display/gimpdisplayshell.h | 2 ++
app/display/gimpimagewindow.c | 31 ++++++++++++++++++++++----
8 files changed, 86 insertions(+), 24 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c
index 4b26715377..25358c8854 100644
--- a/app/display/gimpdisplayshell-callbacks.c
+++ b/app/display/gimpdisplayshell-callbacks.c
@@ -97,6 +97,11 @@ gimp_display_shell_canvas_realize (GtkWidget *canvas,
shell->disp_width = allocation.width;
shell->disp_height = allocation.height;
+ gimp_display_shell_render_set_scale (
+ shell,
+ gdk_window_get_scale_factor (
+ gtk_widget_get_window (gtk_widget_get_toplevel (canvas))));
+
/* set up the scrollbar observers */
g_signal_connect (shell->hsbdata, "value-changed",
G_CALLBACK (gimp_display_shell_hadjustment_changed),
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index 8562c1d928..a6de49e20a 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -163,17 +163,12 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
chunk_width = shell->render_buf_width;
chunk_height = shell->render_buf_height;
-#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
/* multiply the image scale-factor by the window scale-factor, and divide
* the cairo scale-factor by the same amount (further down), so that we make
* full use of the screen resolution, even on hidpi displays.
*/
- scale *=
- gdk_window_get_scale_factor (
- gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell))));
-#endif
+ scale *= shell->render_scale;
- scale = MIN (scale, GIMP_DISPLAY_RENDER_MAX_SCALE);
scale *= MAX (shell->scale_x, shell->scale_y);
if (scale != shell->scale_x)
@@ -221,6 +216,13 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
x1, y1, x2 - x1, y2 - y1);
}
+ /* divide the cairo scale-factor by the window scale-factor, since
+ * the render cache uses device pixels. see comment further up.
+ */
+ cairo_scale (cr,
+ 1.0 / shell->render_scale,
+ 1.0 / shell->render_scale);
+
/* render from the render cache to screen */
cairo_set_source_surface (cr, shell->render_cache, 0, 0);
cairo_paint (cr);
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index f49a8206ef..b650c74b31 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -40,6 +40,28 @@
#include "gimpdisplayshell-render.h"
+#define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1
+#define GIMP_DISPLAY_RENDER_MAX_SCALE 4
+
+
+void
+gimp_display_shell_render_set_scale (GimpDisplayShell *shell,
+ gint scale)
+{
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+#if GIMP_DISPLAY_RENDER_ENABLE_SCALING
+ scale = CLAMP (scale, 1, GIMP_DISPLAY_RENDER_MAX_SCALE);
+
+ if (scale != shell->render_scale)
+ {
+ shell->render_scale = scale;
+
+ gimp_display_shell_render_invalidate_full (shell);
+ }
+#endif
+}
+
void
gimp_display_shell_render_invalidate_full (GimpDisplayShell *shell)
{
@@ -165,6 +187,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
g_return_if_fail (width > 0 && width <= shell->render_buf_width);
g_return_if_fail (height > 0 && height <= shell->render_buf_height);
+ tx *= shell->render_scale;
+ ty *= shell->render_scale;
+ twidth *= shell->render_scale;
+ theight *= shell->render_scale;
+
display_config = shell->display->config;
if (shell->show_all)
@@ -199,11 +226,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
if (! shell->render_cache)
{
- shell->render_cache =
- cairo_surface_create_similar_image (cairo_get_target (cr),
- CAIRO_FORMAT_ARGB32,
- shell->disp_width,
- shell->disp_height);
+ shell->render_cache = cairo_surface_create_similar_image (
+ cairo_get_target (cr),
+ CAIRO_FORMAT_ARGB32,
+ shell->disp_width * shell->render_scale,
+ shell->disp_height * shell->render_scale);
}
if (! shell->render_cache_valid)
@@ -218,6 +245,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
cairo_clip (my_cr);
/* transform to scaled image space, and apply uneven scaling */
+ cairo_scale (my_cr, shell->render_scale, shell->render_scale);
if (shell->rotate_transform)
cairo_transform (my_cr, shell->rotate_transform);
cairo_translate (my_cr, -shell->offset_x, -shell->offset_y);
diff --git a/app/display/gimpdisplayshell-render.h b/app/display/gimpdisplayshell-render.h
index 31898a211e..8cdc89b25a 100644
--- a/app/display/gimpdisplayshell-render.h
+++ b/app/display/gimpdisplayshell-render.h
@@ -19,9 +19,8 @@
#define __GIMP_DISPLAY_SHELL_RENDER_H__
-#define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1
-#define GIMP_DISPLAY_RENDER_MAX_SCALE 4.0
-
+void gimp_display_shell_render_set_scale (GimpDisplayShell *shell,
+ gint scale);
void gimp_display_shell_render_invalidate_full (GimpDisplayShell *shell);
void gimp_display_shell_render_invalidate_area (GimpDisplayShell *shell,
diff --git a/app/display/gimpdisplayshell-scroll.c b/app/display/gimpdisplayshell-scroll.c
index 9e3c4771b2..453574b2f7 100644
--- a/app/display/gimpdisplayshell-scroll.c
+++ b/app/display/gimpdisplayshell-scroll.c
@@ -100,11 +100,11 @@ gimp_display_shell_scroll (GimpDisplayShell *shell,
cairo_surface_t *surface;
cairo_t *cr;
- surface =
- cairo_surface_create_similar_image (shell->render_cache,
- CAIRO_FORMAT_ARGB32,
- shell->disp_width,
- shell->disp_height);
+ surface = cairo_surface_create_similar_image (
+ shell->render_cache,
+ CAIRO_FORMAT_ARGB32,
+ shell->disp_width * shell->render_scale,
+ shell->disp_height * shell->render_scale);
cr = cairo_create (surface);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
@@ -115,7 +115,8 @@ gimp_display_shell_scroll (GimpDisplayShell *shell,
cr = cairo_create (shell->render_cache);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface (cr, surface,
- -x_offset, -y_offset);
+ -x_offset * shell->render_scale,
+ -y_offset * shell->render_scale);
cairo_paint (cr);
cairo_destroy (cr);
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index 31b96a7432..779d1bda91 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -345,6 +345,8 @@ gimp_display_shell_init (GimpDisplayShell *shell)
shell->filter_profile = gimp_babl_get_builtin_color_profile (GIMP_RGB,
GIMP_TRC_NON_LINEAR);
+ shell->render_scale = 1;
+
shell->render_buf_width = 256;
shell->render_buf_height = 256;
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 1abe00a7c1..52df072758 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -171,6 +171,8 @@ struct _GimpDisplayShell
guchar *filter_data; /* filter_buffer's pixels */
gint filter_stride; /* filter_buffer's stride */
+ gint render_scale;
+
cairo_surface_t *render_cache;
cairo_region_t *render_cache_valid;
diff --git a/app/display/gimpimagewindow.c b/app/display/gimpimagewindow.c
index f0493bb3ea..f8d206264c 100644
--- a/app/display/gimpimagewindow.c
+++ b/app/display/gimpimagewindow.c
@@ -71,6 +71,8 @@
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-appearance.h"
#include "gimpdisplayshell-close.h"
+#include "gimpdisplayshell-expose.h"
+#include "gimpdisplayshell-render.h"
#include "gimpdisplayshell-scale.h"
#include "gimpdisplayshell-scroll.h"
#include "gimpdisplayshell-tool-events.h"
@@ -137,6 +139,8 @@ struct _GimpImageWindowPrivate
GdkMonitor *initial_monitor;
+ gint scale_factor;
+
gint suspend_keep_pos;
gint update_ui_manager_idle_id;
@@ -636,10 +640,12 @@ static gboolean
gimp_image_window_configure_event (GtkWidget *widget,
GdkEventConfigure *event)
{
- GimpImageWindow *window = GIMP_IMAGE_WINDOW (widget);
- GtkAllocation allocation;
- gint current_width;
- gint current_height;
+ GimpImageWindow *window = GIMP_IMAGE_WINDOW (widget);
+ GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
+ GtkAllocation allocation;
+ gint current_width;
+ gint current_height;
+ gint scale_factor;
gtk_widget_get_allocation (widget, &allocation);
@@ -664,6 +670,23 @@ gimp_image_window_configure_event (GtkWidget *widget,
shell->size_allocate_from_configure_event = TRUE;
}
+ scale_factor = gdk_window_get_scale_factor (gtk_widget_get_window (widget));
+
+ if (scale_factor != private->scale_factor)
+ {
+ GList *list;
+
+ private->scale_factor = scale_factor;
+
+ for (list = private->shells; list; list = g_list_next (list))
+ {
+ GimpDisplayShell *shell = list->data;
+
+ gimp_display_shell_render_set_scale (shell, scale_factor);
+ gimp_display_shell_expose_full (shell);
+ }
+ }
+
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]