[gimp/gtk3-port: 226/229] app: port projection chunk rendering to a frame clock tick callback



commit 4e49caa65e4f5baae492678f918ec411b3ccbf63
Author: Michael Natterer <mitch gimp org>
Date:   Mon Jul 29 09:12:58 2013 +0200

    app: port projection chunk rendering to a frame clock tick callback

 app/core/gimpprojection.c          |   89 +++++++++++++++++++++++++++++------
 app/core/gimpprojection.h          |   40 ++++++++++++----
 app/display/gimpdisplay-handlers.c |   57 +++++++++++++++++++----
 3 files changed, 151 insertions(+), 35 deletions(-)
---
diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c
index 7708b76..71c12ff 100644
--- a/app/core/gimpprojection.c
+++ b/app/core/gimpprojection.c
@@ -36,10 +36,6 @@
 #include "gimpprojection.h"
 
 
-/*  halfway between G_PRIORITY_HIGH_IDLE and G_PRIORITY_DEFAULT_IDLE  */
-#define GIMP_PROJECTION_IDLE_PRIORITY ((G_PRIORITY_HIGH_IDLE + \
-                                        G_PRIORITY_DEFAULT_IDLE) / 2)
-
 /*  chunk size for one iteration of the chunk renderer  */
 #define GIMP_PROJECTION_CHUNK_WIDTH  256
 #define GIMP_PROJECTION_CHUNK_HEIGHT 128
@@ -84,7 +80,9 @@ static void        gimp_projection_flush_whenever        (GimpProjection  *proj,
                                                           gboolean         now);
 static void        gimp_projection_chunk_render_start    (GimpProjection  *proj);
 static void        gimp_projection_chunk_render_stop     (GimpProjection  *proj);
-static gboolean    gimp_projection_chunk_render_callback (gpointer         data);
+static gboolean    gimp_projection_chunk_render_tick     (gpointer         unused1,
+                                                          gpointer         unused2,
+                                                          GimpProjection  *proj);
 static void        gimp_projection_chunk_render_init     (GimpProjection  *proj);
 static gboolean    gimp_projection_chunk_render_iteration(GimpProjection  *proj);
 static gboolean    gimp_projection_chunk_render_next_area(GimpProjection  *proj);
@@ -172,6 +170,9 @@ gimp_projection_finalize (GObject *object)
   if (proj->chunk_render.running)
     gimp_projection_chunk_render_stop (proj);
 
+  g_list_free (proj->tick_sources);
+  proj->tick_sources = NULL;
+
   gimp_area_list_free (proj->update_areas);
   proj->update_areas = NULL;
 
@@ -388,6 +389,53 @@ gimp_projection_finish_draw (GimpProjection *proj)
     }
 }
 
+void
+gimp_projection_add_tick_source (GimpProjection    *proj,
+                                 GimpObject        *source,
+                                 GimpAddTickFunc    add_func,
+                                 GimpRemoveTickFunc remove_func)
+{
+  g_return_if_fail (GIMP_IS_PROJECTION (proj));
+  g_return_if_fail (GIMP_IS_OBJECT (source));
+  g_return_if_fail (add_func != NULL);
+  g_return_if_fail (remove_func != NULL);
+
+  proj->tick_sources = g_list_append (proj->tick_sources, source);
+
+  /* need only one func strorage, they are the same for all sources */
+  proj->add_tick_func    = add_func;
+  proj->remove_tick_func = remove_func;
+}
+
+void
+gimp_projection_remove_tick_source (GimpProjection *proj,
+                                    GimpObject     *source)
+{
+  gboolean running;
+
+  g_return_if_fail (GIMP_IS_PROJECTION (proj));
+  g_return_if_fail (GIMP_IS_OBJECT (source));
+
+  running = (proj->chunk_render.running &&
+             source == proj->chunk_render_tick_source);
+
+  if (running)
+    gimp_projection_chunk_render_stop (proj);
+
+  proj->tick_sources = g_list_remove (proj->tick_sources, source);
+
+  if (! proj->tick_sources)
+    {
+      proj->add_tick_func    = NULL;
+      proj->remove_tick_func = NULL;
+    }
+
+  if (running && proj->tick_sources)
+    {
+      gimp_projection_chunk_render_start (proj);
+    }
+}
+
 
 /*  private functions  */
 
