static inline void set_half (GeglTile * dst_tile, GeglTile * src_tile, gint width, gint height, const Babl * format, gint i, gint j) { guchar *dst_data = gegl_tile_get_data (dst_tile); guchar *src_data = gegl_tile_get_data (src_tile); gint components = babl_format_get_n_components (format); gint bpp = babl_format_get_bytes_per_pixel (format); if (i) dst_data += bpp * width / 2; if (j) dst_data += bpp * width * height / 2; if (babl_format_get_type (format, 0) == babl_type ("float")) { downscale_float (components, width, height, width * bpp, src_data, dst_data); } else if (babl_format_get_type (format, 0) == babl_type ("u8")) { downscale_u8 (components, width, height, width * bpp, src_data, dst_data); } else { set_half_nearest (dst_tile, src_tile, width, height, format, i, j); } }
/* fixme: make the api of this, as well as blank be the * same as the downscale functions */ static inline void set_half_nearest (GeglTile *dst_tile, GeglTile *src_tile, gint width, gint height, const Babl *format, gint i, gint j) { guchar *dst_data = gegl_tile_get_data (dst_tile); guchar *src_data = gegl_tile_get_data (src_tile); gint bpp = babl_format_get_bytes_per_pixel (format); gint x, y; for (y = 0; y < height / 2; y++) { guchar *dst = dst_data + ( ( (y + j * (height / 2)) * width ) + i * (width / 2) ) * bpp; guchar *src = src_data + (y * 2 * width) * bpp; for (x = 0; x < width / 2; x++) { memcpy (dst, src, bpp); dst += bpp; src += bpp * 2; } } }
static gpointer gegl_tile_backend_file_set_tile (GeglTileSource *self, GeglTile *tile, gint x, gint y, gint z) { GeglTileBackend *backend; GeglTileBackendFile *tile_backend_file; GeglBufferTile *entry; backend = GEGL_TILE_BACKEND (self); tile_backend_file = GEGL_TILE_BACKEND_FILE (backend); entry = gegl_tile_backend_file_lookup_entry (tile_backend_file, x, y, z); if (entry == NULL) { entry = gegl_tile_backend_file_file_entry_new (tile_backend_file); entry->x = x; entry->y = y; entry->z = z; g_hash_table_insert (tile_backend_file->index, entry, entry); } entry->rev = gegl_tile_get_rev (tile); gegl_tile_backend_file_file_entry_write (tile_backend_file, entry, gegl_tile_get_data (tile)); gegl_tile_mark_as_stored (tile); return NULL; }
static gpointer gegl_tile_backend_swap_set_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); gegl_tile_backend_swap_ensure_exist (); if (entry == NULL) { entry = gegl_tile_backend_swap_entry_create (x, y, z); entry->offset = gegl_tile_backend_swap_find_offset (gegl_tile_backend_get_tile_size (backend)); g_hash_table_insert (tile_backend_swap->index, entry, entry); } gegl_tile_backend_swap_entry_write (tile_backend_swap, entry, gegl_tile_get_data (tile)); gegl_tile_mark_as_stored (tile); return NULL; }
/* this is the only place that actually should * instantiate tiles, when the cache is large enough * that should make sure we don't hit this function * too often. */ static GeglTile * gegl_tile_backend_file_get_tile (GeglTileSource *self, gint x, gint y, gint z) { GeglTileBackend *backend; GeglTileBackendFile *tile_backend_file; GeglBufferTile *entry; GeglTile *tile = NULL; gint tile_size; backend = GEGL_TILE_BACKEND (self); tile_backend_file = GEGL_TILE_BACKEND_FILE (backend); entry = gegl_tile_backend_file_lookup_entry (tile_backend_file, x, y, z); if (!entry) return NULL; tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); tile = gegl_tile_new (tile_size); gegl_tile_set_rev (tile, entry->rev); gegl_tile_mark_as_stored (tile); gegl_tile_backend_file_file_entry_read (tile_backend_file, entry, gegl_tile_get_data (tile)); return tile; }
static GeglTile * gegl_tile_backend_swap_get_tile (GeglTileSource *self, gint x, gint y, gint z) { GeglTileBackend *backend; GeglTileBackendSwap *tile_backend_swap; SwapEntry *entry; GeglTile *tile = NULL; gint tile_size; 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) return NULL; tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); tile = gegl_tile_new (tile_size); gegl_tile_mark_as_stored (tile); gegl_tile_backend_swap_entry_read (tile_backend_swap, entry, gegl_tile_get_data (tile)); return tile; }
static GeglTile * get_tile (GeglTileSource *gegl_tile_source, gint x, gint y, gint z) { GeglTileSource *source = ((GeglTileHandler *) gegl_tile_source)->source; GeglTileHandlerEmpty *empty = (GeglTileHandlerEmpty *) gegl_tile_source; GeglTile *tile = NULL; if (source) tile = gegl_tile_source_get_tile (source, x, y, z); if (tile) return tile; if (G_UNLIKELY(!empty->tile)) { gint tile_size = gegl_tile_backend_get_tile_size (empty->backend); empty->tile = gegl_tile_new (tile_size); memset (gegl_tile_get_data (empty->tile), 0x00, tile_size); empty->tile->is_zero_tile = 1; } return gegl_tile_handler_dup_tile (GEGL_TILE_HANDLER (empty), empty->tile, x, y, z); }
static inline void set_half (GeglTile * dst_tile, GeglTile * src_tile, gint width, gint height, const Babl * format, gint i, gint j) { guchar *dst_data = gegl_tile_get_data (dst_tile); guchar *src_data = gegl_tile_get_data (src_tile); gint bpp = babl_format_get_bytes_per_pixel (format); if (i) dst_data += bpp * width / 2; if (j) dst_data += bpp * width * height / 2; gegl_downscale_2x2 (format, width, height, src_data, width * bpp, dst_data, width * bpp); }
int main(int argc, char **argv) { GeglTile *tile; GeglBuffer *buf_a, *buf_b, *buf_small_lin, *buf_big_lin; gpointer shared_data = NULL; gboolean result = TRUE; gpointer scratch_data; GeglRectangle buffer_rect = *GEGL_RECTANGLE(0, 0, 128, 128); gegl_init (&argc, &argv); buf_a = gegl_buffer_new (&buffer_rect, babl_format("RGBA u8")); buf_b = gegl_buffer_new (&buffer_rect, babl_format("RGBA u8")); buf_small_lin = gegl_buffer_linear_new (&buffer_rect, babl_format("RGBA float")); buf_big_lin = gegl_buffer_linear_new (GEGL_RECTANGLE(0, 0, 1024, 1024), babl_format("RGBA float")); tile = gegl_tile_source_get_tile (GEGL_TILE_SOURCE (buf_a), 0, 0, 0); shared_data = gegl_tile_get_data(tile); gegl_tile_unref (tile); if (!assert_is_empty (buf_a, 0, 0, shared_data)) result = FALSE; if (!assert_is_empty (buf_b, 0, 1, shared_data)) result = FALSE; if (!assert_is_empty (buf_a, 0, 0, shared_data)) result = FALSE; if (!assert_is_empty (buf_b, 0, 1, shared_data)) result = FALSE; if (!assert_is_empty (buf_small_lin, 0, 0, shared_data)) result = FALSE; if (!assert_is_unshared (buf_big_lin, 0, 0, shared_data)) result = FALSE; scratch_data = gegl_malloc(4 * buffer_rect.width * buffer_rect.height); gegl_buffer_get (buf_a, &buffer_rect, 1.0, babl_format("RGBA u8"), scratch_data, 0, GEGL_ABYSS_NONE); gegl_buffer_get (buf_b, &buffer_rect, 1.0, babl_format("RGBA u8"), scratch_data, 0, GEGL_ABYSS_NONE); gegl_buffer_get (buf_small_lin, &buffer_rect, 1.0, babl_format("RGBA u8"), scratch_data, 0, GEGL_ABYSS_NONE); gegl_buffer_get (buf_big_lin, &buffer_rect, 1.0, babl_format("RGBA u8"), scratch_data, 0, GEGL_ABYSS_NONE); gegl_free (scratch_data); g_object_unref(buf_a); g_object_unref(buf_b); g_object_unref(buf_small_lin); g_object_unref(buf_big_lin); gegl_exit(); if (result) return SUCCESS; return FAILURE; }
static void get_tile (GeglBufferIterator *iter, int index) { GeglBufferIteratorPriv *priv = iter->priv; SubIterState *sub = &priv->sub_iter[index]; GeglBuffer *buf = priv->sub_iter[index].buffer; if (sub->linear_tile) { sub->current_tile = sub->linear_tile; sub->real_roi = buf->extent; sub->current_tile_mode = GeglIteratorTileMode_LinearTile; } else { int shift_x = buf->shift_x; int shift_y = buf->shift_y; int tile_width = buf->tile_width; int tile_height = buf->tile_height; int tile_x = gegl_tile_indice (iter->roi[index].x + shift_x, tile_width); int tile_y = gegl_tile_indice (iter->roi[index].y + shift_y, tile_height); sub->current_tile = gegl_tile_source_get_tile ((GeglTileSource *)(buf), tile_x, tile_y, 0); if (sub->flags & GEGL_BUFFER_WRITE) gegl_tile_lock (sub->current_tile); sub->real_roi.x = (tile_x * tile_width) - shift_x; sub->real_roi.y = (tile_y * tile_height) - shift_y; sub->real_roi.width = tile_width; sub->real_roi.height = tile_height; sub->current_tile_mode = GeglIteratorTileMode_DirectTile; } sub->row_stride = buf->tile_width * sub->format_bpp; iter->data[index] = gegl_tile_get_data (sub->current_tile); }
static inline void set_blank (GeglTile *dst_tile, gint width, gint height, const Babl *format, gint i, gint j) { guchar *dst_data = gegl_tile_get_data (dst_tile); gint bpp = babl_format_get_bytes_per_pixel (format); gint rowstride = width * bpp; gint scanline; gint bytes = width * bpp / 2; guchar *dst = dst_data + j * height / 2 * rowstride + i * rowstride / 2; for (scanline = 0; scanline < height / 2; scanline++) { memset (dst, 0x0, bytes); dst += rowstride; } }
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 gboolean assert_is_empty (GeglBuffer *buf, gint x, gint y, gpointer shared_data) { gboolean result = TRUE; GeglTile *tile = gegl_tile_source_get_tile (GEGL_TILE_SOURCE (buf), x, y, 0); if (!tile->is_zero_tile) { g_warning ("Not a zero tile"); result = FALSE; } if (gegl_tile_get_data(tile) != shared_data) { g_warning ("Not using shared data"); result = FALSE; } gegl_tile_unref (tile); return result; }
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; }
static gboolean gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i) { GeglBuffer *buffer = i->buffer; gint tile_width = buffer->tile_storage->tile_width; gint tile_height = buffer->tile_storage->tile_height; gint buffer_shift_x = buffer->shift_x; gint buffer_shift_y = buffer->shift_y; gint buffer_x = i->roi.x + buffer_shift_x; gint buffer_y = i->roi.y + buffer_shift_y; if (i->roi.width == 0 || i->roi.height == 0) return FALSE; gulp: /* unref previously held tile */ if (i->tile) { if (i->write && i->subrect.width == tile_width && i->same_format) { gegl_tile_unlock (i->tile); } gegl_tile_unref (i->tile); i->tile = NULL; } if (i->next_col < i->roi.width) { /* return tile on this row */ gint tiledx = buffer_x + i->next_col; gint tiledy = buffer_y + i->next_row; gint offsetx = gegl_tile_offset (tiledx, tile_width); gint offsety = gegl_tile_offset (tiledy, tile_height); { i->subrect.x = offsetx; i->subrect.y = offsety; if (i->roi.width + offsetx - i->next_col < tile_width) i->subrect.width = (i->roi.width + offsetx - i->next_col) - offsetx; else i->subrect.width = tile_width - offsetx; if (i->roi.height + offsety - i->next_row < tile_height) i->subrect.height = (i->roi.height + offsety - i->next_row) - offsety; else i->subrect.height = tile_height - offsety; i->tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer), gegl_tile_indice (tiledx, tile_width), gegl_tile_indice (tiledy, tile_height), 0); if (i->write && i->subrect.width == tile_width && i->same_format) { gegl_tile_lock (i->tile); } i->data = gegl_tile_get_data (i->tile); { gint bpp = babl_format_get_bytes_per_pixel (i->buffer->soft_format); i->rowstride = bpp * tile_width; i->sub_data = (guchar*)(i->data) + bpp * (i->subrect.y * tile_width + i->subrect.x); } i->col = i->next_col; i->row = i->next_row; i->next_col += tile_width - offsetx; i->roi2.x = i->roi.x + i->col; i->roi2.y = i->roi.y + i->row; i->roi2.width = i->subrect.width; i->roi2.height = i->subrect.height; return TRUE; } } else /* move down to next row */ { gint tiledy; gint offsety; i->row = i->next_row; i->col = i->next_col; tiledy = buffer_y + i->next_row; offsety = gegl_tile_offset (tiledy, tile_height); i->next_row += tile_height - offsety; i->next_col=0; if (i->next_row < i->roi.height) { goto gulp; /* return the first tile in the next row */ } return FALSE; } return FALSE; }
static void gegl_tile_backend_swap_entry_read (GeglTileBackendSwap *self, SwapEntry *entry, guchar *dest) { gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)); gint to_be_read = tile_size; guint64 offset = entry->offset; gegl_tile_backend_swap_ensure_exist (); if (entry->link || in_progress) { ThreadParams *queued_op = NULL; g_mutex_lock (&mutex); if (entry->link) queued_op = entry->link->data; else if (in_progress && in_progress->entry == entry) queued_op = in_progress; if (queued_op) { memcpy (dest, gegl_tile_get_data (queued_op->tile), to_be_read); g_mutex_unlock (&mutex); GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "read entry %i, %i, %i from queue", entry->x, entry->y, entry->z); return; } g_mutex_unlock (&mutex); } if (in_offset != offset) { if (lseek (in_fd, offset, SEEK_SET) < 0) { g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno)); return; } in_offset = offset; } while (to_be_read > 0) { GError *error = NULL; gint byte_read; byte_read = read (in_fd, dest + tile_size - to_be_read, to_be_read); if (byte_read <= 0) { g_message ("unable to read tile data from swap: " "%s (%d/%d bytes read) %s", g_strerror (errno), byte_read, to_be_read, error?error->message:"--"); return; } to_be_read -= byte_read; in_offset += byte_read; } GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "read entry %i, %i, %i from %i", entry->x, entry->y, entry->z, (gint)offset); }
static void inline gegl_sampler_get_pixel (GeglSampler *sampler, gint x, gint y, gpointer data, GeglAbyssPolicy repeat_mode) { GeglSamplerNearest *nearest_sampler = (GeglSamplerNearest*)(sampler); GeglBuffer *buffer = sampler->buffer; const GeglRectangle *abyss = &buffer->abyss; guchar *buf = data; if (y < abyss->y || x < abyss->x || y >= abyss->y + abyss->height || x >= abyss->x + abyss->width) { switch (repeat_mode) { case GEGL_ABYSS_CLAMP: x = CLAMP (x, abyss->x, abyss->x+abyss->width-1); y = CLAMP (y, abyss->y, abyss->y+abyss->height-1); break; case GEGL_ABYSS_LOOP: x = abyss->x + GEGL_REMAINDER (x - abyss->x, abyss->width); y = abyss->y + GEGL_REMAINDER (y - abyss->y, abyss->height); break; case GEGL_ABYSS_BLACK: { gfloat color[4] = {0.0, 0.0, 0.0, 1.0}; babl_process (babl_fish (gegl_babl_rgba_linear_float (), sampler->format), color, buf, 1); return; } case GEGL_ABYSS_WHITE: { gfloat color[4] = {1.0, 1.0, 1.0, 1.0}; babl_process (babl_fish (gegl_babl_rgba_linear_float (), sampler->format), color, buf, 1); return; } default: case GEGL_ABYSS_NONE: memset (buf, 0x00, babl_format_get_bytes_per_pixel (sampler->format)); return; } } gegl_buffer_lock (sampler->buffer); { gint tile_width = buffer->tile_width; gint tile_height = buffer->tile_height; gint tiledy = y + buffer->shift_y; gint tiledx = x + buffer->shift_x; gint indice_x = gegl_tile_indice (tiledx, tile_width); gint indice_y = gegl_tile_indice (tiledy, tile_height); GeglTile *tile = nearest_sampler->hot_tile; if (!(tile && tile->x == indice_x && tile->y == indice_y)) { if (gegl_config_threads()>1) g_rec_mutex_lock (&buffer->tile_storage->mutex); if (tile) gegl_tile_unref (tile); tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer), indice_x, indice_y, 0); nearest_sampler->hot_tile = tile; if (gegl_config_threads()>1) g_rec_mutex_unlock (&buffer->tile_storage->mutex); } if (tile) { gint tile_origin_x = indice_x * tile_width; gint tile_origin_y = indice_y * tile_height; gint offsetx = tiledx - tile_origin_x; gint offsety = tiledy - tile_origin_y; guchar *tp = gegl_tile_get_data (tile) + (offsety * tile_width + offsetx) * nearest_sampler->buffer_bpp; babl_process (sampler->fish, tp, buf, 1); } } gegl_buffer_unlock (sampler->buffer); }
static GeglTile * gimp_tile_handler_projection_validate (GeglTileSource *source, GeglTile *tile, gint x, gint y) { GimpTileHandlerProjection *projection; cairo_region_t *tile_region; cairo_rectangle_int_t tile_rect; projection = GIMP_TILE_HANDLER_PROJECTION (source); if (cairo_region_is_empty (projection->dirty_region)) return tile; tile_region = cairo_region_copy (projection->dirty_region); tile_rect.x = x * projection->tile_width; tile_rect.y = y * projection->tile_height; tile_rect.width = projection->tile_width; tile_rect.height = projection->tile_height; cairo_region_intersect_rectangle (tile_region, &tile_rect); if (! cairo_region_is_empty (tile_region)) { gint tile_bpp; gint tile_stride; gint n_rects; gint i; if (! tile) tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (source), x, y, 0); cairo_region_subtract_rectangle (projection->dirty_region, &tile_rect); tile_bpp = babl_format_get_bytes_per_pixel (projection->format); tile_stride = tile_bpp * projection->tile_width; gegl_tile_lock (tile); n_rects = cairo_region_num_rectangles (tile_region); #if 0 g_printerr ("%d ", n_rects); #endif for (i = 0; i < n_rects; i++) { cairo_rectangle_int_t blit_rect; cairo_region_get_rectangle (tile_region, i, &blit_rect); #if 0 g_printerr ("constructing projection at %d %d %d %d\n", blit_rect.x, blit_rect.y, blit_rect.width, blit_rect.height); #endif gegl_node_blit (projection->graph, 1.0, GEGL_RECTANGLE (blit_rect.x, blit_rect.y, blit_rect.width, blit_rect.height), projection->format, gegl_tile_get_data (tile) + (blit_rect.y % projection->tile_height) * tile_stride + (blit_rect.x % projection->tile_width) * tile_bpp, tile_stride, GEGL_ABYSS_NONE); } gegl_tile_unlock (tile); } cairo_region_destroy (tile_region); return tile; }
/* FIXME: make this use direct data access in more cases than the * case of the base buffer. */ gpointer * gegl_buffer_linear_open (GeglBuffer *buffer, const GeglRectangle *extent, /* if NULL, use buf */ gint *rowstride,/* returns rowstride */ const Babl *format) /* if NULL, from buf */ { if (!format) format = buffer->soft_format; if (extent == NULL) extent=&buffer->extent; /*gegl_buffer_lock (buffer);*/ g_rec_mutex_lock (&buffer->tile_storage->mutex); if (extent->x == buffer->extent.x && extent->y == buffer->extent.y && extent->width == buffer->tile_width && extent->height <= buffer->tile_height && buffer->soft_format == format) { GeglTile *tile; g_assert (buffer->tile_width <= buffer->tile_storage->tile_width); g_assert (buffer->tile_height == buffer->tile_storage->tile_height); tile = g_object_get_data (G_OBJECT (buffer), "linear-tile"); g_assert (tile == NULL); /* We need to reference count returned direct * linear buffers to allow multiple open like * the copying case. */ tile = gegl_tile_source_get_tile ((GeglTileSource*) (buffer), 0,0,0); g_assert (tile); gegl_tile_lock (tile); g_object_set_data (G_OBJECT (buffer), "linear-tile", tile); if(rowstride)*rowstride = buffer->tile_storage->tile_width * babl_format_get_bytes_per_pixel (format); return (gpointer)gegl_tile_get_data (tile); } /* first check if there is a linear buffer, share the existing buffer if one * exists. */ { GList *linear_buffers; GList *iter; BufferInfo *info = NULL; linear_buffers = g_object_get_data (G_OBJECT (buffer), "linear-buffers"); for (iter = linear_buffers; iter; iter=iter->next) { info = iter->data; if (info->format == format && info->extent.x == buffer->extent.x && info->extent.y == buffer->extent.y && info->extent.width == buffer->extent.width && info->extent.height == buffer->extent.height ) { info->refs++; g_print ("!!!!!! sharing a linear buffer!!!!!\n"); return info->buf; } } } { BufferInfo *info = g_new0 (BufferInfo, 1); GList *linear_buffers; gint rs; linear_buffers = g_object_get_data (G_OBJECT (buffer), "linear-buffers"); linear_buffers = g_list_append (linear_buffers, info); g_object_set_data (G_OBJECT (buffer), "linear-buffers", linear_buffers); info->extent = *extent; info->format = format; rs = info->extent.width * babl_format_get_bytes_per_pixel (format); if(rowstride)*rowstride = rs; info->buf = gegl_malloc (rs * info->extent.height); gegl_buffer_get_unlocked (buffer, 1.0, &info->extent, format, info->buf, rs, GEGL_ABYSS_NONE); return info->buf; } return NULL; }