/* This file is part of GEGL
*
* GEGL is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* GEGL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GEGL; if not, see .
*
* Copyright 2003 Calvin Williamson
* 2006 Øyvind Kolås
* 2013 Daniel Sabo
*/
#include "config.h"
#include
#include "gegl.h"
#include "gegl-types-internal.h"
#include "gegl-eval-manager.h"
#include "gegl-instrument.h"
#include "graph/gegl-node-private.h"
#include "process/gegl-graph-traversal.h"
static void gegl_eval_manager_class_init (GeglEvalManagerClass *klass);
static void gegl_eval_manager_init (GeglEvalManager *self);
static void gegl_eval_manager_finalize (GObject *self_object);
G_DEFINE_TYPE (GeglEvalManager, gegl_eval_manager, G_TYPE_OBJECT)
static void
gegl_eval_manager_class_init (GeglEvalManagerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gegl_eval_manager_finalize;
}
static void
gegl_eval_manager_init (GeglEvalManager *self)
{
self->state = INVALID;
self->pad_name = NULL;
self->traversal = NULL;
}
static void
gegl_eval_manager_finalize (GObject *self_object)
{
GeglEvalManager *self = GEGL_EVAL_MANAGER (self_object);
g_free (self->pad_name);
g_clear_pointer (&self->traversal, gegl_graph_free);
g_signal_handlers_disconnect_by_data (self->node, self);
G_OBJECT_CLASS (gegl_eval_manager_parent_class)->finalize (self_object);
}
static gboolean
gegl_eval_manager_change_notification (GObject *gobject,
const GeglRectangle *rect,
gpointer user_data)
{
GeglEvalManager *manager = GEGL_EVAL_MANAGER (user_data);
manager->state = INVALID;
return FALSE;
}
void
gegl_eval_manager_prepare (GeglEvalManager *self)
{
g_return_if_fail (GEGL_IS_EVAL_MANAGER (self));
g_return_if_fail (GEGL_IS_NODE (self->node));
if (self->state != READY)
{
if (!self->traversal)
self->traversal = gegl_graph_build (self->node);
else
gegl_graph_rebuild (self->traversal, self->node);
gegl_graph_prepare (self->traversal);
self->state = READY;
}
}
GeglRectangle
gegl_eval_manager_get_bounding_box (GeglEvalManager *self)
{
gegl_eval_manager_prepare (self);
return gegl_graph_get_bounding_box (self->traversal);
}
GeglBuffer *
gegl_eval_manager_apply (GeglEvalManager *self,
const GeglRectangle *roi,
gint level)
{
GeglBuffer *object;
g_return_val_if_fail (GEGL_IS_EVAL_MANAGER (self), NULL);
g_return_val_if_fail (GEGL_IS_NODE (self->node), NULL);
if (level >= GEGL_CACHE_VALID_MIPMAPS)
level = GEGL_CACHE_VALID_MIPMAPS-1;
GEGL_INSTRUMENT_START();
gegl_eval_manager_prepare (self);
GEGL_INSTRUMENT_END ("gegl", "prepare-graph");
GEGL_INSTRUMENT_START();
gegl_graph_prepare_request (self->traversal, roi, level);
GEGL_INSTRUMENT_END ("gegl", "prepare-request");
GEGL_INSTRUMENT_START();
object = gegl_graph_process (self->traversal, level);
GEGL_INSTRUMENT_END ("gegl", "process");
return object;
}
GeglEvalManager * gegl_eval_manager_new (GeglNode *node,
const gchar *pad_name)
{
GeglEvalManager *self = g_object_new (GEGL_TYPE_EVAL_MANAGER, NULL);
g_assert (GEGL_IS_NODE (node));
/* FIXME: This should be a weakref */
self->node = node;
if (pad_name)
self->pad_name = g_strdup (pad_name);
else
self->pad_name = g_strdup ("output");
g_signal_connect (G_OBJECT (self->node), "invalidated",
G_CALLBACK (gegl_eval_manager_change_notification),
self);
return self;
}