static gboolean gegl_operation_composer3_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *result, gint level) { GeglOperationComposer3Class *klass = GEGL_OPERATION_COMPOSER3_GET_CLASS (operation); GeglBuffer *input; GeglBuffer *aux; GeglBuffer *aux2; GeglBuffer *output; gboolean success = FALSE; if (strcmp (output_prop, "output")) { g_warning ("requested processing of %s pad on a composer", output_prop); return FALSE; } if (result->width == 0 || result->height == 0) { output = gegl_operation_context_get_target (context, "output"); return TRUE; } input = gegl_operation_context_get_source (context, "input"); output = gegl_operation_context_get_output_maybe_in_place (operation, context, input, result); aux = gegl_operation_context_get_source (context, "aux"); aux2 = gegl_operation_context_get_source (context, "aux2"); /* A composer with a NULL aux, can still be valid, the * subclass has to handle it. */ if (input != NULL || aux != NULL || aux2 != NULL) { if (gegl_operation_use_threading (operation, result)) { gint threads = gegl_config_threads (); GThreadPool *pool = thread_pool (); ThreadData thread_data[GEGL_MAX_THREADS]; gint pending = threads; if (result->width > result->height) { gint bit = result->width / threads; for (gint j = 0; j < threads; j++) { thread_data[j].roi.y = result->y; thread_data[j].roi.height = result->height; thread_data[j].roi.x = result->x + bit * j; thread_data[j].roi.width = bit; } thread_data[threads-1].roi.width = result->width - (bit * (threads-1)); } else { gint bit = result->height / threads; for (gint j = 0; j < threads; j++) { thread_data[j].roi.x = result->x; thread_data[j].roi.width = result->width; thread_data[j].roi.y = result->y + bit * j; thread_data[j].roi.height = bit; } thread_data[threads-1].roi.height = result->height - (bit * (threads-1)); } for (gint i = 0; i < threads; i++) { thread_data[i].klass = klass; thread_data[i].operation = operation; thread_data[i].input = input; thread_data[i].aux = aux; thread_data[i].aux2 = aux2; thread_data[i].output = output; thread_data[i].pending = &pending; thread_data[i].level = level; thread_data[i].success = TRUE; } for (gint i = 1; i < threads; i++) g_thread_pool_push (pool, &thread_data[i], NULL); thread_process (&thread_data[0], NULL); while (g_atomic_int_get (&pending)) {}; success = thread_data[0].success; } else { success = klass->process (operation, input, aux, aux2, output, result, level); } g_clear_object (&input); g_clear_object (&aux); g_clear_object (&aux2); } else { g_warning ("%s received NULL input, aux, and aux2", gegl_node_get_operation (operation->node)); } return success; }
static gboolean gegl_operation_filter_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *result, gint level) { GeglOperationFilterClass *klass; GeglBuffer *input; GeglBuffer *output; gboolean success = FALSE; klass = GEGL_OPERATION_FILTER_GET_CLASS (operation); g_assert (klass->process); if (strcmp (output_prop, "output")) { g_warning ("requested processing of %s pad on a filter", output_prop); return FALSE; } input = (GeglBuffer*)gegl_operation_context_dup_object (context, "input"); output = gegl_operation_context_get_output_maybe_in_place (operation, context, input, result); if (gegl_operation_use_threading (operation, result)) { gint threads = gegl_config_threads (); GeglSplitStrategy split_strategy = GEGL_SPLIT_STRATEGY_AUTO; GThreadPool *pool = thread_pool (); ThreadData thread_data[GEGL_MAX_THREADS]; gint pending = threads; if (klass->get_split_strategy) { split_strategy = klass->get_split_strategy (operation, context, output_prop, result, level); } if (split_strategy == GEGL_SPLIT_STRATEGY_AUTO) { if (result->width > result->height) split_strategy = GEGL_SPLIT_STRATEGY_VERTICAL; else split_strategy = GEGL_SPLIT_STRATEGY_HORIZONTAL; } if (split_strategy == GEGL_SPLIT_STRATEGY_VERTICAL) { gint bit = result->width / threads; for (gint j = 0; j < threads; j++) { thread_data[j].roi.y = result->y; thread_data[j].roi.height = result->height; thread_data[j].roi.x = result->x + bit * j; thread_data[j].roi.width = bit; } thread_data[threads-1].roi.width = result->width - (bit * (threads-1)); } else if (split_strategy == GEGL_SPLIT_STRATEGY_HORIZONTAL) { gint bit = result->height / threads; for (gint j = 0; j < threads; j++) { thread_data[j].roi.x = result->x; thread_data[j].roi.width = result->width; thread_data[j].roi.y = result->y + bit * j; thread_data[j].roi.height = bit; } thread_data[threads-1].roi.height = result->height - (bit * (threads-1)); } else { g_return_val_if_reached (FALSE); } for (gint i = 0; i < threads; i++) { thread_data[i].klass = klass; thread_data[i].operation = operation; thread_data[i].context = context; thread_data[i].output = output; thread_data[i].pending = &pending; thread_data[i].level = level; thread_data[i].success = TRUE; } for (gint i = 1; i < threads; i++) g_thread_pool_push (pool, &thread_data[i], NULL); thread_process (&thread_data[0], g_object_ref (input)); while (g_atomic_int_get (&pending)) {}; success = thread_data[0].success; } else { success = klass->process (operation, input, output, result, level); } g_clear_object (&input); return success; }