[gegl] bin: make ui renderer of GEGL configurable



commit f14e4b1f78fe067b43b63af10cb9e3306bd30423
Author: Øyvind Kolås <pippin gimp org>
Date:   Sat Dec 22 01:12:10 2018 +0100

    bin: make ui renderer of GEGL configurable
    
    To permit testing various code paths for chains there is now 4 values
    that are recognized for the environment variable GEGL_RENDERER
    
    blit           causes blitting and rendering on demand
    blit-mipmap    causes blitting and rendering on demand with mipmap previews for zoom
    idle           use a GeglProcessor in an idle to do rendering
    thread         use a GeglProcessor in a separate thread to do rendering

 bin/gegl.c |   7 ++-
 bin/ui.c   | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 143 insertions(+), 10 deletions(-)
---
diff --git a/bin/gegl.c b/bin/gegl.c
index 8d9c10cb4..d117d7c6b 100644
--- a/bin/gegl.c
+++ b/bin/gegl.c
@@ -106,7 +106,12 @@ main (gint    argc,
   gchar       *path_root = NULL;
 
 #if HAVE_MRG
-  g_setenv ("GEGL_MIPMAP_RENDERING", "1", TRUE);
+  const gchar *renderer = g_getenv ("GEGL_RENDERER");
+  if (renderer && ( !strcmp (renderer, "blit-mipmap") ||
+                    !strcmp (renderer, "mipmap")))
+    g_setenv ("GEGL_MIPMAP_RENDERING", "1", TRUE);
+
+
 #endif
 
   g_object_set (gegl_config (),
diff --git a/bin/ui.c b/bin/ui.c
index c62d44073..13f844ec9 100644
--- a/bin/ui.c
+++ b/bin/ui.c
@@ -66,6 +66,16 @@ void mrg_gegl_buffer_blit (Mrg *mrg,
 
 static int audio_started = 0;
 
+enum {
+  GEGL_RENDERER_BLIT = 0,
+  GEGL_RENDERER_BLIT_MIPMAP,
+  GEGL_RENDERER_THREAD,
+  GEGL_RENDERER_IDLE,
+  //GEGL_RENDERER_IDLE_MIPMAP,
+  //GEGL_RENDERER_THREAD_MIPMAP,
+};
+static int renderer = GEGL_RENDERER_BLIT;
+
 /*  this structure contains the full application state, and is what
  *  re-renderings of the UI is directly based on.
  */
@@ -84,6 +94,13 @@ struct _State {
   GeglNode   *save;
   GeglNode   *active;
   GeglNode   *rotate;
+  GThread    *thread;
+
+  GeglNode      *processor_node; /* the node we have a processor for */
+  GeglProcessor *processor;
+  GeglBuffer    *processor_buffer;
+  int            renderer_state;
+  int            renderer_dirty;
   int         rev;
   float       u, v;
   float       scale;
@@ -96,6 +113,7 @@ struct _State {
   float       slide_pause;
   int         slide_enabled;
   int         slide_timeout;
+
   GeglNode   *gegl_decode;
   GeglNode   *decode_load;
   GeglNode   *decode_store;
@@ -275,11 +293,78 @@ static void end_audio (void)
 {
 }
 
+static gboolean renderer_task (gpointer data)
+{
+  State *o = data;
+  static gdouble progress = 0.0;
+  void *old_processor = o->processor;
+  GeglBuffer *old_buffer = o->processor_buffer;
+  switch (o->renderer_state)
+  {
+    case 0:
+      if (o->renderer_dirty > 0)
+      {
+      o->renderer_dirty = 0; // do it early - permitting async reset
+      if (o->processor_node != o->sink)
+      {
+        o->processor = gegl_node_new_processor (o->sink, NULL);
+        o->processor_buffer = g_object_ref (gegl_processor_get_buffer (o->processor));
+        if (old_buffer)
+          g_object_unref (old_buffer);
+        if (old_processor)
+          g_object_unref (old_processor);
+
+        gegl_processor_set_rectangle (o->processor, NULL);
+      }
+      o->renderer_state = 1;
+      }
+      //break; // fallthrough
+    case 1:
+
+       if (gegl_processor_work (o->processor, &progress))
+         o->renderer_state = 1;
+       else
+         o->renderer_state = 2;
+      break;
+    case 2:
+      o->renderer_state = 0;
+      break;
+  }
+  return TRUE;
+}
+
+static int has_quit = 0;
+static gpointer renderer_thread (gpointer data)
+{
+  State *o = data;
+  while (!has_quit)
+  {
+    int state = o->renderer_state;
+    renderer_task (data);
+    if (state == 2 && o->renderer_dirty == 0)
+      g_usleep (40000);
+  }
+  return 0;
+}
+
+
+
 int mrg_ui_main (int argc, char **argv, char **ops)
 {
   Mrg *mrg = mrg_new (1024, 768, NULL);
+  const char *renderer_env = g_getenv ("GEGL_RENDERER");
+
   State o = {NULL,};
 
+  if (renderer_env)
+  {
+    if (!strcmp (renderer_env, "blit")) renderer = GEGL_RENDERER_BLIT;
+    if (!strcmp (renderer_env, "blit-mipmap")) renderer = GEGL_RENDERER_BLIT_MIPMAP;
+    if (!strcmp (renderer_env, "mipmap")) renderer = GEGL_RENDERER_BLIT_MIPMAP;
+    if (!strcmp (renderer_env, "thread")) renderer = GEGL_RENDERER_THREAD;
+    if (!strcmp (renderer_env, "idle")) renderer = GEGL_RENDERER_IDLE;
+  }
+
   mrg_set_title (mrg, "GEGL");
 /* we want to see the speed gotten if the fastest babl conversions we have were more accurate */
   //g_setenv ("BABL_TOLERANCE", "0.1", TRUE);
@@ -311,9 +396,32 @@ int mrg_ui_main (int argc, char **argv, char **ops)
   if (o.ops)
     o.active = gegl_node_get_producer (o.sink, "input", NULL);
 
+  o.renderer_dirty = 1;
+
+
+  switch (renderer)
+  {
+    case GEGL_RENDERER_THREAD:
+      o.thread = g_thread_new ("renderer", renderer_thread, &o);
+      break;
+    case GEGL_RENDERER_IDLE:
+      g_idle_add (renderer_task, &o);
+      break;
+    case GEGL_RENDERER_BLIT:
+    case GEGL_RENDERER_BLIT_MIPMAP:
+      break;
+  }
+
+
   mrg_main (mrg);
+  has_quit = 1;
+  if (renderer == GEGL_RENDERER_THREAD)
+    g_thread_join (o.thread);
+
 
-  g_object_unref (o.gegl);
+  g_clear_object (&o.gegl);
+  g_clear_object (&o.processor);
+  g_clear_object (&o.processor_buffer);
   g_clear_object (&o.buffer);
   gegl_exit ();
 
@@ -999,14 +1107,34 @@ static void gegl_ui (Mrg *mrg, void *data)
 {
   State *o = data;
 
-
-  mrg_gegl_blit (mrg,
-                 0, 0,
-                 mrg_width (mrg), mrg_height (mrg),
-                 o->sink,
-                 o->u, o->v,
-                 o->scale,
-                 o->render_quality);
+  switch (renderer)
+  {
+     case GEGL_RENDERER_BLIT:
+     case GEGL_RENDERER_BLIT_MIPMAP:
+       mrg_gegl_blit (mrg,
+                      0, 0,
+                      mrg_width (mrg), mrg_height (mrg),
+                      o->sink,
+                      o->u, o->v,
+                      o->scale,
+                      o->render_quality);
+     break;
+     case GEGL_RENDERER_THREAD:
+     case GEGL_RENDERER_IDLE:
+       if (o->processor_buffer)
+       {
+         GeglBuffer *buffer = g_object_ref (o->processor_buffer);
+         mrg_gegl_buffer_blit (mrg,
+                               0, 0,
+                               mrg_width (mrg), mrg_height (mrg),
+                               buffer,
+                               o->u, o->v,
+                               o->scale,
+                               o->render_quality);
+                               g_object_unref (buffer);
+       }
+       break;
+  }
 
   if (g_str_has_suffix (o->path, ".gif") ||
       g_str_has_suffix (o->path, ".GIF"))


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