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