|
Packit Service |
2781ba |
#include "config.h"
|
|
Packit Service |
2781ba |
#include <string.h>
|
|
Packit Service |
2781ba |
#include <math.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include <glib-object.h>
|
|
Packit Service |
2781ba |
#include <glib/gprintf.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "gegl.h"
|
|
Packit Service |
2781ba |
#include "gegl-types-internal.h"
|
|
Packit Service |
2781ba |
#include "gegl-buffer-types.h"
|
|
Packit Service |
2781ba |
#include "gegl-buffer-private.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile-storage.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile-handler-cache.h"
|
|
Packit Service |
2781ba |
#include "gegl-utils.h"
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static GeglBuffer *
|
|
Packit Service |
2781ba |
gegl_buffer_linear_new2 (const GeglRectangle *extent,
|
|
Packit Service |
2781ba |
const Babl *format,
|
|
Packit Service |
2781ba |
gint rowstride)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (extent==NULL)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_error ("got a NULL extent");
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (format==NULL)
|
|
Packit Service |
2781ba |
format = babl_format ("RGBA float");
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (rowstride <= 0)
|
|
Packit Service |
2781ba |
rowstride = extent->width;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* creating a linear buffer for GeglBuffer is a matter of
|
|
Packit Service |
2781ba |
* requesting the correct parameters when creating the
|
|
Packit Service |
2781ba |
* buffer
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
return g_object_new (GEGL_TYPE_BUFFER,
|
|
Packit Service |
2781ba |
"x", extent->x,
|
|
Packit Service |
2781ba |
"y", extent->y,
|
|
Packit Service |
2781ba |
"shift-x", extent->x,
|
|
Packit Service |
2781ba |
"shift-y", extent->y,
|
|
Packit Service |
2781ba |
"width", extent->width,
|
|
Packit Service |
2781ba |
"height", extent->height,
|
|
Packit Service |
2781ba |
"tile-width", rowstride,
|
|
Packit Service |
2781ba |
"tile-height", extent->height,
|
|
Packit Service |
2781ba |
"format", format,
|
|
Packit Service |
2781ba |
NULL);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
GeglBuffer *
|
|
Packit Service |
2781ba |
gegl_buffer_linear_new (const GeglRectangle *extent,
|
|
Packit Service |
2781ba |
const Babl *format)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
return gegl_buffer_linear_new2 (extent, format, 0);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* XXX:
|
|
Packit Service |
2781ba |
* this should probably be abstracted into a gegl_buffer_cache_insert_tile */
|
|
Packit Service |
2781ba |
void gegl_tile_handler_cache_insert (GeglTileHandlerCache *cache,
|
|
Packit Service |
2781ba |
GeglTile *tile,
|
|
Packit Service |
2781ba |
gint x,
|
|
Packit Service |
2781ba |
gint y,
|
|
Packit Service |
2781ba |
gint z);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
GeglBuffer *
|
|
Packit Service |
2781ba |
gegl_buffer_linear_new_from_data (const gpointer data,
|
|
Packit Service |
2781ba |
const Babl *format,
|
|
Packit Service |
2781ba |
const GeglRectangle *extent,
|
|
Packit Service |
2781ba |
gint rowstride,
|
|
Packit Service |
2781ba |
GDestroyNotify destroy_fn,
|
|
Packit Service |
2781ba |
gpointer destroy_fn_data)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglBuffer *buffer;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (format);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (rowstride <= 0) /* handle both 0 and negative coordinates as a request
|
|
Packit Service |
2781ba |
* for a rowstride, negative rowstrides are not supported.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
rowstride = extent->width;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
rowstride = rowstride / babl_format_get_bytes_per_pixel (format);
|
|
Packit Service |
2781ba |
buffer = gegl_buffer_linear_new2 (extent, format, rowstride);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglTile *tile = gegl_tile_new_bare ();
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
tile->tile_storage = buffer->tile_storage;
|
|
Packit Service |
2781ba |
tile->x = 0;
|
|
Packit Service |
2781ba |
tile->y = 0;
|
|
Packit Service |
2781ba |
tile->z = 0;
|
|
Packit Service |
2781ba |
tile->next_shared = tile;
|
|
Packit Service |
2781ba |
tile->prev_shared = tile;
|
|
Packit Service |
2781ba |
gegl_tile_set_data_full (tile,
|
|
Packit Service |
2781ba |
(gpointer) data,
|
|
Packit Service |
2781ba |
babl_format_get_bytes_per_pixel (format) * rowstride * extent->height,
|
|
Packit Service |
2781ba |
destroy_fn,
|
|
Packit Service |
2781ba |
destroy_fn_data);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (buffer->tile_storage->cache)
|
|
Packit Service |
2781ba |
gegl_tile_handler_cache_insert (buffer->tile_storage->cache, tile, 0, 0, 0);
|
|
Packit Service |
2781ba |
gegl_tile_unref (tile);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return buffer;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* the information kept about a linear buffer, multiple requests can
|
|
Packit Service |
2781ba |
* be handled by the same structure, the multiple clients would have
|
|
Packit Service |
2781ba |
* an immediate shared access to the linear buffer.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
typedef struct {
|
|
Packit Service |
2781ba |
gpointer buf;
|
|
Packit Service |
2781ba |
GeglRectangle extent;
|
|
Packit Service |
2781ba |
const Babl *format;
|
|
Packit Service |
2781ba |
gint refs;
|
|
Packit Service |
2781ba |
} BufferInfo;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* FIXME: make this use direct data access in more cases than the
|
|
Packit Service |
2781ba |
* case of the base buffer.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
gpointer *
|
|
Packit Service |
2781ba |
gegl_buffer_linear_open (GeglBuffer *buffer,
|
|
Packit Service |
2781ba |
const GeglRectangle *extent, /* if NULL, use buf */
|
|
Packit Service |
2781ba |
gint *rowstride,/* returns rowstride */
|
|
Packit Service |
2781ba |
const Babl *format) /* if NULL, from buf */
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (!format)
|
|
Packit Service |
2781ba |
format = buffer->soft_format;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (extent == NULL)
|
|
Packit Service |
2781ba |
extent=&buffer->extent;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*gegl_buffer_lock (buffer);*/
|
|
Packit Service |
2781ba |
g_mutex_lock (buffer->tile_storage->mutex);
|
|
Packit Service |
2781ba |
if (extent->x == buffer->extent.x &&
|
|
Packit Service |
2781ba |
extent->y == buffer->extent.y &&
|
|
Packit Service |
2781ba |
extent->width == buffer->tile_width &&
|
|
Packit Service |
2781ba |
extent->height <= buffer->tile_height &&
|
|
Packit Service |
2781ba |
buffer->soft_format == format)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglTile *tile;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (buffer->tile_width <= buffer->tile_storage->tile_width);
|
|
Packit Service |
2781ba |
g_assert (buffer->tile_height == buffer->tile_storage->tile_height);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
tile = g_object_get_data (G_OBJECT (buffer), "linear-tile");
|
|
Packit Service |
2781ba |
g_assert (tile == NULL); /* We need to reference count returned direct
|
|
Packit Service |
2781ba |
* linear buffers to allow multiple open like
|
|
Packit Service |
2781ba |
* the copying case.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
tile = gegl_tile_source_get_tile ((GeglTileSource*) (buffer),
|
|
Packit Service |
2781ba |
0,0,0);
|
|
Packit Service |
2781ba |
g_assert (tile);
|
|
Packit Service |
2781ba |
gegl_tile_lock (tile);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_object_set_data (G_OBJECT (buffer), "linear-tile", tile);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if(rowstride)*rowstride = buffer->tile_storage->tile_width * babl_format_get_bytes_per_pixel (format);
|
|
Packit Service |
2781ba |
return (gpointer)gegl_tile_get_data (tile);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
/* first check if there is a linear buffer, share the existing buffer if one
|
|
Packit Service |
2781ba |
* exists.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GList *linear_buffers;
|
|
Packit Service |
2781ba |
GList *iter;
|
|
Packit Service |
2781ba |
BufferInfo *info = NULL;
|
|
Packit Service |
2781ba |
linear_buffers = g_object_get_data (G_OBJECT (buffer), "linear-buffers");
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (iter = linear_buffers; iter; iter=iter->next)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
info = iter->data;
|
|
Packit Service |
2781ba |
if (info->format == format &&
|
|
Packit Service |
2781ba |
info->extent.x == buffer->extent.x &&
|
|
Packit Service |
2781ba |
info->extent.y == buffer->extent.y &&
|
|
Packit Service |
2781ba |
info->extent.width == buffer->extent.width &&
|
|
Packit Service |
2781ba |
info->extent.height == buffer->extent.height
|
|
Packit Service |
2781ba |
)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
info->refs++;
|
|
Packit Service |
2781ba |
g_print ("!!!!!! sharing a linear buffer!!!!!\n");
|
|
Packit Service |
2781ba |
return info->buf;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
BufferInfo *info = g_new0 (BufferInfo, 1);
|
|
Packit Service |
2781ba |
GList *linear_buffers;
|
|
Packit Service |
2781ba |
gint rs;
|
|
Packit Service |
2781ba |
linear_buffers = g_object_get_data (G_OBJECT (buffer), "linear-buffers");
|
|
Packit Service |
2781ba |
linear_buffers = g_list_append (linear_buffers, info);
|
|
Packit Service |
2781ba |
g_object_set_data (G_OBJECT (buffer), "linear-buffers", linear_buffers);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
info->extent = *extent;
|
|
Packit Service |
2781ba |
info->format = format;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
rs = info->extent.width * babl_format_get_bytes_per_pixel (format);
|
|
Packit Service |
2781ba |
if(rowstride)*rowstride = rs;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
info->buf = gegl_malloc (rs * info->extent.height);
|
|
Packit Service |
2781ba |
gegl_buffer_get_unlocked (buffer, 1.0, &info->extent, format, info->buf, rs);
|
|
Packit Service |
2781ba |
return info->buf;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
return NULL;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_buffer_linear_close (GeglBuffer *buffer,
|
|
Packit Service |
2781ba |
gpointer linear)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglTile *tile;
|
|
Packit Service |
2781ba |
tile = g_object_get_data (G_OBJECT (buffer), "linear-tile");
|
|
Packit Service |
2781ba |
if (tile)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gegl_tile_unlock (tile);
|
|
Packit Service |
2781ba |
gegl_tile_unref (tile);
|
|
Packit Service |
2781ba |
g_object_set_data (G_OBJECT (buffer), "linear-tile", NULL);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GList *linear_buffers;
|
|
Packit Service |
2781ba |
GList *iter;
|
|
Packit Service |
2781ba |
linear_buffers = g_object_get_data (G_OBJECT (buffer), "linear-buffers");
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (iter = linear_buffers; iter; iter=iter->next)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
BufferInfo *info = iter->data;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (info->buf == linear)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
info->refs--;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (info->refs>0)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_print ("EEeeek! %s\n", G_STRLOC);
|
|
Packit Service |
2781ba |
return; /* there are still others holding a reference to
|
|
Packit Service |
2781ba |
* this linear buffer
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
linear_buffers = g_list_remove (linear_buffers, info);
|
|
Packit Service |
2781ba |
g_object_set_data (G_OBJECT (buffer), "linear-buffers", linear_buffers);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_mutex_unlock (buffer->tile_storage->mutex);
|
|
Packit Service |
2781ba |
/* XXX: potential race */
|
|
Packit Service |
2781ba |
gegl_buffer_set (buffer, &info->extent, 0, info->format, info->buf, 0);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_free (info->buf);
|
|
Packit Service |
2781ba |
g_free (info);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_mutex_lock (buffer->tile_storage->mutex);
|
|
Packit Service |
2781ba |
break;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
/*gegl_buffer_unlock (buffer);*/
|
|
Packit Service |
2781ba |
g_mutex_unlock (buffer->tile_storage->mutex);
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
}
|