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); }
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]); } } } }
/* 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); } } } }
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, ¤t_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); } } } } }