static void gegl_buffer_dispose (GObject *object) { GeglBuffer *buffer = GEGL_BUFFER (object); GeglTileHandler *handler = GEGL_TILE_HANDLER (object); gegl_buffer_sample_cleanup (buffer); if (gegl_cl_is_accelerated ()) gegl_buffer_cl_cache_invalidate (GEGL_BUFFER (object), NULL); if (handler->source && GEGL_IS_TILE_STORAGE (handler->source)) { GeglTileBackend *backend = gegl_buffer_backend (buffer); /* only flush non-internal backends,. */ if (!(GEGL_IS_TILE_BACKEND_FILE (backend) || GEGL_IS_TILE_BACKEND_RAM (backend) || GEGL_IS_TILE_BACKEND_TILE_DIR (backend))) gegl_buffer_flush (buffer); gegl_tile_source_reinit (GEGL_TILE_SOURCE (handler->source)); #if 0 g_object_unref (handler->source); handler->source = NULL; /* this might be a dangerous way of marking that we have already voided */ #endif } _gegl_buffer_drop_hot_tile (buffer); G_OBJECT_CLASS (parent_class)->dispose (object); }
static void gegl_buffer_finalize (GObject *object) { #ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS g_free (GEGL_BUFFER (object)->alloc_stack_trace); allocated_buffers_list = g_list_remove (allocated_buffers_list, object); #endif g_free (GEGL_BUFFER (object)->path); de_allocated_buffers++; G_OBJECT_CLASS (parent_class)->finalize (object); }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); GeglRectangle result = {0,0,0,0}; load_buffer (o); result.width = gegl_buffer_get_width (GEGL_BUFFER (o->user_data)); result.height = gegl_buffer_get_height (GEGL_BUFFER (o->user_data)); return result; }
static gboolean gimp_operation_normal_parent_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *result, gint level) { #if 0 /* this code tries to be smart but is in fact just a too stupid * copy from gegl's normal mode. to fix it, it needs to take * mask and opacity into account */ const GeglRectangle *in_extent = NULL; const GeglRectangle *aux_extent = NULL; GObject *input; GObject *aux; /* get the raw values this does not increase the reference count */ input = gegl_operation_context_get_object (context, "input"); aux = gegl_operation_context_get_object (context, "aux"); /* pass the input/aux buffers directly through if they are not * overlapping */ if (input) in_extent = gegl_buffer_get_abyss (GEGL_BUFFER (input)); if (! input || (aux && ! gegl_rectangle_intersect (NULL, in_extent, result))) { gegl_operation_context_set_object (context, "output", aux); return TRUE; } if (aux) aux_extent = gegl_buffer_get_abyss (GEGL_BUFFER (aux)); if (! aux || (input && ! gegl_rectangle_intersect (NULL, aux_extent, result))) { gegl_operation_context_set_object (context, "output", input); return TRUE; } #endif /* chain up, which will create the needed buffers for our actual * process function */ return GEGL_OPERATION_CLASS (parent_class)->process (operation, context, output_prop, result, level); }
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 = gegl_operation_context_get_source (context, "input"); output = gegl_operation_context_get_target (context, "output"); success = klass->process (operation, input, output, result, level); if (output == GEGL_BUFFER (operation->node->cache)) gegl_cache_computed (operation->node->cache, result); if (input != NULL) g_object_unref (input); return success; }
static gboolean gegl_nop_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *result, gint level) { GeglBuffer *input; if (strcmp (output_prop, "output")) { g_warning ("requested processing of %s pad on a nop", output_prop); return FALSE; } input = GEGL_BUFFER (gegl_operation_context_get_object (context, "input")); if (!input) { g_warning ("nop received NULL input"); return FALSE; } gegl_operation_context_take_object (context, "output", g_object_ref (G_OBJECT (input))); return TRUE; }
/** * gegl_graph_prepare: * @path: The traversal path * * Prepare all nodes, initializing their output formats and have rects. */ void gegl_graph_prepare (GeglGraphTraversal *path) { GList *list_iter = 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_mutex_lock (&node->mutex); gegl_operation_prepare (operation); node->have_rect = gegl_operation_get_bounding_box (operation); node->valid_have_rect = TRUE; if (node->cache) { gegl_buffer_set_extent (GEGL_BUFFER (node->cache), &node->have_rect); } g_mutex_unlock (&node->mutex); if (!g_hash_table_contains (path->contexts, node)) { GeglOperationContext *context = gegl_operation_context_new (node->operation); g_hash_table_insert (path->contexts, node, context); } } }
/** * mypaint_gegl_tiled_surface_set_buffer: * @buffer: (transfer full): The buffer which shall back this surface. * */ void mypaint_gegl_tiled_surface_set_buffer(MyPaintGeglTiledSurface *self, GeglBuffer *buffer) { if (buffer && self->buffer == buffer) { return; } if (self->buffer) { g_object_unref(self->buffer); } if (buffer) { g_return_if_fail(GEGL_IS_BUFFER(buffer)); g_object_ref(buffer); self->buffer = buffer; } else { // Using GeglBuffer with aligned tiles for zero-copy access self->buffer = GEGL_BUFFER(g_object_new(GEGL_TYPE_BUFFER, "x", self->extent_rect.x, "y", self->extent_rect.y, "width", self->extent_rect.width, "height", self->extent_rect.height, "format", self->format, "tile-width", self->parent.tile_size, "tile-height", self->parent.tile_size, NULL)); } g_assert(GEGL_IS_BUFFER(self->buffer)); self->parent.threadsafe_tile_requests = buffer_is_native(self); }
static gboolean gegl_operation_source_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *result, gint level) { GeglOperationSourceClass *klass = GEGL_OPERATION_SOURCE_GET_CLASS (operation); GeglBuffer *output; gboolean success; if (strcmp (output_prop, "output")) { g_warning ("requested processing of %s pad on a source operation", output_prop); return FALSE; } g_assert (klass->process); output = gegl_operation_context_get_target (context, "output"); success = klass->process (operation, output, result, level); if (output == GEGL_BUFFER (operation->node->cache)) gegl_cache_computed (operation->node->cache, result); return success; }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglRectangle result = {0,0,0,0}; GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); load_buffer (o); if (o->chant_data) { result.width = gegl_buffer_get_width (GEGL_BUFFER (o->chant_data)); result.height = gegl_buffer_get_height (GEGL_BUFFER (o->chant_data)); } return result; }
static gboolean gegl_operation_point_filter_op_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_pad, const GeglRectangle *roi) { GeglBuffer *input; GeglBuffer *output; gboolean success = FALSE; input = gegl_operation_context_get_source (context, "input"); if (gegl_can_do_inplace_processing (operation, input, roi)) { output = g_object_ref (input); gegl_operation_context_take_object (context, "output", G_OBJECT (output)); } else { output = gegl_operation_context_get_target (context, "output"); } success = gegl_operation_point_filter_process (operation, input, output, roi); if (output == GEGL_BUFFER (operation->node->cache)) gegl_cache_computed (operation->node->cache, roi); if (input != NULL) g_object_unref (input); return success; }
static void my_set_property (GObject *gobject, guint property_id, const GValue *value, GParamSpec *pspec) { GeglOperation *operation = GEGL_OPERATION (gobject); GeglProperties *o = GEGL_PROPERTIES (operation); Priv *p = get_priv(o); GObject *buffer = NULL; switch (property_id) { case PROP_buffer: if (o->buffer) { // Invariant: valid buffer should always have valid signal handler g_assert(p->buffer_changed_handler > 0); g_signal_handler_disconnect (o->buffer, p->buffer_changed_handler); /* XXX: should decrement signal connected count */ } buffer = G_OBJECT (g_value_get_object (value)); if (buffer) { p->buffer_changed_handler = gegl_buffer_signal_connect (GEGL_BUFFER(buffer), "changed", G_CALLBACK(buffer_changed), operation); } break; default: break; } /* The set_property provided by the chant system does the * storing and reffing/unreffing of the input properties */ set_property(gobject, property_id, value, pspec); }
static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GeglSampler *self = GEGL_SAMPLER (object); switch (property_id) { case PROP_BUFFER: gegl_sampler_set_buffer (self, GEGL_BUFFER (g_value_get_object (value))); break; case PROP_FORMAT: self->format = g_value_get_pointer (value); break; case PROP_LEVEL: self->lvel = g_value_get_int (value); break; default: break; } }
GeglBuffer * gegl_operation_context_get_source (GeglOperationContext *context, const gchar *padname) { GeglBuffer *input; input = GEGL_BUFFER (gegl_operation_context_dup_object (context, padname)); return input; }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglRectangle result = {0,0,0,0}; GeglBuffer *buffer = ensure_buffer (operation); result = *gegl_buffer_get_extent (GEGL_BUFFER (buffer)); return result; }
static void load_buffer (GeglProperties *op_raw_load) { if (!op_raw_load->user_data) { FILE *pfp; gchar *command; gint width, height, val_max; gchar newline; command = g_strdup_printf ("dcraw -4 -c '%s'\n", op_raw_load->path); pfp = popen (command, PIPE_MODE); g_free (command); if (fscanf (pfp, "P6 %d %d %d %c", &width, &height, &val_max, &newline) != 4) { pclose (pfp); g_warning ("not able to aquire raw data"); return; } { GeglRectangle extent = { 0, 0, 0, 0 }; extent.width = width; extent.height = height; op_raw_load->user_data = (gpointer) gegl_buffer_new (&extent, babl_format_new ( babl_model ("RGB"), babl_type ("u16"), babl_component ("G"), babl_component ("B"), babl_component ("R"), NULL)); } { guint16 *buf = g_new (guint16, width * height * 3); fread (buf, 1, width * height * 3 * 2, pfp); gegl_buffer_set (GEGL_BUFFER (op_raw_load->user_data), NULL, 0, babl_format_new ( babl_model ("RGB"), babl_type ("u16"), babl_component ("G"), babl_component ("B"), babl_component ("R"), NULL), buf, GEGL_AUTO_ROWSTRIDE ); g_free (buf); } fclose (pfp); } }
static void load_buffer (GeglProperties *op_raw_load) { if (!op_raw_load->user_data) { FILE *pfp; gchar *command; gint width, height, val_max; char newline; command = g_strdup_printf ("dcraw -j -d -4 -c '%s'\n", op_raw_load->path); pfp = popen (command, PIPE_MODE); g_free (command); if (fscanf (pfp, "P6 %d %d %d %c", &width, &height, &val_max, &newline) != 4) { pclose (pfp); g_warning ("not able to aquire raw data"); return; } { GeglRectangle extent = { 0, 0, width, height }; op_raw_load->user_data = (void*)gegl_buffer_new (&extent, babl_format ("Y u16")); } { guchar *buf = g_new (guchar, width * height * 3 * 2); fread (buf, 1, width * height * 3 * 2, pfp); if(strstr (op_raw_load->path, "rawbayerS")){ gint i; for (i=0;i<width*height*3;i++) { guchar tmp = buf[i*2]; buf[i*2] = buf[i*2+1]; buf[i*2+1] = tmp; } } gegl_buffer_set (GEGL_BUFFER (op_raw_load->user_data), NULL, 0, babl_format_new ( babl_model ("RGB"), babl_type ("u16"), babl_component ("R"), babl_component ("G"), babl_component ("B"), NULL), buf, GEGL_AUTO_ROWSTRIDE); g_free (buf); } fclose (pfp); } }
static void gegl_cache_init (GeglCache *self) { self->node = NULL; self->mutex = g_mutex_new (); /* thus providing a default value for GeglCache, that overrides the NULL * from GeglBuffer */ GEGL_BUFFER (self)->format = (gpointer) babl_format ("R'G'B'A u8"); }
static gboolean photos_operation_svg_multiply_operation_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_pad, const GeglRectangle *roi, gint level) { GObject *aux; GObject *input; const GeglRectangle *aux_bbox = NULL; const GeglRectangle *in_bbox = NULL; gboolean ret_val = TRUE; aux = gegl_operation_context_get_object (context, "aux"); if (aux != NULL) aux_bbox = gegl_buffer_get_abyss (GEGL_BUFFER (aux)); input = gegl_operation_context_get_object (context, "input"); if (input != NULL) in_bbox = gegl_buffer_get_abyss (GEGL_BUFFER (input)); if (aux == NULL || (input != NULL && !gegl_rectangle_intersect (NULL, aux_bbox, roi))) { gegl_operation_context_set_object (context, "output", input); goto out; } if (input == NULL || (aux != NULL && !gegl_rectangle_intersect (NULL, in_bbox, roi))) { gegl_operation_context_set_object (context, "output", aux); goto out; } ret_val = GEGL_OPERATION_CLASS (photos_operation_svg_multiply_parent_class)->process (operation, context, output_pad, roi, level); out: return ret_val; }
static void gegl_buffer_source_prepare (GeglOperation *operation) { const Babl *format = NULL; GeglProperties *o = GEGL_PROPERTIES (operation); if (o->buffer) format = gegl_buffer_get_format (GEGL_BUFFER (o->buffer)); gegl_operation_set_format (operation, "output", format); }
/* we replicate the process function from GeglOperationComposer to be * able to bail out earlier for some common processing time pitfalls */ static gboolean gegl_operation_composer_process2 (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *result) { GeglOperationComposerClass *klass = GEGL_OPERATION_COMPOSER_GET_CLASS (operation); GeglBuffer *input; GeglBuffer *aux; GeglBuffer *output; gboolean success = FALSE; if (strcmp (output_prop, "output")) { g_warning ("requested processing of %s pad on a composer", output_prop); return FALSE; } input = gegl_operation_context_get_source (context, "input"); aux = gegl_operation_context_get_source (context, "aux"); if (gegl_can_do_inplace_processing (operation, input, result)) { output = g_object_ref (input); gegl_operation_context_take_object (context, "output", G_OBJECT (output)); } else output = gegl_operation_context_get_target (context, "output"); { gboolean done = FALSE; if (result->width == 0 || result->height == 0) done = TRUE; success = done; if (!done) { success = klass->process (operation, input, aux, output, result); if (output == GEGL_BUFFER (operation->node->cache)) gegl_cache_computed (operation->node->cache, result); } if (input) g_object_unref (input); if (aux) g_object_unref (aux); } return success; }
GeglBuffer * gegl_operation_context_get_source (GeglOperationContext *context, const gchar *padname) { GeglBuffer *real_input; GeglBuffer *input; real_input = GEGL_BUFFER (gegl_operation_context_get_object (context, padname)); if (!real_input) return NULL; input = g_object_ref (real_input); return input; }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglRectangle result = {0,0,0,0}; GeglProperties *o = GEGL_PROPERTIES (operation); if (!o->buffer) { return result; } result = *gegl_buffer_get_extent (GEGL_BUFFER (o->buffer)); return result; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); if (o->buffer) { GeglBuffer *output = GEGL_BUFFER (o->buffer); gegl_buffer_copy (input, result, output, result); } return TRUE; }
static gboolean gegl_operation_composer_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *result, gint level) { GeglOperationComposerClass *klass = GEGL_OPERATION_COMPOSER_GET_CLASS (operation); GeglBuffer *input; GeglBuffer *aux; GeglBuffer *output; gboolean success = FALSE; if (strcmp (output_prop, "output")) { g_warning ("requested processing of %s pad on a composer", output_prop); return FALSE; } input = gegl_operation_context_get_source (context, "input"); aux = gegl_operation_context_get_source (context, "aux"); output = gegl_operation_context_get_target (context, "output"); /* A composer with a NULL aux, can still be valid, the * subclass has to handle it. */ if (input != NULL || aux != NULL) { success = klass->process (operation, input, aux, output, result, level); if (output == GEGL_BUFFER (operation->node->cache)) gegl_cache_computed (operation->node->cache, result); if (input) g_object_unref (input); if (aux) g_object_unref (aux); } else { g_warning ("%s received NULL input and aux", gegl_node_get_debug_name (operation->node)); } return success; }
static GObject * gegl_cache_constructor (GType type, guint n_params, GObjectConstructParam *params) { GObject *object; GeglCache *self; object = G_OBJECT_CLASS (gegl_cache_parent_class)->constructor (type, n_params, params); self = GEGL_CACHE (object); self->valid_region = gegl_region_new (); self->format = GEGL_BUFFER (self)->format; return object; }
static gboolean process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_pad, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); GeglBuffer *output; load_buffer (o); g_assert (o->user_data); g_assert (g_str_equal (output_pad, "output")); output = GEGL_BUFFER (o->user_data); g_object_ref (output); gegl_operation_context_take_object (context, "output", G_OBJECT (output)); return TRUE; }
void gegl_cache_invalidate (GeglCache *self, const GeglRectangle *roi) { #if 0 if (roi) { gegl_buffer_clear (GEGL_BUFFER (self), roi); } else { g_warning ("XXX: full invalidation of GeglCache NYI\n"); } #endif g_mutex_lock (self->mutex); if (roi) { GeglRectangle expanded = gegl_rectangle_expand (roi); GeglRegion *temp_region; temp_region = gegl_region_rectangle (&expanded); gegl_region_subtract (self->valid_region, temp_region); gegl_region_destroy (temp_region); g_signal_emit (self, gegl_cache_signals[INVALIDATED], 0, roi, NULL); } else { GeglRectangle rect = { 0, 0, 0, 0 }; /* should probably be the extent of the cache */ if (self->valid_region) gegl_region_destroy (self->valid_region); self->valid_region = gegl_region_new (); g_signal_emit (self, gegl_cache_signals[INVALIDATED], 0, &rect, NULL); } g_mutex_unlock (self->mutex); }
gint gegl_buffer_leaks (void) { #ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS { GList *leaked_buffer = NULL; for (leaked_buffer = allocated_buffers_list; leaked_buffer != NULL; leaked_buffer = leaked_buffer->next) { GeglBuffer *buffer = GEGL_BUFFER (leaked_buffer->data); g_printerr ("\n" "Leaked buffer allocation stack trace:\n"); g_printerr ("%s\n", buffer->alloc_stack_trace); } } g_list_free (allocated_buffers_list); allocated_buffers_list = NULL; #endif return allocated_buffers - de_allocated_buffers; }
GeglBuffer * gegl_operation_context_get_target (GeglOperationContext *context, const gchar *padname) { GeglBuffer *output; const GeglRectangle *result; const Babl *format; GeglNode *node; GeglOperation *operation; #if 0 g_return_val_if_fail (GEGL_IS_OPERATION_CONTEXT (context), NULL); #endif operation = context->operation; node = operation->node; /* <ick */ format = gegl_operation_get_format (operation, padname); if (format == NULL) { g_warning ("no format for %s presuming RGBA float\n", gegl_node_get_debug_name (node)); format = babl_format ("RGBA float"); } g_assert (format != NULL); g_assert (!strcmp (padname, "output")); result = &context->result_rect; if (result->width == 0 || result->height == 0) { output = g_object_ref (emptybuf()); } else if (node->dont_cache == FALSE && ! GEGL_OPERATION_CLASS (G_OBJECT_GET_CLASS (operation))->no_cache) { GeglBuffer *cache; cache = GEGL_BUFFER (gegl_node_get_cache (node)); /* Only use the cache if the result is within the cache * extent. This is certainly not optimal. My gut feeling is that * the current caching mechanism needs to be redesigned */ if (gegl_rectangle_contains (gegl_buffer_get_extent (cache), result)) { output = g_object_ref (cache); } else { output = gegl_buffer_new_ram (result, format); } } else { output = gegl_buffer_new_ram (result, format); } gegl_operation_context_take_object (context, padname, G_OBJECT (output)); return output; }