[gimp] app: make display update much faster again
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: make display update much faster again
- Date: Tue, 16 Jul 2019 15:21:26 +0000 (UTC)
commit 9aa6aa1f040e6476a1e047b09d6c0403cdb8f344
Author: Michael Natterer <mitch gimp org>
Date: Mon Jul 15 23:24:35 2019 +0200
app: make display update much faster again
Introduce a render cache that keeps the result of scaling, color
management, display filters and shell mask (for tools like fuzzy
select).
Change gimpdisplayshell-render.[ch] to only render to the cache and
manage a cairo region of the cache's valid area. Call cache
invalidation functions form various places. Change the API of all
render functions to be in display coordinates.
Also get rid of gimpdisplayxfer.[ch] because we now have a
canvas-sized cairo surface which is a surface similar to the
destination surface.
app/display/Makefile.am | 2 -
app/display/gimpdisplay.c | 3 +
app/display/gimpdisplayshell-callbacks.c | 34 +++-
app/display/gimpdisplayshell-draw.c | 53 ++----
app/display/gimpdisplayshell-filter.c | 1 +
app/display/gimpdisplayshell-handlers.c | 4 +
app/display/gimpdisplayshell-profile.c | 5 +-
app/display/gimpdisplayshell-render.c | 258 +++++++++++++++++++-------
app/display/gimpdisplayshell-render.h | 39 +++-
app/display/gimpdisplayshell-rotate.c | 3 +
app/display/gimpdisplayshell-scale.c | 2 +
app/display/gimpdisplayshell-scroll.c | 41 +++++
app/display/gimpdisplayshell.c | 12 +-
app/display/gimpdisplayshell.h | 8 +-
app/display/gimpdisplayxfer.c | 300 -------------------------------
app/display/gimpdisplayxfer.h | 37 ----
16 files changed, 346 insertions(+), 456 deletions(-)
---
diff --git a/app/display/Makefile.am b/app/display/Makefile.am
index eda865265d..4429f84478 100644
--- a/app/display/Makefile.am
+++ b/app/display/Makefile.am
@@ -156,8 +156,6 @@ libappdisplay_a_sources = \
gimpdisplayshell-transform.h \
gimpdisplayshell-utils.c \
gimpdisplayshell-utils.h \
- gimpdisplayxfer.c \
- gimpdisplayxfer.h \
gimpimagewindow.c \
gimpimagewindow.h \
gimpmotionbuffer.c \
diff --git a/app/display/gimpdisplay.c b/app/display/gimpdisplay.c
index 709f95f09a..1c2914c343 100644
--- a/app/display/gimpdisplay.c
+++ b/app/display/gimpdisplay.c
@@ -44,6 +44,7 @@
#include "gimpdisplayshell-expose.h"
#include "gimpdisplayshell-handlers.h"
#include "gimpdisplayshell-icon.h"
+#include "gimpdisplayshell-render.h"
#include "gimpdisplayshell-transform.h"
#include "gimpimagewindow.h"
@@ -897,4 +898,6 @@ gimp_display_paint_area (GimpDisplay *display,
y2 = ceil ((gdouble) y2 / PAINT_AREA_CHUNK_HEIGHT) * PAINT_AREA_CHUNK_HEIGHT;
gimp_display_shell_expose_area (shell, x1, y1, x2 - x1, y2 - y1);
+
+ gimp_display_shell_render_invalidate_area (shell, x1, y1, x2 - x1, y2 - y1);
}
diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c
index e567563c6a..7b2e281a29 100644
--- a/app/display/gimpdisplayshell-callbacks.c
+++ b/app/display/gimpdisplayshell-callbacks.c
@@ -38,12 +38,12 @@
#include "gimpdisplayshell-appearance.h"
#include "gimpdisplayshell-callbacks.h"
#include "gimpdisplayshell-draw.h"
+#include "gimpdisplayshell-render.h"
#include "gimpdisplayshell-scale.h"
#include "gimpdisplayshell-scroll.h"
#include "gimpdisplayshell-scrollbars.h"
#include "gimpdisplayshell-selection.h"
#include "gimpdisplayshell-title.h"
-#include "gimpdisplayxfer.h"
#include "gimpimagewindow.h"
#include "gimpnavigationeditor.h"
@@ -80,9 +80,10 @@ void
gimp_display_shell_canvas_realize (GtkWidget *canvas,
GimpDisplayShell *shell)
{
- GimpCanvasPaddingMode padding_mode;
- GimpRGB padding_color;
- GtkAllocation allocation;
+ GimpCanvasPaddingMode padding_mode;
+ GimpRGB padding_color;
+ GtkAllocation allocation;
+ const gchar *env;
gtk_widget_grab_focus (canvas);
@@ -115,7 +116,27 @@ gimp_display_shell_canvas_realize (GtkWidget *canvas,
/* allow shrinking */
gtk_widget_set_size_request (GTK_WIDGET (shell), 0, 0);
- shell->xfer = gimp_display_xfer_realize (GTK_WIDGET(shell));
+ shell->render_buf_width = 256;
+ shell->render_buf_height = 256;
+
+ env = g_getenv ("GIMP_DISPLAY_RENDER_BUF_SIZE");
+
+ if (env)
+ {
+ gint width = atoi (env);
+ gint height = width;
+
+ env = strchr (env, 'x');
+ if (env)
+ height = atoi (env + 1);
+
+ if (width > 0 && width <= 8192 &&
+ height > 0 && height <= 8192)
+ {
+ shell->render_buf_width = width;
+ shell->render_buf_height = height;
+ }
+ }
}
static gboolean
@@ -130,6 +151,9 @@ gimp_display_shell_canvas_tick (GtkWidget *widget,
if ((shell->disp_width != allocation.width) ||
(shell->disp_height != allocation.height))
{
+ g_clear_pointer (&shell->render_cache, cairo_surface_destroy);
+ gimp_display_shell_render_invalidate_full (shell);
+
if (shell->zoom_on_resize &&
shell->disp_width > 64 &&
shell->disp_height > 64 &&
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index 654828016c..ccc14005eb 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -32,17 +32,10 @@
#include "gimpcanvas.h"
#include "gimpcanvas-style.h"
-#include "gimpcanvaspath.h"
#include "gimpdisplay.h"
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-draw.h"
#include "gimpdisplayshell-render.h"
-#include "gimpdisplayshell-scale.h"
-#include "gimpdisplayshell-transform.h"
-#include "gimpdisplayxfer.h"
-
-
-#define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1
/* public functions */
@@ -157,8 +150,8 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
* chunk size as necessary, to accommodate for the display
* transform and window scale factor.
*/
- chunk_width = GIMP_DISPLAY_RENDER_BUF_WIDTH;
- chunk_height = GIMP_DISPLAY_RENDER_BUF_HEIGHT;
+ 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
@@ -197,23 +190,8 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
for (c = 0; c < n_cols; c++)
{
- gint x1 = x + (2 * c * w + n_cols) / (2 * n_cols);
- gint x2 = x + (2 * (c + 1) * w + n_cols) / (2 * n_cols);
- gdouble ix1, iy1;
- gdouble ix2, iy2;
- gint ix, iy;
- gint iw, ih;
-
- /* map chunk from screen space to scaled image space */
- gimp_display_shell_untransform_bounds_with_scale (
- shell, scale,
- x1, y1, x2, y2,
- &ix1, &iy1, &ix2, &iy2);
-
- ix = floor (ix1);
- iy = floor (iy1);
- iw = ceil (ix2) - ix;
- ih = ceil (iy2) - iy;
+ gint x1 = x + (2 * c * w + n_cols) / (2 * n_cols);
+ gint x2 = x + (2 * (c + 1) * w + n_cols) / (2 * n_cols);
cairo_save (cr);
@@ -221,14 +199,21 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
cairo_rectangle (cr, x1, y1, x2 - x1, y2 - y1);
cairo_clip (cr);
- /* transform to scaled image space, and apply uneven scaling */
- if (shell->rotate_transform)
- cairo_transform (cr, shell->rotate_transform);
- cairo_translate (cr, -shell->offset_x, -shell->offset_y);
- cairo_scale (cr, shell->scale_x / scale, shell->scale_y / scale);
-
- /* render image */
- gimp_display_shell_render (shell, cr, ix, iy, iw, ih, scale);
+ if (! gimp_display_shell_render_is_valid (shell,
+ x1, y1, x2 - x1, y2 - y1))
+ {
+ /* render image to the render cache */
+ gimp_display_shell_render (shell, cr,
+ x1, y1, x2 - x1, y2 - y1,
+ scale);
+
+ gimp_display_shell_render_validate_area (shell,
+ x1, y1, x2 - x1, y2 - y1);
+ }
+
+ /* render from the render cache to screen */
+ cairo_set_source_surface (cr, shell->render_cache, 0, 0);
+ cairo_paint (cr);
cairo_restore (cr);
diff --git a/app/display/gimpdisplayshell-filter.c b/app/display/gimpdisplayshell-filter.c
index 3992238fb9..ad482820aa 100644
--- a/app/display/gimpdisplayshell-filter.c
+++ b/app/display/gimpdisplayshell-filter.c
@@ -139,6 +139,7 @@ gimp_display_shell_filter_changed_idle (gpointer data)
gimp_display_shell_profile_update (shell);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
shell->filter_idle_id = 0;
diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c
index 9d7be6f76a..d3bac52f1c 100644
--- a/app/display/gimpdisplayshell-handlers.c
+++ b/app/display/gimpdisplayshell-handlers.c
@@ -61,6 +61,7 @@
#include "gimpdisplayshell-handlers.h"
#include "gimpdisplayshell-icon.h"
#include "gimpdisplayshell-profile.h"
+#include "gimpdisplayshell-render.h"
#include "gimpdisplayshell-rulers.h"
#include "gimpdisplayshell-scale.h"
#include "gimpdisplayshell-scroll.h"
@@ -840,6 +841,7 @@ gimp_display_shell_size_changed_detailed_handler (GimpImage *image,
gimp_display_shell_scroll_clamp_and_update (shell);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
}
}
@@ -1048,6 +1050,7 @@ gimp_display_shell_monitor_res_notify_handler (GObject *config,
gimp_display_shell_scaled (shell);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
}
}
@@ -1121,6 +1124,7 @@ gimp_display_shell_quality_notify_handler (GObject *config,
GimpDisplayShell *shell)
{
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
}
static void
diff --git a/app/display/gimpdisplayshell-profile.c b/app/display/gimpdisplayshell-profile.c
index 57f290a04a..df6c4b144b 100644
--- a/app/display/gimpdisplayshell-profile.c
+++ b/app/display/gimpdisplayshell-profile.c
@@ -40,7 +40,6 @@
#include "gimpdisplayshell-actions.h"
#include "gimpdisplayshell-filter.h"
#include "gimpdisplayshell-profile.h"
-#include "gimpdisplayxfer.h"
#include "gimp-intl.h"
@@ -159,8 +158,8 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
if (shell->filter_transform || shell->profile_transform)
{
- gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH;
- gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT;
+ gint w = shell->render_buf_width;
+ gint h = shell->render_buf_height;
shell->profile_data =
gegl_malloc (w * h * babl_format_get_bytes_per_pixel (src_format));
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index 0470d7b73f..7d0ea1af4a 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -28,9 +28,6 @@
#include "config/gimpdisplayconfig.h"
-#include "gegl/gimp-gegl-utils.h"
-
-#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
#include "core/gimppickable.h"
#include "core/gimpprojectable.h"
@@ -41,38 +38,129 @@
#include "gimpdisplayshell-filter.h"
#include "gimpdisplayshell-profile.h"
#include "gimpdisplayshell-render.h"
-#include "gimpdisplayshell-scroll.h"
-#include "gimpdisplayxfer.h"
+void
+gimp_display_shell_render_invalidate_full (GimpDisplayShell *shell)
+{
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+ g_clear_pointer (&shell->render_cache_valid, cairo_region_destroy);
+}
+
+void
+gimp_display_shell_render_invalidate_area (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+ if (shell->render_cache_valid)
+ {
+ cairo_rectangle_int_t rect;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ cairo_region_subtract_rectangle (shell->render_cache_valid, &rect);
+ }
+}
+
+void
+gimp_display_shell_render_validate_area (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+ if (shell->render_cache_valid)
+ {
+ cairo_rectangle_int_t rect;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ cairo_region_union_rectangle (shell->render_cache_valid, &rect);
+ }
+}
+
+gboolean
+gimp_display_shell_render_is_valid (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ if (shell->render_cache_valid)
+ {
+ cairo_rectangle_int_t rect;
+ cairo_region_overlap_t overlap;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ overlap = cairo_region_contains_rectangle (shell->render_cache_valid,
+ &rect);
+
+ return (overlap == CAIRO_REGION_OVERLAP_IN);
+ }
+
+ return FALSE;
+}
+
void
gimp_display_shell_render (GimpDisplayShell *shell,
cairo_t *cr,
- gint x,
- gint y,
- gint w,
- gint h,
+ gint tx,
+ gint ty,
+ gint twidth,
+ gint theight,
gdouble scale)
{
- GimpImage *image;
- GeglBuffer *buffer;
+ GimpImage *image;
+ GeglBuffer *buffer;
#ifdef USE_NODE_BLIT
- GeglNode *node;
+ GeglNode *node;
#endif
- cairo_surface_t *xfer;
- gint xfer_src_x;
- gint xfer_src_y;
- gint mask_src_x = 0;
- gint mask_src_y = 0;
- gint cairo_stride;
- guchar *cairo_data;
+ cairo_t *my_cr;
+ gint cairo_stride;
+ guchar *cairo_data;
+ gdouble x1, y1;
+ gdouble x2, y2;
+ gint x;
+ gint y;
+ gint width;
+ gint height;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
g_return_if_fail (cr != NULL);
- g_return_if_fail (w > 0 && w <= GIMP_DISPLAY_RENDER_BUF_WIDTH);
- g_return_if_fail (h > 0 && h <= GIMP_DISPLAY_RENDER_BUF_HEIGHT);
g_return_if_fail (scale > 0.0);
+ /* map chunk from screen space to scaled image space */
+ gimp_display_shell_untransform_bounds_with_scale (shell, scale,
+ tx, ty,
+ tx + twidth, ty + theight,
+ &x1, &y1,
+ &x2, &y2);
+
+ x = floor (x1);
+ y = floor (y1);
+ width = ceil (x2) - x;
+ height = ceil (y2) - y;
+
+ g_return_if_fail (width > 0 && width <= shell->render_buf_width);
+ g_return_if_fail (height > 0 && height <= shell->render_buf_height);
+
image = gimp_display_get_image (shell->display);
buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image));
#ifdef USE_NODE_BLIT
@@ -81,12 +169,45 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gimp_projectable_begin_render (GIMP_PROJECTABLE (image));
#endif
- xfer = gimp_display_xfer_get_surface (shell->xfer, w, h,
- &xfer_src_x, &xfer_src_y);
+ if (! shell->render_surface)
+ {
+ shell->render_surface =
+ cairo_surface_create_similar_image (cairo_get_target (cr),
+ CAIRO_FORMAT_ARGB32,
+ shell->render_buf_width,
+ shell->render_buf_height);
+ }
- cairo_stride = cairo_image_surface_get_stride (xfer);
- cairo_data = cairo_image_surface_get_data (xfer) +
- xfer_src_y * cairo_stride + xfer_src_x * 4;
+ cairo_surface_flush (shell->render_surface);
+
+ 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);
+ }
+
+ if (! shell->render_cache_valid)
+ {
+ shell->render_cache_valid = cairo_region_create ();
+ }
+
+ my_cr = cairo_create (shell->render_cache);
+
+ /* clip to chunk bounds, in screen space */
+ cairo_rectangle (my_cr, tx, ty, twidth, theight);
+ cairo_clip (my_cr);
+
+ /* transform to scaled image space, and apply uneven scaling */
+ if (shell->rotate_transform)
+ cairo_transform (my_cr, shell->rotate_transform);
+ cairo_translate (my_cr, -shell->offset_x, -shell->offset_y);
+ cairo_scale (my_cr, shell->scale_x / scale, shell->scale_y / scale);
+
+ cairo_stride = cairo_image_surface_get_stride (shell->render_surface);
+ cairo_data = cairo_image_surface_get_data (shell->render_surface);
if (shell->profile_transform ||
gimp_display_shell_has_filter (shell))
@@ -105,8 +226,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
! shell->filter_buffer)
{
- gint fw = GIMP_DISPLAY_RENDER_BUF_WIDTH;
- gint fh = GIMP_DISPLAY_RENDER_BUF_HEIGHT;
+ gint fw = shell->render_buf_width;
+ gint fh = shell->render_buf_height;
shell->filter_data =
gegl_malloc (fw * fh *
@@ -131,13 +252,13 @@ gimp_display_shell_render (GimpDisplayShell *shell,
*/
#ifndef USE_NODE_BLIT
gegl_buffer_get (buffer,
- GEGL_RECTANGLE (x, y, w, h), scale,
+ GEGL_RECTANGLE (x, y, width, height), scale,
gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
shell->profile_data, shell->profile_stride,
GEGL_ABYSS_CLAMP);
#else
gegl_node_blit (node,
- scale, GEGL_RECTANGLE (x, y, w, h),
+ scale, GEGL_RECTANGLE (x, y, width, height),
gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
shell->profile_data, shell->profile_stride,
GEGL_BLIT_CACHE);
@@ -149,13 +270,13 @@ gimp_display_shell_render (GimpDisplayShell *shell,
*/
#ifndef USE_NODE_BLIT
gegl_buffer_get (buffer,
- GEGL_RECTANGLE (x, y, w, h), scale,
+ GEGL_RECTANGLE (x, y, width, height), scale,
shell->filter_format,
shell->filter_data, shell->filter_stride,
GEGL_ABYSS_CLAMP);
#else
gegl_node_blit (node,
- scale, GEGL_RECTANGLE (x, y, w, h),
+ scale, GEGL_RECTANGLE (x, y, width, height),
shell->filter_format,
shell->filter_data, shell->filter_stride,
GEGL_BLIT_CACHE);
@@ -169,9 +290,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
{
gimp_color_transform_process_buffer (shell->filter_transform,
shell->profile_buffer,
- GEGL_RECTANGLE (0, 0, w, h),
+ GEGL_RECTANGLE (0, 0,
+ width, height),
shell->filter_buffer,
- GEGL_RECTANGLE (0, 0, w, h));
+ GEGL_RECTANGLE (0, 0,
+ width, height));
}
/* if there are filters, apply them
@@ -194,7 +317,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
*/
gimp_color_display_stack_convert_buffer (shell->filter_stack,
filter_buffer,
- GEGL_RECTANGLE (x, y, w, h));
+ GEGL_RECTANGLE (x, y,
+ width, height));
g_object_unref (filter_buffer);
}
@@ -210,9 +334,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
*/
gimp_color_transform_process_buffer (shell->profile_transform,
shell->filter_buffer,
- GEGL_RECTANGLE (0, 0, w, h),
+ GEGL_RECTANGLE (0, 0,
+ width, height),
shell->filter_buffer,
- GEGL_RECTANGLE (0, 0, w, h));
+ GEGL_RECTANGLE (0, 0,
+ width, height));
}
else if (! can_convert_to_u8)
{
@@ -221,16 +347,19 @@ gimp_display_shell_render (GimpDisplayShell *shell,
*/
gimp_color_transform_process_buffer (shell->profile_transform,
shell->profile_buffer,
- GEGL_RECTANGLE (0, 0, w, h),
+ GEGL_RECTANGLE (0, 0,
+ width, height),
shell->filter_buffer,
- GEGL_RECTANGLE (0, 0, w, h));
+ GEGL_RECTANGLE (0, 0,
+ width, height));
}
else
{
GeglBuffer *buffer =
gegl_buffer_linear_new_from_data (cairo_data,
babl_format ("cairo-ARGB32"),
- GEGL_RECTANGLE (0, 0, w, h),
+ GEGL_RECTANGLE (0, 0,
+ width, height),
cairo_stride,
NULL, NULL);
@@ -239,9 +368,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
*/
gimp_color_transform_process_buffer (shell->profile_transform,
shell->profile_buffer,
- GEGL_RECTANGLE (0, 0, w, h),
+ GEGL_RECTANGLE (0, 0,
+ width, height),
buffer,
- GEGL_RECTANGLE (0, 0, w, h));
+ GEGL_RECTANGLE (0, 0,
+ width, height));
g_object_unref (buffer);
}
}
@@ -252,7 +383,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
{
gegl_buffer_get (shell->filter_buffer,
- GEGL_RECTANGLE (0, 0, w, h), 1.0,
+ GEGL_RECTANGLE (0, 0, width, height), 1.0,
babl_format ("cairo-ARGB32"),
cairo_data, cairo_stride,
GEGL_ABYSS_CLAMP);
@@ -265,13 +396,13 @@ gimp_display_shell_render (GimpDisplayShell *shell,
*/
#ifndef USE_NODE_BLIT
gegl_buffer_get (buffer,
- GEGL_RECTANGLE (x, y, w, h), scale,
+ GEGL_RECTANGLE (x, y, width, height), scale,
babl_format ("cairo-ARGB32"),
cairo_data, cairo_stride,
GEGL_ABYSS_CLAMP);
#else
gegl_node_blit (node,
- scale, GEGL_RECTANGLE (x, y, w, h),
+ scale, GEGL_RECTANGLE (x, y, width, height),
babl_format ("cairo-ARGB32"),
cairo_data, cairo_stride,
GEGL_BLIT_CACHE);
@@ -282,26 +413,30 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gimp_projectable_end_render (GIMP_PROJECTABLE (image));
#endif
+ cairo_surface_mark_dirty (shell->render_surface);
+
+ cairo_set_source_surface (my_cr, shell->render_surface, x, y);
+ cairo_paint (my_cr);
+
if (shell->mask)
{
if (! shell->mask_surface)
{
shell->mask_surface =
cairo_image_surface_create (CAIRO_FORMAT_A8,
- GIMP_DISPLAY_RENDER_BUF_WIDTH,
- GIMP_DISPLAY_RENDER_BUF_HEIGHT);
+ shell->render_buf_width,
+ shell->render_buf_height);
}
- cairo_surface_mark_dirty (shell->mask_surface);
+ cairo_surface_flush (shell->mask_surface);
cairo_stride = cairo_image_surface_get_stride (shell->mask_surface);
- cairo_data = cairo_image_surface_get_data (shell->mask_surface) +
- mask_src_y * cairo_stride + mask_src_x;
+ cairo_data = cairo_image_surface_get_data (shell->mask_surface);
gegl_buffer_get (shell->mask,
GEGL_RECTANGLE (x - floor (shell->mask_offset_x * scale),
y - floor (shell->mask_offset_y * scale),
- w, h),
+ width, height),
scale,
babl_format ("Y u8"),
cairo_data, cairo_stride,
@@ -309,11 +444,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
if (shell->mask_inverted)
{
- gint mask_height = h;
+ gint mask_height = height;
while (mask_height--)
{
- gint mask_width = w;
+ gint mask_width = width;
guchar *d = cairo_data;
while (mask_width--)
@@ -326,19 +461,12 @@ gimp_display_shell_render (GimpDisplayShell *shell,
cairo_data += cairo_stride;
}
}
- }
- /* put it to the screen */
- cairo_set_source_surface (cr, xfer,
- x - xfer_src_x,
- y - xfer_src_y);
- cairo_paint (cr);
+ cairo_surface_mark_dirty (shell->mask_surface);
- if (shell->mask)
- {
- gimp_cairo_set_source_rgba (cr, &shell->mask_color);
- cairo_mask_surface (cr, shell->mask_surface,
- x - mask_src_x,
- y - mask_src_y);
+ gimp_cairo_set_source_rgba (my_cr, &shell->mask_color);
+ cairo_mask_surface (my_cr, shell->mask_surface, x, y);
}
+
+ cairo_destroy (my_cr);
}
diff --git a/app/display/gimpdisplayshell-render.h b/app/display/gimpdisplayshell-render.h
index 7b4a644cfb..31898a211e 100644
--- a/app/display/gimpdisplayshell-render.h
+++ b/app/display/gimpdisplayshell-render.h
@@ -18,12 +18,37 @@
#ifndef __GIMP_DISPLAY_SHELL_RENDER_H__
#define __GIMP_DISPLAY_SHELL_RENDER_H__
-void gimp_display_shell_render (GimpDisplayShell *shell,
- cairo_t *cr,
- gint x,
- gint y,
- gint w,
- gint h,
- gdouble scale);
+
+#define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1
+#define GIMP_DISPLAY_RENDER_MAX_SCALE 4.0
+
+
+void gimp_display_shell_render_invalidate_full (GimpDisplayShell *shell);
+void gimp_display_shell_render_invalidate_area (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+void gimp_display_shell_render_validate_area (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+gboolean gimp_display_shell_render_is_valid (GimpDisplayShell *shell,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+void gimp_display_shell_render (GimpDisplayShell *shell,
+ cairo_t *cr,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gdouble scale);
+
#endif /* __GIMP_DISPLAY_SHELL_RENDER_H__ */
diff --git a/app/display/gimpdisplayshell-rotate.c b/app/display/gimpdisplayshell-rotate.c
index dd9ed6940f..59e71c1134 100644
--- a/app/display/gimpdisplayshell-rotate.c
+++ b/app/display/gimpdisplayshell-rotate.c
@@ -29,6 +29,7 @@
#include "gimpdisplay.h"
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-expose.h"
+#include "gimpdisplayshell-render.h"
#include "gimpdisplayshell-rotate.h"
#include "gimpdisplayshell-scale.h"
#include "gimpdisplayshell-scroll.h"
@@ -84,6 +85,7 @@ gimp_display_shell_flip (GimpDisplayShell *shell,
gimp_display_shell_restore_viewport_center (shell, cx, cy);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
}
}
@@ -121,6 +123,7 @@ gimp_display_shell_rotate_to (GimpDisplayShell *shell,
gimp_display_shell_restore_viewport_center (shell, cx, cy);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
}
void
diff --git a/app/display/gimpdisplayshell-scale.c b/app/display/gimpdisplayshell-scale.c
index 73811e664e..dec74fb885 100644
--- a/app/display/gimpdisplayshell-scale.c
+++ b/app/display/gimpdisplayshell-scale.c
@@ -36,6 +36,7 @@
#include "gimpdisplay.h"
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-expose.h"
+#include "gimpdisplayshell-render.h"
#include "gimpdisplayshell-rotate.h"
#include "gimpdisplayshell-scale.h"
#include "gimpdisplayshell-scroll.h"
@@ -719,6 +720,7 @@ gimp_display_shell_scale_resize (GimpDisplayShell *shell,
gimp_display_shell_scaled (shell);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
/* re-enable the active tool */
gimp_display_shell_resume (shell);
diff --git a/app/display/gimpdisplayshell-scroll.c b/app/display/gimpdisplayshell-scroll.c
index 1987d5d9a4..d120f4c2ab 100644
--- a/app/display/gimpdisplayshell-scroll.c
+++ b/app/display/gimpdisplayshell-scroll.c
@@ -36,6 +36,7 @@
#include "gimpdisplay-foreach.h"
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-expose.h"
+#include "gimpdisplayshell-render.h"
#include "gimpdisplayshell-rotate.h"
#include "gimpdisplayshell-rulers.h"
#include "gimpdisplayshell-scale.h"
@@ -94,6 +95,45 @@ gimp_display_shell_scroll (GimpDisplayShell *shell,
gimp_overlay_box_scroll (GIMP_OVERLAY_BOX (shell->canvas),
-x_offset, -y_offset);
+ if (shell->render_cache)
+ {
+ 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);
+
+ cr = cairo_create (surface);
+ cairo_set_source_surface (cr, shell->render_cache, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ cr = cairo_create (shell->render_cache);
+ cairo_set_source_surface (cr, surface,
+ -x_offset, -y_offset);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ cairo_surface_destroy (surface);
+ }
+
+ if (shell->render_cache_valid)
+ {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_translate (shell->render_cache_valid,
+ -x_offset, -y_offset);
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = shell->disp_width;
+ rect.height = shell->disp_height;
+
+ cairo_region_intersect_rectangle (shell->render_cache_valid, &rect);
+ }
}
/* re-enable the active tool */
@@ -137,6 +177,7 @@ gimp_display_shell_scroll_set_offset (GimpDisplayShell *shell,
gimp_display_shell_scrolled (shell);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
/* re-enable the active tool */
gimp_display_shell_resume (shell);
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index b029487787..a1075cb66f 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -723,8 +723,12 @@ gimp_display_shell_dispose (GObject *object)
shell->filter_idle_id = 0;
}
- g_clear_pointer (&shell->mask_surface, cairo_surface_destroy);
- g_clear_pointer (&shell->checkerboard, cairo_pattern_destroy);
+ g_clear_pointer (&shell->render_cache, cairo_surface_destroy);
+ g_clear_pointer (&shell->render_cache_valid, cairo_region_destroy);
+
+ g_clear_pointer (&shell->render_surface, cairo_surface_destroy);
+ g_clear_pointer (&shell->mask_surface, cairo_surface_destroy);
+ g_clear_pointer (&shell->checkerboard, cairo_pattern_destroy);
gimp_display_shell_profile_finalize (shell);
@@ -1032,6 +1036,7 @@ gimp_display_shell_profile_changed (GimpColorManaged *managed)
gimp_display_shell_profile_update (shell);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
}
static void
@@ -1312,6 +1317,7 @@ gimp_display_shell_reconnect (GimpDisplayShell *shell)
gimp_display_shell_scaled (shell);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
}
static gboolean
@@ -1377,6 +1383,7 @@ gimp_display_shell_empty (GimpDisplayShell *shell)
gimp_display_shell_rotate_update_transform (shell);
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
user_context = gimp_get_user_context (shell->display->gimp);
@@ -1867,4 +1874,5 @@ gimp_display_shell_set_mask (GimpDisplayShell *shell,
shell->mask_inverted = inverted;
gimp_display_shell_expose_full (shell);
+ gimp_display_shell_render_invalidate_full (shell);
}
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index a96f67aa76..00176344aa 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -166,7 +166,13 @@ struct _GimpDisplayShell
guchar *filter_data; /* filter_buffer's pixels */
gint filter_stride; /* filter_buffer's stride */
- GimpDisplayXfer *xfer; /* manages image buffer transfers */
+ cairo_surface_t *render_cache;
+ cairo_region_t *render_cache_valid;
+
+ gint render_buf_width;
+ gint render_buf_height;
+
+ cairo_surface_t *render_surface; /* buffer for rendering the mask */
cairo_surface_t *mask_surface; /* buffer for rendering the mask */
cairo_pattern_t *checkerboard; /* checkerboard pattern */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]