static void gegl_operations_update_visible (void) { GHashTableIter iter; const gchar *iter_key; GType iter_value; g_mutex_lock (&operations_cache_mutex); g_hash_table_remove_all (visible_operation_names); g_slist_free (operations_list); operations_list = NULL; g_hash_table_iter_init (&iter, known_operation_names); while (g_hash_table_iter_next (&iter, (gpointer)&iter_key, (gpointer)&iter_value)) { GObjectClass *object_class; GeglOperationClass *operation_class; const gchar *operation_license; object_class = g_type_class_ref (iter_value); operation_class = GEGL_OPERATION_CLASS (object_class); operation_license = g_hash_table_lookup (operation_class->keys, "license"); if (!operation_license || gegl_operations_check_license (operation_license)) { if (operation_license) { GEGL_NOTE (GEGL_DEBUG_LICENSE, "Accepted %s for %s", operation_license, iter_key); } if (operation_class->name && (0 == strcmp (iter_key, operation_class->name))) { /* Is the primary name of the operation */ operations_list = g_slist_insert_sorted (operations_list, (gpointer) iter_key, (GCompareFunc) strcmp); } g_hash_table_insert (visible_operation_names, g_strdup (iter_key), (gpointer) iter_value); } else if (operation_license) { GEGL_NOTE (GEGL_DEBUG_LICENSE, "Rejected %s for %s", operation_license, iter_key); } g_type_class_unref (object_class); } g_mutex_unlock (&operations_cache_mutex); }
static gpointer gegl_tile_backend_file_flush (GeglTileSource *source, GeglTile *tile, gint x, gint y, gint z) { GeglTileBackend *backend; GeglTileBackendFile *self; GList *tiles; backend = GEGL_TILE_BACKEND (source); self = GEGL_TILE_BACKEND_FILE (backend); gegl_tile_backend_file_ensure_exist (self); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "flushing %s", self->path); self->header.rev ++; self->header.next = self->next_pre_alloc; /* this is the offset we start handing out headers from*/ tiles = g_hash_table_get_keys (self->index); if (tiles == NULL) self->header.next = 0; else { GList *iter; for (iter = tiles; iter; iter = iter->next) { GeglBufferItem *item = iter->data; gegl_tile_backend_file_write_block (self, &item->block); } gegl_tile_backend_file_write_block (self, NULL); /* terminate the index */ g_list_free (tiles); } gegl_tile_backend_file_write_header (self); #if HAVE_GIO g_output_stream_flush (self->o, NULL, NULL); #else fsync (self->o); #endif GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "flushed %s", self->path); return (gpointer)0xf0f; }
/* Reads buffer index from the file descriptor (first argument) or * memory mapped file if map argument is not NULL */ GList * gegl_buffer_read_index (int i, goffset *offset, gchar *map) /* load the index */ { GList *ret = NULL; GeglBufferItem *item; for (item = read_block (i, offset, map); item; item = read_block (i, offset, map)) { g_assert (item); GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD,"loaded item: %i, %i, %i offset:%i next:%i", item->tile.x, item->tile.y, item->tile.z, (guint)item->tile.offset, (guint)item->block.next); *offset = item->block.next; ret = g_list_prepend (ret, item); } ret = g_list_reverse (ret); return ret; }
static gboolean gegl_tile_backend_file_write_header (GeglTileBackendFile *self) { gboolean success; gegl_tile_backend_file_ensure_exist (self); #if HAVE_GIO success = g_seekable_seek (G_SEEKABLE (self->o), 0, G_SEEK_SET, NULL, NULL); #else success = (lseek (self->o, 0, SEEK_SET) != -1); #endif if (success == FALSE) { g_warning ("unable to seek in buffer"); return FALSE; } #if HAVE_GIO g_output_stream_write (self->o, &(self->header), 256, NULL, NULL); #else write (self->o, &(self->header), 256); #endif GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Wrote header, next=%i", (gint)self->header.next); return TRUE; }
static void gegl_tile_backend_file_finalize (GObject *object) { GeglTileBackendFile *self = (GeglTileBackendFile *) object; if (self->index) g_hash_table_unref (self->index); if (self->exist) { GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "finalizing buffer %s", self->path); if (self->i != -1) { close (self->i); self->i = -1; } if (self->o != -1) { close (self->o); self->o = -1; } } if (self->path) g_free (self->path); if (self->monitor) g_object_unref (self->monitor); if (self->file) g_object_unref (self->file); (*G_OBJECT_CLASS (parent_class)->finalize)(object); }
static gboolean process (GeglOperation *operation, GeglBuffer *out_buf, const GeglRectangle *roi, gint level) { GeglBufferIterator *iter; const Babl *out_format = gegl_operation_get_format (operation, "output"); if (gegl_operation_use_opencl (operation)) { GeglBufferClIterator *cl_iter; gboolean err; GEGL_NOTE (GEGL_DEBUG_OPENCL, "GEGL_OPERATION_POINT_RENDER: %s", GEGL_OPERATION_GET_CLASS (operation)->name); cl_iter = gegl_buffer_cl_iterator_new (out_buf, roi, out_format, GEGL_CL_BUFFER_WRITE); while (gegl_buffer_cl_iterator_next (cl_iter, &err) && !err) { err = cl_process (operation, cl_iter->tex[0], cl_iter->roi); if (err) { gegl_buffer_cl_iterator_stop (cl_iter); break; } } if (err) GEGL_NOTE (GEGL_DEBUG_OPENCL, "Error: %s", GEGL_OPERATION_GET_CLASS (operation)->name); else return TRUE; } iter = gegl_buffer_iterator_new (out_buf, roi, level, out_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) c_process (operation, iter->data[0], &iter->roi[0]); return TRUE; }
static gboolean operation_source_process (GeglOperation *operation, GeglBuffer *output, const GeglRectangle *result, gint level) { const Babl *out_format = gegl_operation_get_format (operation, "output"); if ((result->width > 0) && (result->height > 0)) { GeglBufferIterator *iter; if (gegl_operation_use_opencl (operation) && babl_format_get_n_components (out_format) == 4 && babl_format_get_type (out_format, 0) == babl_type ("float")) { GeglBufferClIterator *cl_iter; gboolean err; GEGL_NOTE (GEGL_DEBUG_OPENCL, "GEGL_OPERATION_POINT_RENDER: %s", GEGL_OPERATION_GET_CLASS (operation)->name); cl_iter = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE); while (gegl_buffer_cl_iterator_next (cl_iter, &err) && !err) { err = checkerboard_cl_process (operation, cl_iter->tex[0], cl_iter->size[0], &cl_iter->roi[0], level); if (err) { gegl_buffer_cl_iterator_stop (cl_iter); break; } } if (err) GEGL_NOTE (GEGL_DEBUG_OPENCL, "Error: %s", GEGL_OPERATION_GET_CLASS (operation)->name); else return TRUE; } iter = gegl_buffer_iterator_new (output, result, level, out_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) checkerboard_process (operation, iter->data[0], iter->length, &iter->roi[0], level); } return TRUE; }
static void seekto(LoadInfo *info, gint offset) { info->offset = offset; GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "seek to %i", offset); if(lseek (info->i, info->offset, SEEK_SET) == -1) { g_warning ("failed seeking"); } }
static inline GeglBufferTile * gegl_tile_backend_file_file_entry_new (GeglTileBackendFile *self) { GeglBufferTile *entry = gegl_tile_entry_new (0,0,0); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Creating new entry"); gegl_tile_backend_file_ensure_exist (self); if (self->free_list) { /* XXX: losing precision ? * the free list seems to operate with fixed size datums and * only keep track of offsets. */ gint offset = GPOINTER_TO_INT (self->free_list->data); entry->offset = offset; self->free_list = g_slist_remove (self->free_list, self->free_list->data); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, " set offset %i from free list", ((gint)entry->offset)); } else { gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); entry->offset = self->next_pre_alloc; GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, " set offset %i (next allocation)", (gint)entry->offset); self->next_pre_alloc += tile_size; if (self->next_pre_alloc >= self->total) /* automatic growing ensuring that we have room for next allocation.. */ { self->total = self->total + 32 * tile_size; GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "growing file to %i bytes", (gint)self->total); ftruncate (self->o, self->total); self->foffset = -1; } } gegl_tile_backend_file_dbg_alloc (gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self))); return entry; }
static inline GeglBufferTile * gegl_tile_backend_file_file_entry_new (GeglTileBackendFile *self) { GeglBufferTile *entry = gegl_tile_entry_new (0,0,0); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Creating new entry"); gegl_tile_backend_file_ensure_exist (self); if (self->free_list) { /* XXX: losing precision ? */ gint offset = GPOINTER_TO_INT (self->free_list->data); entry->offset = offset; self->free_list = g_slist_remove (self->free_list, self->free_list->data); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, " set offset %i from free list", ((gint)entry->offset)); } else { gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); entry->offset = self->next_pre_alloc; GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, " set offset %i (next allocation)", (gint)entry->offset); self->next_pre_alloc += tile_size; if (self->next_pre_alloc >= self->total) { self->total = self->total + 32 * tile_size; GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "growing file to %i bytes", (gint)self->total); #if HAVE_GIO g_assert (g_seekable_truncate (G_SEEKABLE (self->o), self->total, NULL,NULL)); #else g_assert (ftruncate (self->o, self->total) == 0); #endif } } gegl_tile_backend_file_dbg_alloc (gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self))); return entry; }
static void gegl_tile_backend_swap_entry_write (GeglTileBackendSwap *self, SwapEntry *entry, guchar *source) { ThreadParams *params; gint length = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); guchar *new_source; gegl_tile_backend_swap_ensure_exist (); if (entry->link) { g_mutex_lock (&mutex); if (entry->link) { params = entry->link->data; memcpy (params->source, source, length); g_mutex_unlock (&mutex); GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "overwrote queue entry %i, %i, %i at %i", entry->x, entry->y, entry->z, (gint)entry->offset); return; } g_mutex_unlock (&mutex); } new_source = g_malloc (length); memcpy (new_source, source, length); params = g_slice_new0 (ThreadParams); params->operation = OP_WRITE; params->length = length; params->source = new_source; params->entry = entry; gegl_tile_backend_swap_push_queue (params); GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "pushed write of entry %i, %i, %i at %i", entry->x, entry->y, entry->z, (gint)entry->offset); }
static gpointer gegl_tile_backend_swap_writer_thread (gpointer ignored) { while (TRUE) { ThreadParams *params; g_mutex_lock (&mutex); while (g_queue_is_empty (queue) && !exit_thread) g_cond_wait (&queue_cond, &mutex); if (exit_thread) { g_mutex_unlock (&mutex); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "exiting writer thread"); return NULL; } params = (ThreadParams *)g_queue_pop_head (queue); if (params->operation == OP_WRITE) { in_progress = params; params->entry->link = NULL; } g_mutex_unlock (&mutex); switch (params->operation) { case OP_WRITE: gegl_tile_backend_swap_write (params); break; case OP_TRUNCATE: if (ftruncate (out_fd, total) != 0) g_warning ("failed to resize swap file: %s", g_strerror (errno)); break; } g_mutex_lock (&mutex); in_progress = NULL; if (params->operation == OP_WRITE) gegl_tile_unref (params->tile); g_slice_free (ThreadParams, params); g_mutex_unlock (&mutex); } return NULL; }
static void gegl_tile_backend_swap_resize (guint64 size) { ThreadParams *params; total = size; params = g_slice_new0 (ThreadParams); params->operation = OP_TRUNCATE; gegl_tile_backend_swap_push_queue (params); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "pushed resize to %i", (gint)total); }
static void gegl_tile_backend_swap_entry_write (GeglTileBackendSwap *self, SwapEntry *entry, GeglTile *tile) { ThreadParams *params; gint length = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); gegl_tile_backend_swap_ensure_exist (); if (entry->link) { g_mutex_lock (&mutex); if (entry->link) { params = entry->link->data; gegl_tile_unref (params->tile); params->tile = gegl_tile_dup (tile); g_mutex_unlock (&mutex); GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "tile %i, %i, %i at %i is already enqueued, changed data", entry->x, entry->y, entry->z, (gint)entry->offset); return; } g_mutex_unlock (&mutex); } params = g_slice_new0 (ThreadParams); params->operation = OP_WRITE; params->length = length; params->tile = gegl_tile_dup (tile); params->entry = entry; gegl_tile_backend_swap_push_queue (params); GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "pushed write of entry %i, %i, %i at %i", entry->x, entry->y, entry->z, (gint)entry->offset); }
static void gegl_tile_backend_swap_constructed (GObject *object) { GeglTileBackend *backend = GEGL_TILE_BACKEND (object); G_OBJECT_CLASS (parent_class)->constructed (object); backend->priv->shared = FALSE; gegl_tile_backend_set_flush_on_destroy (backend, FALSE); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "constructing swap backend"); }
static inline void gegl_tile_backend_file_file_entry_read (GeglTileBackendFile *self, GeglBufferTile *entry, guchar *dest) { gint to_be_read; gboolean success; gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); goffset offset = entry->offset; gegl_tile_backend_file_ensure_exist (self); #if HAVE_GIO success = g_seekable_seek (G_SEEKABLE (self->i), offset, G_SEEK_SET, NULL, NULL); #else success = (lseek (self->i, offset, SEEK_SET) >= 0); #endif if (success == FALSE) { g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno)); return; } to_be_read = tile_size; while (to_be_read > 0) { gint byte_read; #if HAVE_GIO byte_read = g_input_stream_read (G_INPUT_STREAM (self->i), dest + tile_size - to_be_read, to_be_read, NULL, NULL); #else byte_read = read (self->i, dest + tile_size - to_be_read, to_be_read); #endif if (byte_read <= 0) { g_message ("unable to read tile data from self: " "%s (%d/%d bytes read)", g_strerror (errno), byte_read, to_be_read); return; } to_be_read -= byte_read; } GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "read entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset); }
static void gegl_tile_backend_file_finalize (GObject *object) { GeglTileBackendFile *self = (GeglTileBackendFile *) object; if (self->index) g_hash_table_unref (self->index); if (self->exist) { GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "finalizing buffer %s", self->path); #if HAVE_GIO if (self->io) { g_io_stream_close (self->io, NULL, NULL); g_object_unref (self->io); self->io = NULL; } if (self->file) g_file_delete (self->file, NULL, NULL); #else if (self->i != -1) { close (self->i); self->i = -1; } if (self->o != -1) { close (self->o); self->o = -1; } #endif } if (self->path) g_free (self->path); #if HAVE_GIO if (self->monitor) g_object_unref (self->monitor); if (self->file) g_object_unref (self->file); #endif (*G_OBJECT_CLASS (parent_class)->finalize)(object); }
static inline void gegl_tile_backend_file_file_entry_write (GeglTileBackendFile *self, GeglBufferTile *entry, guchar *source) { gint to_be_written; gboolean success; gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); goffset offset = entry->offset; gegl_tile_backend_file_ensure_exist (self); #if HAVE_GIO success = g_seekable_seek (G_SEEKABLE (self->o), offset, G_SEEK_SET, NULL, NULL); #else success = (lseek (self->o, offset, SEEK_SET) >= 0); #endif if (success == FALSE) { g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno)); return; } to_be_written = tile_size; while (to_be_written > 0) { gint wrote; #if HAVE_GIO wrote = g_output_stream_write (self->o, source + tile_size - to_be_written, to_be_written, NULL, NULL); #else wrote = write (self->o, source + tile_size - to_be_written, to_be_written); #endif if (wrote <= 0) { g_message ("unable to write tile data to self: " "%s (%d/%d bytes written)", g_strerror (errno), wrote, to_be_written); return; } to_be_written -= wrote; } GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "wrote entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset); }
/* Reads buffer header from the file descriptor (first argument) or * memory mapped file if map argument is not NULL */ GeglBufferItem * gegl_buffer_read_header (int i, goffset *offset, gchar *map) { goffset placeholder; GeglBufferItem *ret; if (offset==0) offset = &placeholder; if (map == NULL) if(lseek(i, 0, SEEK_SET) == -1) g_warning ("failed seeking to %i", 0); *offset = 0; ret = g_malloc (sizeof (GeglBufferHeader)); if (map) { memcpy (ret, map, sizeof (GeglBufferHeader)); *offset += sizeof (GeglBufferHeader); } else { ssize_t sz_read = read(i, ret, sizeof(GeglBufferHeader)); if (sz_read != -1) *offset += sz_read; } GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "read header: tile-width: %i tile-height: %i next:%i %ix%i\n", ret->header.tile_width, ret->header.tile_height, (guint)ret->block.next, ret->header.width, ret->header.height); if (!(ret->header.magic[0]=='G' && ret->header.magic[1]=='E' && ret->header.magic[2]=='G' && ret->header.magic[3]=='L')) { g_warning ("Magic is wrong! %s", ret->header.magic); } return ret; }
static inline void gegl_tile_backend_file_file_entry_read (GeglTileBackendFile *self, GeglBufferTile *entry, guchar *dest) { gint to_be_read; gboolean success; gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); goffset offset = entry->offset; guchar *tdest = dest; gegl_tile_backend_file_ensure_exist (self); if (self->foffset != offset) { success = (lseek (self->i, offset, SEEK_SET) >= 0); if (success == FALSE) { g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno)); return; } self->foffset = offset; } to_be_read = tile_size; while (to_be_read > 0) { GError *error = NULL; gint byte_read; byte_read = read (self->i, tdest + tile_size - to_be_read, to_be_read); if (byte_read <= 0) { g_message ("unable to read tile data from self: " "%s (%d/%d bytes read) %s", g_strerror (errno), byte_read, to_be_read, error?error->message:"--"); return; } to_be_read -= byte_read; self->foffset += byte_read; } GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "read entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset); }
static void gegl_tile_backend_swap_ensure_exist (void) { if (in_fd == -1 || out_fd == -1) { gchar *filename = g_strdup_printf ("%i-shared.swap", getpid ()); path = g_build_filename (gegl_config ()->swap, filename, NULL); g_free (filename); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "creating swapfile %s", path); out_fd = g_open (path, O_RDWR|O_CREAT, 0770); in_fd = g_open (path, O_RDONLY, 0); if (out_fd == -1 || in_fd == -1) g_warning ("Could not open swap file '%s': %s", path, g_strerror (errno)); } }
static gboolean gegl_tile_backend_file_write_header (GeglTileBackendFile *self) { gboolean success; gegl_tile_backend_file_ensure_exist (self); success = (lseek (self->o, 0, SEEK_SET) != -1); if (success == FALSE) { g_warning ("unable to seek in buffer"); return FALSE; } write (self->o, &(self->header), 256); self->foffset = 256; GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Wrote header, next=%i", (gint)self->header.next); return TRUE; }
static GObject * gegl_tile_backend_swap_constructor (GType type, guint n_params, GObjectConstructParam *params) { GObject *object; GeglTileBackendSwap *self; GeglTileBackend *backend; object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params); self = GEGL_TILE_BACKEND_SWAP (object); backend = GEGL_TILE_BACKEND (object); self->index = g_hash_table_new (gegl_tile_backend_swap_hashfunc, gegl_tile_backend_swap_equalfunc); backend->priv->shared = FALSE; GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "constructing swap backend"); return object; }
static void gegl_tile_backend_swap_write (ThreadParams *params) { gint to_be_written = params->length; guint64 offset = params->entry->offset; if (out_offset != offset) { if (lseek (out_fd, offset, SEEK_SET) < 0) { g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno)); return; } out_offset = offset; } while (to_be_written > 0) { gint wrote; wrote = write (out_fd, gegl_tile_get_data (params->tile) + params->length - to_be_written, to_be_written); if (wrote <= 0) { g_message ("unable to write tile data to self: " "%s (%d/%d bytes written)", g_strerror (errno), wrote, to_be_written); break; } to_be_written -= wrote; out_offset += wrote; } GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "writer thread wrote at %i", (gint)offset); }
static void gegl_tile_backend_file_ensure_exist (GeglTileBackendFile *self) { if (!self->exist) { GeglTileBackend *backend; self->exist = TRUE; backend = GEGL_TILE_BACKEND (self); GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "creating swapfile %s", self->path); self->o = g_open (self->path, O_RDWR|O_CREAT, 0770); if (self->o == -1) g_warning ("%s: Could not open '%s': %s", G_STRFUNC, self->path, g_strerror (errno)); self->next_pre_alloc = 256; /* reserved space for header */ self->total = 256; /* reserved space for header */ self->foffset = 0; gegl_buffer_header_init (&self->header, backend->priv->tile_width, backend->priv->tile_height, backend->priv->px_size, backend->priv->format ); gegl_tile_backend_file_write_header (self); self->foffset = 256; fsync (self->o); self->i = dup (self->o); /*self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));*/ self->next_pre_alloc = 256; /* reserved space for header */ self->total = 256; /* reserved space for header */ g_assert (self->i != -1); g_assert (self->o != -1); } }
/* sets up the node's bounding box */ static void gegl_have_visitor_visit_node (GeglVisitor *self, GeglNode *node) { GeglOperation *operation; glong time = gegl_ticks (); GEGL_VISITOR_CLASS (gegl_have_visitor_parent_class)->visit_node (self, node); if (!node) return; operation = node->operation; g_mutex_lock (node->mutex); node->have_rect = gegl_operation_get_bounding_box (operation); GEGL_NOTE (GEGL_DEBUG_PROCESS, "For \"%s\" have_rect = %d,%d %d×%d", gegl_node_get_debug_name (node), node->have_rect.x, node->have_rect.y, node->have_rect.width, node->have_rect.height); g_mutex_unlock (node->mutex); time = gegl_ticks () - time; gegl_instrument ("process", gegl_node_get_operation (node), time); gegl_instrument (gegl_node_get_operation (node), "defined-region", time); }
static gpointer gegl_tile_backend_swap_void_tile (GeglTileSource *self, GeglTile *tile, gint x, gint y, gint z) { GeglTileBackend *backend; GeglTileBackendSwap *tile_backend_swap; SwapEntry *entry; backend = GEGL_TILE_BACKEND (self); tile_backend_swap = GEGL_TILE_BACKEND_SWAP (backend); entry = gegl_tile_backend_swap_lookup_entry (tile_backend_swap, x, y, z); if (entry != NULL) { GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "void tile %i, %i, %i", x, y, z); gegl_tile_backend_swap_entry_destroy (tile_backend_swap, entry); } return NULL; }
GeglBuffer * gegl_buffer_load (const gchar *path) { GeglBuffer *ret; LoadInfo *info = g_slice_new0 (LoadInfo); info->path = g_strdup (path); info->i = g_open (info->path, O_RDONLY, 0770); GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "starting to load buffer %s", path); if (info->i == -1) { GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "failed top open %s for reading", path); return NULL; } { GeglBufferItem *header = gegl_buffer_read_header (info->i, &info->offset); g_assert (header); /*memcpy (&(info->header), header, sizeof (GeglBufferHeader));*/ info->header = *(&header->header); info->offset = info->header.next; /*g_free (header);*/ /* is there a pointer to a string or something we're missing? */ } info->tile_size = info->header.tile_width * info->header.tile_height * info->header.bytes_per_pixel; info->format = babl_format (info->header.description); ret = g_object_new (GEGL_TYPE_BUFFER, "format", info->format, "tile-width", info->header.tile_width, "tile-height", info->header.tile_height, "height", info->header.height, "width", info->header.width, "path", path, NULL); /* sanity check, should probably report error condition and return safely instead */ g_assert (babl_format_get_bytes_per_pixel (info->format) == info->header.bytes_per_pixel); info->tiles = gegl_buffer_read_index (info->i, &info->offset); /* load each tile */ { GList *iter; gint i = 0; for (iter = info->tiles; iter; iter = iter->next) { GeglBufferTile *entry = iter->data; guchar *data; GeglTile *tile; tile = gegl_tile_source_get_tile (GEGL_TILE_SOURCE (ret), entry->x, entry->y, entry->z); if (info->offset != entry->offset) { seekto (info, entry->offset); } /*g_assert (info->offset == entry->offset);*/ g_assert (tile); gegl_tile_lock (tile); data = gegl_tile_get_data (tile); g_assert (data); { ssize_t sz_read = read (info->i, data, info->tile_size); if(sz_read != -1) info->offset += sz_read; } /*g_assert (info->offset == entry->offset + info->tile_size);*/ gegl_tile_unlock (tile); gegl_tile_unref (tile); i++; } GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "%i tiles loaded",i); } GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "buffer loaded %s", info->path); load_info_destroy (info); return ret; }
/* reads a block of information from a geglbuffer that resides in an GInputStream, * if offset is NULL it is read from the current offsetition of the stream. If offset * is passed in the offset stored at the location is used as the initial seeking * point and will be updated with the offset after the read is completed. */ static GeglBufferItem *read_block (int i, goffset *offset) { GeglBufferBlock block; GeglBufferItem *ret; gsize byte_read = 0; gint own_size=0; if (*offset==0) return NULL; if (offset) if(lseek(i, *offset, SEEK_SET) == -1) g_warning ("failed seeking to %i", (gint)*offset); { ssize_t sz_read = read (i, &block, sizeof (GeglBufferBlock)); if(sz_read != -1) byte_read += sz_read; } GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "read block: length:%i next:%i", block.length, (guint)block.next); switch (block.flags) { case GEGL_FLAG_TILE: case GEGL_FLAG_FREE_TILE: own_size = sizeof (GeglBufferTile); break; default: g_warning ("skipping unknown type of entry flags=%i", block.flags); break; } if (block.length != own_size) { GEGL_NOTE(GEGL_DEBUG_BUFFER_LOAD, "read block of size %i which is different from expected %i only using available expected", block.length, own_size); } if (block.length == own_size || block.length > own_size ) { /* we discard any excess information that might have been added in later * versions */ ret = g_malloc (own_size); memcpy (ret, &block, sizeof (GeglBufferBlock)); { ssize_t sz_read = read (i, ((gchar*)ret) + sizeof(GeglBufferBlock), own_size - sizeof(GeglBufferBlock)); if(sz_read != -1) byte_read += sz_read; } ret->block.length = own_size; } else if (block.length < own_size) { ret = g_malloc (own_size); memcpy (ret, &block, sizeof (GeglBufferBlock)); { ssize_t sz_read = read (i, ret + sizeof(GeglBufferBlock), block.length - sizeof (GeglBufferBlock)); if(sz_read != -1) byte_read += sz_read; } ret->block.length = own_size; } else { ret = NULL; g_warning ("skipping block : of flags:%i\n", block.flags); } *offset += byte_read; return ret; }
/* 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); } } } }