GList *
gegl_graph_get_connected_output_contexts (GeglGraphTraversal *path,
                                          GeglPad            *output_pad)
{
  GList *result = NULL;
  GSList *targets = gegl_pad_get_connections (output_pad);
  GSList *targets_iter;
  for (targets_iter = targets; targets_iter; targets_iter = g_slist_next (targets_iter))
    {
      GeglNode *target_node = gegl_connection_get_sink_node (targets_iter->data);
      GeglOperationContext *target_context = g_hash_table_lookup (path->contexts, target_node);
      
      /* Only include this target if it's part of the current path */
      if (target_context)
        {
          const gchar *target_pad_name = gegl_pad_get_name (gegl_connection_get_sink_pad (targets_iter->data));
          
          ContextConnection *result_element = g_new0 (ContextConnection, 1);
          result_element->name    = target_pad_name;
          result_element->context = target_context;
          
          result = g_list_prepend (result, result_element);
        }
    }
  return result;
}
void
layer_add_gegl_node(GeglEditorLayer* layer, GeglNode* node)
{
  //get input pads
  //gegl_pad_is_output
  GSList	*pads	    = gegl_node_get_input_pads(node);
  guint		 num_inputs = g_slist_length(pads);
  gchar**	 inputs	    = malloc(sizeof(gchar*)*num_inputs);
  int		 i;
  for(i = 0; pads != NULL; pads = pads->next, i++)
    {
      inputs[i] = (gchar*)gegl_pad_get_name(pads->data);
    }

  gint	id;
  if(gegl_node_get_pad(node, "output") == NULL)
    {
      id = gegl_editor_add_node(layer->editor, gegl_node_get_operation(node), num_inputs, inputs, 0, NULL);
    }
  else
    {
      gchar*	output = "output";
      gchar* outputs[] = {output};
      id	       = gegl_editor_add_node(layer->editor, gegl_node_get_operation(node), num_inputs, inputs, 1, outputs);
    }

  node_id_pair* new_pair = malloc(sizeof(node_id_pair));
  new_pair->node	 = node;
  new_pair->id		 = id;
  layer->pairs		 = g_slist_append(layer->pairs, new_pair);
}
Beispiel #3
0
void
gegl_dot_util_add_connection (GString        *string,
                              GeglConnection *connection)
{
  GeglNode *source;
  GeglNode *sink;
  GeglPad  *source_pad;
  GeglPad  *sink_pad;

  source     = gegl_connection_get_source_node (connection);
  sink       = gegl_connection_get_sink_node (connection);
  source_pad = gegl_connection_get_source_pad (connection);
  sink_pad   = gegl_connection_get_sink_pad (connection);

  g_string_append_printf (string, "op_%p:%s -> op_%p:%s;\n",
                          source, gegl_pad_get_name (source_pad),
                          sink,   gegl_pad_get_name (sink_pad));
}
void
gegl_node_disconnect_all_pads(GeglNode* node)
{
  GSList* list;
  for(list = gegl_node_get_pads(node); list != NULL; list = list->next)
    {
      if(gegl_pad_is_input(list->data)) //disconnect inputs
	{
	  gegl_node_disconnect(node, (gchar*)gegl_pad_get_name(list->data));
	}
      else if(gegl_pad_is_output(list->data)) //disconnect outputs
	{
	  GeglNode** nodes;
	  const gchar** pads;
	  gint num_consumers = gegl_node_get_consumers(node, gegl_pad_get_name(list->data), &nodes, &pads);
	  gint i;
	  for(i = 0; i < num_consumers; i++)
	    {
	      gegl_node_disconnect(nodes[i], pads[i]);
	    }
	}
    }
}
Beispiel #5
0
/* this is the visitor that does the real computations for GEGL */
static void
gegl_eval_visitor_visit_pad (GeglVisitor *self,
                             GeglPad     *pad)
{
  GeglNode        *node       = gegl_pad_get_node (pad);
  gpointer         context_id = self->context_id;
  GeglOperationContext *context    = gegl_node_get_context (node, context_id);
  GeglOperation   *operation  = node->operation;

  GEGL_VISITOR_CLASS (gegl_eval_visitor_parent_class)->visit_pad (self, pad);

  if (gegl_pad_is_output (pad))
    {
      /* processing only really happens for output pads */
      if (context->cached)
        {
          GEGL_NOTE (GEGL_DEBUG_PROCESS, "Using cache for pad '%s' on \"%s\"", gegl_pad_get_name (pad), gegl_node_get_debug_name (node));
          gegl_operation_context_set_object (context,
                                             gegl_pad_get_name (pad),
                                             G_OBJECT (node->cache));
        }
      else
        {
          glong time      = gegl_ticks ();

          /* Make the operation do it's actual processing */
          GEGL_NOTE (GEGL_DEBUG_PROCESS, "For \"%s\" processing pad '%s' result_rect = %d, %d %d×%d",
                     gegl_pad_get_name (pad), gegl_node_get_debug_name (node),
                     context->result_rect.x, context->result_rect.y, context->result_rect.width, context->result_rect.height);
          gegl_operation_process (operation, context, gegl_pad_get_name (pad),
                                  &context->result_rect);
          time      = gegl_ticks () - time;

          gegl_instrument ("process", gegl_node_get_operation (node), time);

          if (gegl_pad_get_num_connections (pad) > 1)
            {
              /* Mark buffers that have been consumed by different parts of the
               * graph so that in-place processing can be avoided on them.
               */
              GValue *value;
              GeglBuffer *buffer;
              value = gegl_operation_context_get_value (context, gegl_pad_get_name (pad));
              if (value)
                {
                  buffer = g_value_get_object (value);
                  if (buffer)
                    gegl_object_set_has_forked (buffer);
                }
            }
        }
    }
  else if (gegl_pad_is_input (pad))
    {
      GeglPad *source_pad = gegl_pad_get_connected_to (pad);

      /* the work needed to be done on input pads is to set the
       * data from the corresponding output pad it is connected to
       */
      if (source_pad)
        {
          GValue           value          = { 0 };
          GParamSpec      *prop_spec      = gegl_pad_get_param_spec (pad);
          GeglNode        *source_node    = gegl_pad_get_node (source_pad);
          GeglOperationContext *source_context = gegl_node_get_context (source_node, context_id);

          g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));

          gegl_operation_context_get_property (source_context,
                                          gegl_pad_get_name (source_pad),
                                          &value);

          if (!g_value_get_object (&value) &&
              !g_object_get_data (G_OBJECT (source_node), "graph"))
            g_warning ("eval-visitor encountered a NULL buffer passed from: %s.%s-[%p]",
                       gegl_node_get_debug_name (source_node),
                       gegl_pad_get_name (source_pad),
                       g_value_get_object (&value));

          gegl_operation_context_set_property (context,
                                          gegl_pad_get_name (pad),
                                          &value);
          /* reference counting for this source dropped to zero, freeing up */
          if (-- gegl_node_get_context (
                     gegl_pad_get_node (source_pad), context_id)->refs == 0 &&
              g_value_get_object (&value))
            {
              gegl_operation_context_remove_property (
                 gegl_node_get_context (
                    gegl_pad_get_node (source_pad), context_id),
                    gegl_pad_get_name (source_pad));
            }

          g_value_unset (&value);

	  /* processing for sink operations that accepts partial consumption
             and thus probably are being processed by the processor from the
             this very operation.
           */
          if (GEGL_IS_OPERATION_SINK (operation) &&
              !gegl_operation_sink_needs_full (operation))
            {
              GEGL_NOTE (GEGL_DEBUG_PROCESS, "Processing pad '%s' on \"%s\"", gegl_pad_get_name (pad), gegl_node_get_debug_name (node));
              gegl_operation_process (operation, context, "output",
                &context->result_rect);
            }
        }
    }
}
Beispiel #6
0
void
gegl_dot_util_add_node (GString  *string,
                        GeglNode *node)
{
  g_string_append_printf (string, "op_%p [fontsize=\"10\" label=\"", node);

  /* We build the record from top to bottom */
  g_string_append_printf (string, "{");

  /* The first row is a list of output pads */
  {
    GSList  *pads       = gegl_node_get_pads (node);
    GSList  *entry      = pads;
    gboolean got_output = FALSE;

    g_string_append_printf (string, "{");

    while (entry)
      {
        GeglPad *pad = entry->data;
        if (gegl_pad_is_output (pad))
          {
            if (got_output)
              {
                g_string_append (string, "|");
              }
            got_output = TRUE;
            g_string_append_printf (string, "<%s>%s",
                                    gegl_pad_get_name (pad),
                                    gegl_pad_get_name (pad));
          }
        entry = g_slist_next (entry);
      }

    g_string_append_printf (string, "}|");
  }

  /* The second row is the operation name such as gegl:translate */
  g_string_append_printf (string, "%s |", gegl_node_get_debug_name (node));

  /* The next rows are property names and their values */
  if (1)
    {
      guint        n_properties;
      GParamSpec **properties = gegl_operation_list_properties (gegl_node_get_operation (node), &n_properties);
      guint        i;
      for (i = 0; i < n_properties; i++)
        {
          const gchar *name   = properties[i]->name;
          GValue       tvalue = { 0, };
          GValue       svalue = { 0, };

          if (properties[i]->value_type == GEGL_TYPE_BUFFER)
            continue;

          g_value_init (&svalue, G_TYPE_STRING);
          g_value_init (&tvalue, properties[i]->value_type);

          gegl_node_get_property (node, name, &tvalue);

          if (g_value_transform (&tvalue, &svalue))
            {
              gchar *sval = g_value_dup_string (&svalue);
              if (sval && strlen (sval) > 30)
                {
                  sval[28] = '.';
                  sval[29] = '.';
                  sval[30] = '\0';
                }
              if (sval)
                {
                  g_string_append_printf (string, "%s=%s | ", name, sval);
                  g_free (sval);
                }
              g_value_unset (&svalue);
            }
          g_value_unset (&tvalue);
        }
      g_free (properties);
    }

  /* The last row is input pads */
  {
    GSList  *pads      = gegl_node_get_pads (node);
    GSList  *entry     = pads;
    gboolean got_input = FALSE;

    g_string_append_printf (string, "{");

    while (entry)
      {
        GeglPad *pad = entry->data;
        if (gegl_pad_is_input (pad))
          {
            if (got_input)
              {
                g_string_append (string, "|");
              }
            got_input = TRUE;
            g_string_append_printf (string, "<%s>%s",
                                    gegl_pad_get_name (pad),
                                    gegl_pad_get_name (pad));
          }
        entry = g_slist_next (entry);
      }

    g_string_append_printf (string, "}");
  }

  g_string_append_printf (string, "}\"");
  g_string_append_printf (string, "shape=\"record\"];\n");
}
void
gegl_graph_prepare_request (GeglGraphTraversal  *path,
                            const GeglRectangle *request_roi,
                            gint                 level)
{
  GList *list_iter = NULL;
  static const GeglRectangle empty_rect = {0, 0, 0, 0};

  g_return_if_fail (path->bfs_path);

  if (path->rects_dirty)
    {
      /* Zero all the needs rects so we can intersect with them below */
      for (list_iter = path->bfs_path; list_iter; list_iter = list_iter->next)
        {
          GeglNode *node = GEGL_NODE (list_iter->data);
          GeglOperationContext *context = g_hash_table_lookup (path->contexts, node);

          /* We only need to reset the need rect, result will always get overwritten */
          gegl_operation_context_set_need_rect (context, &empty_rect);

          /* Reset cached status, because the rect we need may have changed */
          context->cached = FALSE;
        }
    }

  path->rects_dirty = TRUE;

  {
    /* Prep the first node */
    GeglNode *node = GEGL_NODE (path->bfs_path->data);
    GeglOperationContext *context = g_hash_table_lookup (path->contexts, node);
    GeglRectangle new_need;

    g_return_if_fail (context);

    gegl_rectangle_intersect (&new_need, &node->have_rect, request_roi);

    gegl_operation_context_set_need_rect (context, &new_need);
    gegl_operation_context_set_result_rect (context, &new_need);
  }
  
  /* Iterate over all the nodes and propagate the requested rectangle */
  for (list_iter = path->bfs_path; list_iter; list_iter = list_iter->next)
    {
      GeglNode             *node      = GEGL_NODE (list_iter->data);
      GeglOperation        *operation = node->operation;
      GeglOperationContext *context;
      GeglRectangle        *request;
      GSList               *input_pads;
      
      context = g_hash_table_lookup (path->contexts, node);
      g_return_if_fail (context);
      
      request = gegl_operation_context_get_need_rect (context);

      if (request->width == 0 || request->height == 0)
        {
          gegl_operation_context_set_result_rect (context, &empty_rect);
          continue;
        }
      
      if (node->cache)
        {
          gint i;
          for (i = level; i >=0 && !context->cached; i--)
          {
            if (gegl_region_rect_in (node->cache->valid_region[level], request) == GEGL_OVERLAP_RECTANGLE_IN)
            {
              /* This node is cached and the cache fulfills our need rect */
              context->cached = TRUE;
              gegl_operation_context_set_result_rect (context, &empty_rect);
            }
          }
          if (context->cached)
            continue;
        }

      {
        /* Expand request if the operation has a minimum processing requirement */
        GeglRectangle full_request = gegl_operation_get_cached_region (operation, request);

        gegl_operation_context_set_need_rect (context, &full_request);

        /* FIXME: We could trim this down based on the cache, instead of being all or nothing */
        gegl_operation_context_set_result_rect (context, request);

        for (input_pads = node->input_pads; input_pads; input_pads = input_pads->next)
          {
            GeglPad *source_pad = gegl_pad_get_connected_to (input_pads->data);

            if (source_pad)
              {
                GeglNode             *source_node    = gegl_pad_get_node (source_pad);
                GeglOperationContext *source_context = g_hash_table_lookup (path->contexts, source_node);
                const gchar          *pad_name       = gegl_pad_get_name (input_pads->data);

                GeglRectangle rect, current_need, new_need;

                /* Combine this need rect with any existing request */
                rect = gegl_operation_get_required_for_output (operation, pad_name, &full_request);
                current_need = *gegl_operation_context_get_need_rect (source_context);

                gegl_rectangle_bounding_box (&new_need, &rect, &current_need);

                /* Limit request to the nodes output */
                gegl_rectangle_intersect (&new_need, &source_node->have_rect, &new_need);

                gegl_operation_context_set_need_rect (source_context, &new_need);
              }
          }
      }
    }
}