@@ -489,11 +537,14 @@ static void
 gimp_projection_chunk_render_start (GimpProjection *proj)
 {
   g_return_if_fail (proj->chunk_render.running == FALSE);
+  g_return_if_fail (proj->tick_sources != NULL);
+
+  proj->chunk_render_tick_source = proj->tick_sources->data;
 
-  proj->chunk_render_idle_id =
-    g_idle_add_full (GIMP_PROJECTION_IDLE_PRIORITY,
-                     gimp_projection_chunk_render_callback, proj,
-                     NULL);
+  proj->chunk_render_tick_id =
+    proj->add_tick_func (proj->chunk_render_tick_source,
+                         gimp_projection_chunk_render_tick,
+                         proj);
 
   proj->chunk_render.running = TRUE;
 }
@@ -503,17 +554,20 @@ gimp_projection_chunk_render_stop (GimpProjection *proj)
 {
   g_return_if_fail (proj->chunk_render.running == TRUE);
 
-  g_source_remove (proj->chunk_render_idle_id);
-  proj->chunk_render_idle_id = 0;
+  proj->remove_tick_func (proj->chunk_render_tick_source,
+                          proj->chunk_render_tick_id);
+
+  proj->chunk_render_tick_source = NULL;
+  proj->chunk_render_tick_id     = 0;
 
   proj->chunk_render.running = FALSE;
 }
 
 static gboolean
-gimp_projection_chunk_render_callback (gpointer data)
+gimp_projection_chunk_render_tick (gpointer        unused1,
+                                   gpointer        unused2,
+                                   GimpProjection *proj)
 {
-  GimpProjection *proj = data;
-
   if (! gimp_projection_chunk_render_iteration (proj))
     {
       gimp_projection_chunk_render_stop (proj);
@@ -571,9 +625,12 @@ gimp_projection_chunk_render_init (GimpProjection *proj)
           return;
         }
 
-      gimp_projection_chunk_render_next_area (proj);
+      if (proj->tick_sources)
+        {
+          gimp_projection_chunk_render_next_area (proj);
 
-      gimp_projection_chunk_render_start (proj);
+          gimp_projection_chunk_render_start (proj);
+        }
     }
 }
 
diff --git a/app/core/gimpprojection.h b/app/core/gimpprojection.h
index 1b9b2d8..3c362b4 100644
--- a/app/core/gimpprojection.h
+++ b/app/core/gimpprojection.h
@@ -22,6 +22,16 @@
 #include "gimpobject.h"
 
 
+typedef gboolean (* GimpTickCallback)   (gpointer          unused1,
+                                         gpointer          unused2,
+                                         GimpProjection   *proj);
+typedef guint    (* GimpAddTickFunc)    (GimpObject       *source,
+                                         GimpTickCallback  callback,
+                                         gpointer          user_data);
+typedef void     (* GimpRemoveTickFunc) (GimpObject       *source,
+                                         guint             id);
+
+
 typedef struct _GimpProjectionChunkRender GimpProjectionChunkRender;
 
 struct _GimpProjectionChunkRender
@@ -59,7 +69,12 @@ struct _GimpProjection
 
   GSList                    *update_areas;
   GimpProjectionChunkRender  chunk_render;
-  guint                      chunk_render_idle_id;
+  GimpObject                *chunk_render_tick_source;
+  guint                      chunk_render_tick_id;
+
+  GList                     *tick_sources;
+  GimpAddTickFunc            add_tick_func;
+  GimpRemoveTickFunc         remove_tick_func;
 
   gboolean                   invalidate_preview;
 };
@@ -79,16 +94,23 @@ struct _GimpProjectionClass
 
 GType            gimp_projection_get_type         (void) G_GNUC_CONST;
 
-GimpProjection * gimp_projection_new              (GimpProjectable   *projectable);
+GimpProjection * gimp_projection_new                (GimpProjectable   *projectable);
+
+void             gimp_projection_flush              (GimpProjection    *proj);
+void             gimp_projection_flush_now          (GimpProjection    *proj);
+void             gimp_projection_finish_draw        (GimpProjection    *proj);
 
