GeglPad * gegl_pad_get_connected_to (GeglPad *self) { GeglPad *pad = NULL; g_return_val_if_fail (GEGL_IS_PAD (self), NULL); if (gegl_pad_is_input (self) && gegl_pad_get_num_connections (self) == 1) { GeglConnection *connection = g_slist_nth_data (self->connections, 0); pad = gegl_connection_get_source_pad (connection); } return pad; }
/* 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); } } } }