1 /* This file is part of GEGL
2  *
3  * GEGL is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 3 of the License, or (at your option) any later version.
7  *
8  * GEGL is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
15  *
16  * Copyright 2003 Calvin Williamson
17  *           2006 Øyvind Kolås
18  *           2013 Daniel Sabo
19  */
20 
21 #include "config.h"
22 
23 #include <glib-object.h>
24 
25 #include "gegl.h"
26 #include "gegl-types-internal.h"
27 #include "gegl-eval-manager.h"
28 #include "gegl-instrument.h"
29 
30 #include "graph/gegl-node-private.h"
31 
32 #include "process/gegl-graph-traversal.h"
33 
34 static void gegl_eval_manager_class_init (GeglEvalManagerClass *klass);
35 static void gegl_eval_manager_init (GeglEvalManager *self);
36 static void gegl_eval_manager_finalize (GObject *self_object);
37 
G_DEFINE_TYPE(GeglEvalManager,gegl_eval_manager,G_TYPE_OBJECT)38 G_DEFINE_TYPE (GeglEvalManager, gegl_eval_manager, G_TYPE_OBJECT)
39 
40 static void
41 gegl_eval_manager_class_init (GeglEvalManagerClass *klass)
42 {
43   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
44 
45   gobject_class->finalize = gegl_eval_manager_finalize;
46 }
47 
48 static void
gegl_eval_manager_init(GeglEvalManager * self)49 gegl_eval_manager_init (GeglEvalManager *self)
50 {
51   self->state     = INVALID;
52   self->pad_name  = NULL;
53   self->traversal = NULL;
54 }
55 
56 static void
gegl_eval_manager_finalize(GObject * self_object)57 gegl_eval_manager_finalize (GObject *self_object)
58 {
59   GeglEvalManager *self = GEGL_EVAL_MANAGER (self_object);
60 
61   g_free (self->pad_name);
62   g_clear_pointer (&self->traversal, gegl_graph_free);
63 
64   g_signal_handlers_disconnect_by_data (self->node, self);
65 
66   G_OBJECT_CLASS (gegl_eval_manager_parent_class)->finalize (self_object);
67 }
68 
69 static gboolean
gegl_eval_manager_change_notification(GObject * gobject,const GeglRectangle * rect,gpointer user_data)70 gegl_eval_manager_change_notification (GObject             *gobject,
71                                        const GeglRectangle *rect,
72                                        gpointer             user_data)
73 {
74   GeglEvalManager *manager = GEGL_EVAL_MANAGER (user_data);
75   manager->state = INVALID;
76 
77   return FALSE;
78 }
79 
80 void
gegl_eval_manager_prepare(GeglEvalManager * self)81 gegl_eval_manager_prepare (GeglEvalManager *self)
82 {
83   g_return_if_fail (GEGL_IS_EVAL_MANAGER (self));
84   g_return_if_fail (GEGL_IS_NODE (self->node));
85 
86   if (self->state != READY)
87     {
88       if (!self->traversal)
89         self->traversal = gegl_graph_build (self->node);
90       else
91         gegl_graph_rebuild (self->traversal, self->node);
92 
93       gegl_graph_prepare (self->traversal);
94 
95       self->state = READY;
96     }
97 }
98 
99 GeglRectangle
gegl_eval_manager_get_bounding_box(GeglEvalManager * self)100 gegl_eval_manager_get_bounding_box (GeglEvalManager     *self)
101 {
102   gegl_eval_manager_prepare (self);
103   return gegl_graph_get_bounding_box (self->traversal);
104 }
105 
106 GeglBuffer *
gegl_eval_manager_apply(GeglEvalManager * self,const GeglRectangle * roi,gint level)107 gegl_eval_manager_apply (GeglEvalManager     *self,
108                          const GeglRectangle *roi,
109                          gint                 level)
110 {
111   GeglBuffer  *object;
112 
113   g_return_val_if_fail (GEGL_IS_EVAL_MANAGER (self), NULL);
114   g_return_val_if_fail (GEGL_IS_NODE (self->node), NULL);
115 
116   if (level >= GEGL_CACHE_VALID_MIPMAPS)
117     level = GEGL_CACHE_VALID_MIPMAPS-1;
118 
119   GEGL_INSTRUMENT_START();
120   gegl_eval_manager_prepare (self);
121   GEGL_INSTRUMENT_END ("gegl", "prepare-graph");
122 
123   GEGL_INSTRUMENT_START();
124   gegl_graph_prepare_request (self->traversal, roi, level);
125   GEGL_INSTRUMENT_END ("gegl", "prepare-request");
126 
127   GEGL_INSTRUMENT_START();
128   object = gegl_graph_process (self->traversal, level);
129   GEGL_INSTRUMENT_END ("gegl", "process");
130 
131   return object;
132 }
133 
gegl_eval_manager_new(GeglNode * node,const gchar * pad_name)134 GeglEvalManager * gegl_eval_manager_new     (GeglNode    *node,
135                                              const gchar *pad_name)
136 {
137   GeglEvalManager *self = g_object_new (GEGL_TYPE_EVAL_MANAGER, NULL);
138 
139   g_assert (GEGL_IS_NODE (node));
140 
141   /* FIXME: This should be a weakref */
142   self->node = node;
143 
144   if (pad_name)
145     self->pad_name = g_strdup (pad_name);
146   else
147     self->pad_name = g_strdup ("output");
148 
149   g_signal_connect (G_OBJECT (self->node), "invalidated",
150                     G_CALLBACK (gegl_eval_manager_change_notification),
151                     self);
152   return self;
153 }
154