-void             gimp_projection_flush            (GimpProjection    *proj);
-void             gimp_projection_flush_now        (GimpProjection    *proj);
-void             gimp_projection_finish_draw      (GimpProjection    *proj);
+void             gimp_projection_add_tick_source    (GimpProjection    *proj,
+                                                     GimpObject        *source,
+                                                     GimpAddTickFunc    add_func,
+                                                     GimpRemoveTickFunc remove_func);
+void             gimp_projection_remove_tick_source (GimpProjection    *proj,
+                                                     GimpObject        *source);
 
-gint64           gimp_projection_estimate_memsize (GimpImageBaseType  type,
-                                                   GimpPrecision      precision,
-                                                   gint               width,
-                                                   gint               height);
+gint64           gimp_projection_estimate_memsize   (GimpImageBaseType  type,
+                                                     GimpPrecision      precision,
+                                                     gint               width,
+                                                     gint               height);
 
 
 #endif /*  __GIMP_PROJECTION_H__  */
diff --git a/app/display/gimpdisplay-handlers.c b/app/display/gimpdisplay-handlers.c
index 4539f07..5d92541 100644
--- a/app/display/gimpdisplay-handlers.c
+++ b/app/display/gimpdisplay-handlers.c
@@ -23,23 +23,31 @@
 #include "display-types.h"
 
 #include "core/gimpimage.h"
+#include "core/gimpprojection.h"
 
 #include "gimpdisplay.h"
 #include "gimpdisplay-handlers.h"
+#include "gimpdisplayshell.h"
 
 
 /*  local function prototypes  */
 
-static void   gimp_display_update_handler (GimpProjection *projection,
-                                           gboolean        now,
-                                           gint            x,
-                                           gint            y,
-                                           gint            w,
-                                           gint            h,
-                                           GimpDisplay    *display);
-static void   gimp_display_flush_handler  (GimpImage      *image,
-                                           gboolean        invalidate_preview,
-                                           GimpDisplay    *display);
+static void   gimp_display_update_handler       (GimpProjection   *projection,
+                                                 gboolean          now,
+                                                 gint              x,
+                                                 gint              y,
+                                                 gint              w,
+                                                 gint              h,
+                                                 GimpDisplay      *display);
+static void   gimp_display_flush_handler        (GimpImage        *image,
+                                                 gboolean          invalidate_preview,
+                                                 GimpDisplay      *display);
+
+static guint  gimp_display_add_tick_callback    (GimpObject       *source,
+                                                 GimpTickCallback  callback,
+                                                 gpointer          user_data);
+static void   gimp_display_remove_tick_callback (GimpObject       *source,
+                                                 guint             id);
 
 
 /*  public functions  */
@@ -62,6 +70,11 @@ gimp_display_connect (GimpDisplay *display)
   g_signal_connect (image, "flush",
                     G_CALLBACK (gimp_display_flush_handler),
                     display);
+
+  gimp_projection_add_tick_source (gimp_image_get_projection (image),
+                                   GIMP_OBJECT (display),
+                                   gimp_display_add_tick_callback,
+                                   gimp_display_remove_tick_callback);
 }
 
 void
@@ -75,6 +88,9 @@ gimp_display_disconnect (GimpDisplay *display)
 
   g_return_if_fail (GIMP_IS_IMAGE (image));
 
+  gimp_projection_remove_tick_source (gimp_image_get_projection (image),
+                                      GIMP_OBJECT (display));
+
   g_signal_handlers_disconnect_by_func (image,
                                         gimp_display_flush_handler,
                                         display);
@@ -106,3 +122,24 @@ gimp_display_flush_handler (GimpImage   *image,
 {
   gimp_display_flush (display);
 }
+
+static guint
+gimp_display_add_tick_callback (GimpObject       *source,
+                                GimpTickCallback  callback,
+                                gpointer          user_data)
+{
+  GimpDisplayShell *shell = gimp_display_get_shell (GIMP_DISPLAY (source));
+
+  return gtk_widget_add_tick_callback (shell->canvas,
+                                       (GtkTickCallback) callback,
+                                       user_data, NULL);
+}
+
+static void
+gimp_display_remove_tick_callback (GimpObject *source,
+                                   guint       id)
+{
+  GimpDisplayShell *shell = gimp_display_get_shell (GIMP_DISPLAY (source));
+
+  gtk_widget_remove_tick_callback (shell->canvas, id);
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]