void gegl_operation_context_destroy (GeglOperationContext *self) { gegl_operation_context_purge (self); g_slice_free (GeglOperationContext, self); }
/** * gegl_graph_process: * @path: The traversal path * * Process the prepared request. This will return the * resulting buffer from the final node, or NULL if * that node is a sink. * * If gegl_graph_prepare_request has not been called * the behavior of this function is undefined. * * Return value: (transfer full): The result of the graph, or NULL if * there is no output pad. */ GeglBuffer * gegl_graph_process (GeglGraphTraversal *path, gint level) { GList *list_iter = NULL; GeglBuffer *result = NULL; GeglOperationContext *context = NULL; GeglOperationContext *last_context = NULL; GeglBuffer *operation_result = NULL; for (list_iter = path->dfs_path; list_iter; list_iter = list_iter->next) { GeglNode *node = GEGL_NODE (list_iter->data); GeglOperation *operation = node->operation; g_return_val_if_fail (node, NULL); g_return_val_if_fail (operation, NULL); GEGL_INSTRUMENT_START(); operation_result = NULL; if (last_context) gegl_operation_context_purge (last_context); context = g_hash_table_lookup (path->contexts, node); g_return_val_if_fail (context, NULL); GEGL_NOTE (GEGL_DEBUG_PROCESS, "Will process %s result_rect = %d, %d %d×%d", gegl_node_get_debug_name (node), context->result_rect.x, context->result_rect.y, context->result_rect.width, context->result_rect.height); if (context->need_rect.width > 0 && context->need_rect.height > 0) { if (context->cached) { GEGL_NOTE (GEGL_DEBUG_PROCESS, "Using cached result for %s", gegl_node_get_debug_name (node)); operation_result = GEGL_BUFFER (node->cache); } else { /* provide something on input pad, always - this makes having behavior depending on it not being set.. not work, is sacrifising that worth it? */ if (gegl_node_has_pad (node, "input") && !gegl_operation_context_get_object (context, "input")) { gegl_operation_context_set_object (context, "input", G_OBJECT (gegl_graph_get_shared_empty(path))); } context->level = level; /* note: this hard-coding of "output" makes some more custom * graph topologies harder than neccesary. */ gegl_operation_process (operation, context, "output", &context->need_rect, context->level); operation_result = GEGL_BUFFER (gegl_operation_context_get_object (context, "output")); if (operation_result && operation_result == (GeglBuffer *)operation->node->cache) gegl_cache_computed (operation->node->cache, &context->need_rect, level); } } else { operation_result = NULL; } if (operation_result) { GeglPad *output_pad = gegl_node_get_pad (node, "output"); GList *targets = gegl_graph_get_connected_output_contexts (path, output_pad); GList *targets_iter; GEGL_NOTE (GEGL_DEBUG_PROCESS, "Will deliver the results of %s:%s to %d targets", gegl_node_get_debug_name (node), "output", g_list_length (targets)); if (g_list_length (targets) > 1) gegl_object_set_has_forked (G_OBJECT (operation_result)); for (targets_iter = targets; targets_iter; targets_iter = g_list_next (targets_iter)) { ContextConnection *target_con = targets_iter->data; gegl_operation_context_set_object (target_con->context, target_con->name, G_OBJECT (operation_result)); } g_list_free_full (targets, free_context_connection); } last_context = context; GEGL_INSTRUMENT_END ("process", gegl_node_get_operation (node)); } if (last_context) { if (operation_result) result = g_object_ref (operation_result); else if (gegl_node_has_pad (last_context->operation->node, "output")) result = g_object_ref (gegl_graph_get_shared_empty (path)); gegl_operation_context_purge (last_context); } return result; }