Blame gegl/buffer/gegl-buffer.c

Packit Service 2781ba
/* This file is part of GEGL.
Packit Service 2781ba
 *
Packit Service 2781ba
 * This library is free software; you can redistribute it and/or
Packit Service 2781ba
 * modify it under the terms of the GNU Lesser General Public
Packit Service 2781ba
 * License as published by the Free Software Foundation; either
Packit Service 2781ba
 * version 3 of the License, or (at your option) any later version.
Packit Service 2781ba
 *
Packit Service 2781ba
 * This library is distributed in the hope that it will be useful,
Packit Service 2781ba
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2781ba
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 2781ba
 * Lesser General Public License for more details.
Packit Service 2781ba
 *
Packit Service 2781ba
 * You should have received a copy of the GNU Lesser General Public
Packit Service 2781ba
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit Service 2781ba
 *
Packit Service 2781ba
 * Copyright 2006-2008 Øyvind Kolås <pippin@gimp.org>
Packit Service 2781ba
 */
Packit Service 2781ba
Packit Service 2781ba
#include "config.h"
Packit Service 2781ba
Packit Service 2781ba
#include <math.h>
Packit Service 2781ba
#include <string.h>
Packit Service 2781ba
#include <errno.h>
Packit Service 2781ba
#include <stdlib.h>
Packit Service 2781ba
Packit Service 2781ba
#include <sys/types.h>
Packit Service 2781ba
#ifdef HAVE_UNISTD_H
Packit Service 2781ba
#include <unistd.h>
Packit Service 2781ba
#endif
Packit Service 2781ba
#include <errno.h>
Packit Service 2781ba
Packit Service 2781ba
#include <sys/types.h>
Packit Service 2781ba
#ifdef HAVE_UNISTD_H
Packit Service 2781ba
#include <unistd.h>
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
#ifdef G_OS_WIN32
Packit Service 2781ba
#include <process.h>
Packit Service 2781ba
#define getpid() _getpid()
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
#include <glib-object.h>
Packit Service 2781ba
#include <glib/gstdio.h>
Packit Service 2781ba
#include <glib/gprintf.h>
Packit Service 2781ba
#include <gio/gio.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.h"
Packit Service 2781ba
#include "gegl-buffer-private.h"
Packit Service 2781ba
#include "gegl-tile-handler.h"
Packit Service 2781ba
#include "gegl-tile-storage.h"
Packit Service 2781ba
#include "gegl-tile-backend.h"
Packit Service 2781ba
#include "gegl-tile-backend-file.h"
Packit Service 2781ba
#include "gegl-tile-backend-tiledir.h"
Packit Service 2781ba
#include "gegl-tile-backend-ram.h"
Packit Service 2781ba
#include "gegl-tile.h"
Packit Service 2781ba
#include "gegl-tile-handler-cache.h"
Packit Service 2781ba
#include "gegl-tile-handler-log.h"
Packit Service 2781ba
#include "gegl-tile-handler-empty.h"
Packit Service 2781ba
#include "gegl-sampler-nearest.h"
Packit Service 2781ba
#include "gegl-sampler-linear.h"
Packit Service 2781ba
#include "gegl-sampler-cubic.h"
Packit Service 2781ba
#include "gegl-sampler-lohalo.h"
Packit Service 2781ba
#include "gegl-types-internal.h"
Packit Service 2781ba
#include "gegl-utils.h"
Packit Service 2781ba
#include "gegl-id-pool.h"
Packit Service 2781ba
#include "gegl-buffer-index.h"
Packit Service 2781ba
#include "gegl-config.h"
Packit Service 2781ba
#include "gegl-buffer-cl-cache.h"
Packit Service 2781ba
Packit Service 2781ba
/* #define GEGL_BUFFER_DEBUG_ALLOCATIONS */
Packit Service 2781ba
Packit Service 2781ba
/* #define GEGL_BUFFER_DEBUG_ALLOCATIONS to print allocation stack
Packit Service 2781ba
 * traces for leaked GeglBuffers using GNU C libs backtrace_symbols()
Packit Service 2781ba
 */
Packit Service 2781ba
#ifdef HAVE_EXECINFO_H
Packit Service 2781ba
#include <execinfo.h>
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
G_DEFINE_TYPE (GeglBuffer, gegl_buffer, GEGL_TYPE_TILE_HANDLER)
Packit Service 2781ba
Packit Service 2781ba
static GObjectClass * parent_class = NULL;
Packit Service 2781ba
Packit Service 2781ba
enum
Packit Service 2781ba
{
Packit Service 2781ba
  PROP_0,
Packit Service 2781ba
  PROP_X,
Packit Service 2781ba
  PROP_Y,
Packit Service 2781ba
  PROP_WIDTH,
Packit Service 2781ba
  PROP_HEIGHT,
Packit Service 2781ba
  PROP_SHIFT_X,
Packit Service 2781ba
  PROP_SHIFT_Y,
Packit Service 2781ba
  PROP_ABYSS_X,
Packit Service 2781ba
  PROP_ABYSS_Y,
Packit Service 2781ba
  PROP_ABYSS_WIDTH,
Packit Service 2781ba
  PROP_ABYSS_HEIGHT,
Packit Service 2781ba
  PROP_TILE_WIDTH,
Packit Service 2781ba
  PROP_TILE_HEIGHT,
Packit Service 2781ba
  PROP_FORMAT,
Packit Service 2781ba
  PROP_PX_SIZE,
Packit Service 2781ba
  PROP_PIXELS,
Packit Service 2781ba
  PROP_PATH,
Packit Service 2781ba
  PROP_BACKEND
Packit Service 2781ba
};
Packit Service 2781ba
Packit Service 2781ba
enum {
Packit Service 2781ba
  CHANGED,
Packit Service 2781ba
  LAST_SIGNAL
Packit Service 2781ba
};
Packit Service 2781ba
Packit Service 2781ba
static GeglBuffer *gegl_buffer_new_from_format     (const void *babl_fmt,
Packit Service 2781ba
                                                    gint        x,
Packit Service 2781ba
                                                    gint        y,
Packit Service 2781ba
                                                    gint        width,
Packit Service 2781ba
                                                    gint        height,
Packit Service 2781ba
                                                    gint        tile_width,
Packit Service 2781ba
                                                    gint        tile_height,
Packit Service 2781ba
                                                    gboolean    use_ram);
Packit Service 2781ba
static const void *gegl_buffer_internal_get_format (GeglBuffer *buffer);
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
guint gegl_buffer_signals[LAST_SIGNAL] = { 0 };
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
static inline gint gegl_buffer_needed_tiles (gint w,
Packit Service 2781ba
                                             gint stride)
Packit Service 2781ba
{
Packit Service 2781ba
  return ((w - 1) / stride) + 1;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static inline gint gegl_buffer_needed_width (gint w,
Packit Service 2781ba
                                             gint stride)
Packit Service 2781ba
{
Packit Service 2781ba
  return gegl_buffer_needed_tiles (w, stride) * stride;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_buffer_get_property (GObject    *gobject,
Packit Service 2781ba
                          guint       property_id,
Packit Service 2781ba
                          GValue     *value,
Packit Service 2781ba
                          GParamSpec *pspec)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglBuffer *buffer = GEGL_BUFFER (gobject);
Packit Service 2781ba
Packit Service 2781ba
  switch (property_id)
Packit Service 2781ba
    {
Packit Service 2781ba
      case PROP_WIDTH:
Packit Service 2781ba
        g_value_set_int (value, buffer->extent.width);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_HEIGHT:
Packit Service 2781ba
        g_value_set_int (value, buffer->extent.height);
Packit Service 2781ba
        break;
Packit Service 2781ba
      case PROP_TILE_WIDTH:
Packit Service 2781ba
        g_value_set_int (value, buffer->tile_width);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_TILE_HEIGHT:
Packit Service 2781ba
        g_value_set_int (value, buffer->tile_height);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_PATH:
Packit Service 2781ba
          {
Packit Service 2781ba
            GeglTileBackend *backend = gegl_buffer_backend (buffer);
Packit Service 2781ba
            if (GEGL_IS_TILE_BACKEND_FILE(backend))
Packit Service 2781ba
              {
Packit Service 2781ba
                if (buffer->path)
Packit Service 2781ba
                  g_free (buffer->path);
Packit Service 2781ba
                buffer->path = NULL;
Packit Service 2781ba
                g_object_get (backend, "path", &buffer->path, NULL);
Packit Service 2781ba
              }
Packit Service 2781ba
          }
Packit Service 2781ba
          g_value_set_string (value, buffer->path);
Packit Service 2781ba
        break;
Packit Service 2781ba
      case PROP_PIXELS:
Packit Service 2781ba
        g_value_set_int (value, buffer->extent.width * buffer->extent.height);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_PX_SIZE:
Packit Service 2781ba
        g_value_set_int (value, buffer->tile_storage->px_size);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_FORMAT:
Packit Service 2781ba
        /* might already be set the first time, if it was set during
Packit Service 2781ba
         * construction, we're caching the value in the buffer itself,
Packit Service 2781ba
         * since it will never change.
Packit Service 2781ba
         */
Packit Service 2781ba
Packit Service 2781ba
        {
Packit Service 2781ba
          const Babl *format;
Packit Service 2781ba
Packit Service 2781ba
            format = buffer->soft_format;
Packit Service 2781ba
          if (format == NULL)
Packit Service 2781ba
            format = buffer->format;
Packit Service 2781ba
          if (format == NULL)
Packit Service 2781ba
            format = gegl_buffer_internal_get_format (buffer);
Packit Service 2781ba
Packit Service 2781ba
          g_value_set_pointer (value, (void*)format);
Packit Service 2781ba
        }
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_BACKEND:
Packit Service 2781ba
        g_value_set_pointer (value, buffer->backend);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_X:
Packit Service 2781ba
        g_value_set_int (value, buffer->extent.x);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_Y:
Packit Service 2781ba
        g_value_set_int (value, buffer->extent.y);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_SHIFT_X:
Packit Service 2781ba
        g_value_set_int (value, buffer->shift_x);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_SHIFT_Y:
Packit Service 2781ba
        g_value_set_int (value, buffer->shift_y);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      default:
Packit Service 2781ba
        G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
Packit Service 2781ba
        break;
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_buffer_set_property (GObject      *gobject,
Packit Service 2781ba
                          guint         property_id,
Packit Service 2781ba
                          const GValue *value,
Packit Service 2781ba
                          GParamSpec   *pspec)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglBuffer *buffer = GEGL_BUFFER (gobject);
Packit Service 2781ba
Packit Service 2781ba
  switch (property_id)
Packit Service 2781ba
    {
Packit Service 2781ba
      case PROP_X:
Packit Service 2781ba
        buffer->extent.x = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_Y:
Packit Service 2781ba
        buffer->extent.y = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_WIDTH:
Packit Service 2781ba
        buffer->extent.width = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_HEIGHT:
Packit Service 2781ba
        buffer->extent.height = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_TILE_HEIGHT:
Packit Service 2781ba
        buffer->tile_height = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_TILE_WIDTH:
Packit Service 2781ba
        buffer->tile_width = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_PATH:
Packit Service 2781ba
        if (buffer->path)
Packit Service 2781ba
          g_free (buffer->path);
Packit Service 2781ba
        buffer->path = g_value_dup_string (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_SHIFT_X:
Packit Service 2781ba
        buffer->shift_x = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_SHIFT_Y:
Packit Service 2781ba
        buffer->shift_y = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_ABYSS_X:
Packit Service 2781ba
        buffer->abyss.x = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_ABYSS_Y:
Packit Service 2781ba
        buffer->abyss.y = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_ABYSS_WIDTH:
Packit Service 2781ba
        buffer->abyss.width = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_ABYSS_HEIGHT:
Packit Service 2781ba
        buffer->abyss.height = g_value_get_int (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_FORMAT:
Packit Service 2781ba
        /* Do not set to NULL even if asked to do so by a non-overriden
Packit Service 2781ba
         * value, this is needed since a default value can not be specified
Packit Service 2781ba
         * for a gpointer paramspec
Packit Service 2781ba
         */
Packit Service 2781ba
        if (g_value_get_pointer (value))
Packit Service 2781ba
          {
Packit Service 2781ba
            const Babl *format = g_value_get_pointer (value);
Packit Service 2781ba
            /* XXX: need to check if the internal format matches, should
Packit Service 2781ba
             * perhaps do different things here depending on whether
Packit Service 2781ba
             * we are during construction or not
Packit Service 2781ba
             */
Packit Service 2781ba
            if (buffer->soft_format)
Packit Service 2781ba
              {
Packit Service 2781ba
                gegl_buffer_set_format (buffer, format);
Packit Service 2781ba
              }
Packit Service 2781ba
            else
Packit Service 2781ba
              {
Packit Service 2781ba
                buffer->format = format;
Packit Service 2781ba
              }
Packit Service 2781ba
          }
Packit Service 2781ba
        break;
Packit Service 2781ba
      case PROP_BACKEND:
Packit Service 2781ba
        if (g_value_get_pointer (value))
Packit Service 2781ba
          buffer->backend = g_value_get_pointer (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      default:
Packit Service 2781ba
        G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
Packit Service 2781ba
        break;
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
#ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS
Packit Service 2781ba
static GList *allocated_buffers_list = NULL;
Packit Service 2781ba
#endif
Packit Service 2781ba
static gint   allocated_buffers      = 0;
Packit Service 2781ba
static gint   de_allocated_buffers   = 0;
Packit Service 2781ba
Packit Service 2781ba
/* this should only be possible if this buffer matches all the buffers down to
Packit Service 2781ba
 * storage, all of those parent buffers would change size as well, no tiles
Packit Service 2781ba
 * would be voided as a result of changing the extent.
Packit Service 2781ba
 */
Packit Service 2781ba
gboolean
Packit Service 2781ba
gegl_buffer_set_extent (GeglBuffer          *buffer,
Packit Service 2781ba
                        const GeglRectangle *extent)
Packit Service 2781ba
{
Packit Service 2781ba
  g_return_val_if_fail(GEGL_IS_BUFFER(buffer), FALSE);
Packit Service 2781ba
   (*(GeglRectangle*)gegl_buffer_get_extent (buffer))=*extent;
Packit Service 2781ba
Packit Service 2781ba
  if ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->priv->header))
Packit Service 2781ba
    {
Packit Service 2781ba
      GeglBufferHeader *header =
Packit Service 2781ba
        ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->priv->header));
Packit Service 2781ba
      header->x = buffer->extent.x;
Packit Service 2781ba
      header->y = buffer->extent.y;
Packit Service 2781ba
      header->width = buffer->extent.width;
Packit Service 2781ba
      header->height = buffer->extent.height;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return TRUE;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void gegl_buffer_stats (void)
Packit Service 2781ba
{
Packit Service 2781ba
  g_warning ("Buffer statistics: allocated:%i deallocated:%i balance:%i",
Packit Service 2781ba
             allocated_buffers, de_allocated_buffers, allocated_buffers - de_allocated_buffers);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gint gegl_buffer_leaks (void)
Packit Service 2781ba
{
Packit Service 2781ba
#ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS
Packit Service 2781ba
  {
Packit Service 2781ba
    GList *leaked_buffer = NULL;
Packit Service 2781ba
Packit Service 2781ba
    for (leaked_buffer = allocated_buffers_list;
Packit Service 2781ba
         leaked_buffer != NULL;
Packit Service 2781ba
         leaked_buffer = leaked_buffer->next)
Packit Service 2781ba
      {
Packit Service 2781ba
        GeglBuffer *buffer = GEGL_BUFFER (leaked_buffer->data);
Packit Service 2781ba
Packit Service 2781ba
        g_printerr ("\n"
Packit Service 2781ba
                   "Leaked buffer allocation stack trace:\n");
Packit Service 2781ba
        g_printerr ("%s\n", buffer->alloc_stack_trace);
Packit Service 2781ba
      }
Packit Service 2781ba
  }
Packit Service 2781ba
  g_list_free (allocated_buffers_list);
Packit Service 2781ba
  allocated_buffers_list = NULL;
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
  return allocated_buffers - de_allocated_buffers;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
_gegl_buffer_drop_hot_tile (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglTileStorage *storage = buffer->tile_storage;
Packit Service 2781ba
  if (storage->hot_tile)
Packit Service 2781ba
    {
Packit Service 2781ba
      gegl_tile_unref (storage->hot_tile);
Packit Service 2781ba
      storage->hot_tile = NULL;
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_buffer_dispose (GObject *object)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglBuffer  *buffer  = GEGL_BUFFER (object);
Packit Service 2781ba
  GeglTileHandler *handler = GEGL_TILE_HANDLER (object);
Packit Service 2781ba
Packit Service 2781ba
  gegl_buffer_sample_cleanup (buffer);
Packit Service 2781ba
Packit Service 2781ba
  if (gegl_cl_is_accelerated ())
Packit Service 2781ba
    gegl_buffer_cl_cache_invalidate (GEGL_BUFFER (object), NULL);
Packit Service 2781ba
Packit Service 2781ba
  if (handler->source &&
Packit Service 2781ba
      GEGL_IS_TILE_STORAGE (handler->source))
Packit Service 2781ba
    {
Packit Service 2781ba
      GeglTileBackend *backend = gegl_buffer_backend (buffer);
Packit Service 2781ba
Packit Service 2781ba
      /* only flush non-internal backends,. */
Packit Service 2781ba
      if (!(GEGL_IS_TILE_BACKEND_FILE (backend) ||
Packit Service 2781ba
            GEGL_IS_TILE_BACKEND_RAM (backend) ||
Packit Service 2781ba
            GEGL_IS_TILE_BACKEND_TILE_DIR (backend)))
Packit Service 2781ba
        gegl_buffer_flush (buffer);
Packit Service 2781ba
Packit Service 2781ba
      gegl_tile_source_reinit (GEGL_TILE_SOURCE (handler->source));
Packit Service 2781ba
Packit Service 2781ba
#if 0
Packit Service 2781ba
      g_object_unref (handler->source);
Packit Service 2781ba
      handler->source = NULL; /* this might be a dangerous way of marking that we have already voided */
Packit Service 2781ba
#endif
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  _gegl_buffer_drop_hot_tile (buffer);
Packit Service 2781ba
Packit Service 2781ba
  G_OBJECT_CLASS (parent_class)->dispose (object);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_buffer_finalize (GObject *object)
Packit Service 2781ba
{
Packit Service 2781ba
#ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS
Packit Service 2781ba
  g_free (GEGL_BUFFER (object)->alloc_stack_trace);
Packit Service 2781ba
  allocated_buffers_list = g_list_remove (allocated_buffers_list, object);
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
  g_free (GEGL_BUFFER (object)->path);
Packit Service 2781ba
  de_allocated_buffers++;
Packit Service 2781ba
  G_OBJECT_CLASS (parent_class)->finalize (object);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglTileBackend *
Packit Service 2781ba
gegl_buffer_backend (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglTileSource *tmp = GEGL_TILE_SOURCE (buffer);
Packit Service 2781ba
Packit Service 2781ba
  if (!tmp)
Packit Service 2781ba
    return NULL;
Packit Service 2781ba
Packit Service 2781ba
  do
Packit Service 2781ba
    {
Packit Service 2781ba
      tmp = GEGL_TILE_HANDLER (tmp)->source;
Packit Service 2781ba
    } while (tmp &&
Packit Service 2781ba
             /*GEGL_IS_TILE_TRAIT (tmp) &&*/
Packit Service 2781ba
             !GEGL_IS_TILE_BACKEND (tmp));
Packit Service 2781ba
  if (!tmp &&
Packit Service 2781ba
      !GEGL_IS_TILE_BACKEND (tmp))
Packit Service 2781ba
    return NULL;
Packit Service 2781ba
Packit Service 2781ba
  return (GeglTileBackend *) tmp;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglTileStorage *
Packit Service 2781ba
gegl_buffer_tile_storage (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglTileSource *tmp = GEGL_TILE_SOURCE (buffer);
Packit Service 2781ba
Packit Service 2781ba
  do
Packit Service 2781ba
    {
Packit Service 2781ba
      tmp = ((GeglTileHandler *) (tmp))->source;
Packit Service 2781ba
    } while (!GEGL_IS_TILE_STORAGE (tmp));
Packit Service 2781ba
Packit Service 2781ba
  g_assert (tmp);
Packit Service 2781ba
Packit Service 2781ba
  return (GeglTileStorage *) tmp;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void babl_backtrack (void);
Packit Service 2781ba
Packit Service 2781ba
static void gegl_buffer_storage_changed (GeglTileStorage     *storage,
Packit Service 2781ba
                                         const GeglRectangle *rect,
Packit Service 2781ba
                                         gpointer             userdata)
Packit Service 2781ba
{
Packit Service 2781ba
  g_signal_emit_by_name (GEGL_BUFFER (userdata), "changed", rect, NULL);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GObject *
Packit Service 2781ba
gegl_buffer_constructor (GType                  type,
Packit Service 2781ba
                         guint                  n_params,
Packit Service 2781ba
                         GObjectConstructParam *params)
Packit Service 2781ba
{
Packit Service 2781ba
  GObject         *object;
Packit Service 2781ba
  GeglBuffer      *buffer;
Packit Service 2781ba
  GeglTileBackend *backend;
Packit Service 2781ba
  GeglTileHandler *handler;
Packit Service 2781ba
  GeglTileSource  *source;
Packit Service 2781ba
Packit Service 2781ba
  gint width;
Packit Service 2781ba
  gint height;
Packit Service 2781ba
  gint x;
Packit Service 2781ba
  gint y;
Packit Service 2781ba
Packit Service 2781ba
  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
Packit Service 2781ba
Packit Service 2781ba
  buffer    = GEGL_BUFFER (object);
Packit Service 2781ba
  handler   = GEGL_TILE_HANDLER (object);
Packit Service 2781ba
  source  = handler->source;
Packit Service 2781ba
  backend   = gegl_buffer_backend (buffer);
Packit Service 2781ba
Packit Service 2781ba
  x=buffer->extent.x;
Packit Service 2781ba
  y=buffer->extent.y;
Packit Service 2781ba
  width=buffer->extent.width;
Packit Service 2781ba
  height=buffer->extent.height;
Packit Service 2781ba
Packit Service 2781ba
  if (source)
Packit Service 2781ba
    {
Packit Service 2781ba
      if (GEGL_IS_TILE_STORAGE (source))
Packit Service 2781ba
        buffer->format = GEGL_TILE_STORAGE (source)->format;
Packit Service 2781ba
      else if (GEGL_IS_BUFFER (source))
Packit Service 2781ba
        buffer->format = GEGL_BUFFER (source)->format;
Packit Service 2781ba
    }
Packit Service 2781ba
  else
Packit Service 2781ba
    {
Packit Service 2781ba
      /* if no source is specified if a format is specified, we
Packit Service 2781ba
       * we need to create our own
Packit Service 2781ba
       * source (this adds a redirection buffer in between for
Packit Service 2781ba
       * all "allocated from format", type buffers.
Packit Service 2781ba
       */
Packit Service 2781ba
      if (buffer->backend)
Packit Service 2781ba
        {
Packit Service 2781ba
          void             *storage;
Packit Service 2781ba
Packit Service 2781ba
          storage = gegl_tile_storage_new (buffer->backend);
Packit Service 2781ba
Packit Service 2781ba
          source = g_object_new (GEGL_TYPE_BUFFER, "source", storage, NULL);
Packit Service 2781ba
Packit Service 2781ba
          g_object_unref (storage);
Packit Service 2781ba
Packit Service 2781ba
          gegl_tile_handler_set_source ((GeglTileHandler*)(buffer), source);
Packit Service 2781ba
          g_object_unref (source);
Packit Service 2781ba
Packit Service 2781ba
          g_signal_connect (storage, "changed",
Packit Service 2781ba
                            G_CALLBACK(gegl_buffer_storage_changed), buffer);
Packit Service 2781ba
Packit Service 2781ba
          g_assert (source);
Packit Service 2781ba
          backend = gegl_buffer_backend (GEGL_BUFFER (source));
Packit Service 2781ba
          g_assert (backend);
Packit Service 2781ba
	        g_assert (backend == buffer->backend);
Packit Service 2781ba
	      }
Packit Service 2781ba
      else if (buffer->path && g_str_equal (buffer->path, "RAM"))
Packit Service 2781ba
        {
Packit Service 2781ba
          source = GEGL_TILE_SOURCE (gegl_buffer_new_from_format (buffer->format,
Packit Service 2781ba
                                                             buffer->extent.x,
Packit Service 2781ba
                                                             buffer->extent.y,
Packit Service 2781ba
                                                             buffer->extent.width,
Packit Service 2781ba
                                                             buffer->extent.height,
Packit Service 2781ba
                                                             buffer->tile_width,
Packit Service 2781ba
                                                             buffer->tile_height, TRUE));
Packit Service 2781ba
          /* after construction,. x and y should be set to reflect
Packit Service 2781ba
           * the top level behavior exhibited by this buffer object.
Packit Service 2781ba
           */
Packit Service 2781ba
          gegl_tile_handler_set_source ((GeglTileHandler*)(buffer), source);
Packit Service 2781ba
          g_object_unref (source);
Packit Service 2781ba
Packit Service 2781ba
          g_assert (source);
Packit Service 2781ba
          backend = gegl_buffer_backend (GEGL_BUFFER (source));
Packit Service 2781ba
          g_assert (backend);
Packit Service 2781ba
        }
Packit Service 2781ba
      else if (buffer->path)
Packit Service 2781ba
        {
Packit Service 2781ba
          GeglBufferHeader *header;
Packit Service 2781ba
          void             *storage;
Packit Service 2781ba
Packit Service 2781ba
          backend = g_object_new (GEGL_TYPE_TILE_BACKEND_FILE,
Packit Service 2781ba
                                  "tile-width", 128,
Packit Service 2781ba
                                  "tile-height", 64,
Packit Service 2781ba
                                  "format", buffer->format?buffer->format:babl_format ("RGBA float"),
Packit Service 2781ba
                                  "path", buffer->path,
Packit Service 2781ba
                                  NULL);
Packit Service 2781ba
          storage = gegl_tile_storage_new (backend);
Packit Service 2781ba
Packit Service 2781ba
          source = g_object_new (GEGL_TYPE_BUFFER, "source", storage, NULL);
Packit Service 2781ba
Packit Service 2781ba
          /* after construction,. x and y should be set to reflect
Packit Service 2781ba
           * the top level behavior exhibited by this buffer object.
Packit Service 2781ba
           */
Packit Service 2781ba
          gegl_tile_handler_set_source ((GeglTileHandler*)(buffer), source);
Packit Service 2781ba
          g_object_unref (source);
Packit Service 2781ba
Packit Service 2781ba
          g_signal_connect (storage, "changed",
Packit Service 2781ba
                            G_CALLBACK(gegl_buffer_storage_changed), buffer);
Packit Service 2781ba
Packit Service 2781ba
          g_assert (source);
Packit Service 2781ba
          backend = gegl_buffer_backend (GEGL_BUFFER (source));
Packit Service 2781ba
          g_assert (backend);
Packit Service 2781ba
          header = backend->priv->header;
Packit Service 2781ba
          buffer->extent.x = header->x;
Packit Service 2781ba
          buffer->extent.y = header->y;
Packit Service 2781ba
          buffer->extent.width = header->width;
Packit Service 2781ba
          buffer->extent.height = header->height;
Packit Service 2781ba
          buffer->format = gegl_tile_backend_get_format (backend);
Packit Service 2781ba
        }
Packit Service 2781ba
      else if (buffer->format)
Packit Service 2781ba
        {
Packit Service 2781ba
          source = GEGL_TILE_SOURCE (gegl_buffer_new_from_format (buffer->format,
Packit Service 2781ba
                                                             buffer->extent.x,
Packit Service 2781ba
                                                             buffer->extent.y,
Packit Service 2781ba
                                                             buffer->extent.width,
Packit Service 2781ba
                                                             buffer->extent.height,
Packit Service 2781ba
                                                             buffer->tile_width,
Packit Service 2781ba
                                                             buffer->tile_height, FALSE));
Packit Service 2781ba
          /* after construction,. x and y should be set to reflect
Packit Service 2781ba
           * the top level behavior exhibited by this buffer object.
Packit Service 2781ba
           */
Packit Service 2781ba
          gegl_tile_handler_set_source ((GeglTileHandler*)(buffer), source);
Packit Service 2781ba
          g_object_unref (source);
Packit Service 2781ba
Packit Service 2781ba
          g_assert (source);
Packit Service 2781ba
          backend = gegl_buffer_backend (GEGL_BUFFER (source));
Packit Service 2781ba
          g_assert (backend);
Packit Service 2781ba
        }
Packit Service 2781ba
      else
Packit Service 2781ba
        {
Packit Service 2781ba
          g_warning ("not enough data to have a tile source for our buffer");
Packit Service 2781ba
        }
Packit Service 2781ba
        /* we reset the size if it seems to have been set to 0 during a on
Packit Service 2781ba
         * disk buffer creation, nasty but it does the job.
Packit Service 2781ba
         */
Packit Service 2781ba
Packit Service 2781ba
      if (buffer->extent.width == 0)
Packit Service 2781ba
        {
Packit Service 2781ba
          buffer->extent.width = width;
Packit Service 2781ba
          buffer->extent.height = height;
Packit Service 2781ba
          buffer->extent.x = x;
Packit Service 2781ba
          buffer->extent.y = y;
Packit Service 2781ba
        }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  g_assert (backend);
Packit Service 2781ba
Packit Service 2781ba
  if (buffer->extent.width == -1 &&
Packit Service 2781ba
      buffer->extent.height == -1) /* no specified extents,
Packit Service 2781ba
                                      inheriting from source */
Packit Service 2781ba
    {
Packit Service 2781ba
      if (GEGL_IS_BUFFER (source))
Packit Service 2781ba
        {
Packit Service 2781ba
          buffer->extent.x = GEGL_BUFFER (source)->extent.x;
Packit Service 2781ba
          buffer->extent.y = GEGL_BUFFER (source)->extent.y;
Packit Service 2781ba
          buffer->extent.width  = GEGL_BUFFER (source)->extent.width;
Packit Service 2781ba
          buffer->extent.height = GEGL_BUFFER (source)->extent.height;
Packit Service 2781ba
        }
Packit Service 2781ba
      else if (GEGL_IS_TILE_STORAGE (source))
Packit Service 2781ba
        {
Packit Service 2781ba
          buffer->extent.x = 0;
Packit Service 2781ba
          buffer->extent.y = 0;
Packit Service 2781ba
          buffer->extent.width  = GEGL_TILE_STORAGE (source)->width;
Packit Service 2781ba
          buffer->extent.height = GEGL_TILE_STORAGE (source)->height;
Packit Service 2781ba
        }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  if (buffer->abyss.width == 0 &&
Packit Service 2781ba
      buffer->abyss.height == 0 &&
Packit Service 2781ba
      buffer->abyss.x == 0 &&
Packit Service 2781ba
      buffer->abyss.y == 0)      /* 0 sized extent == inherit buffer extent
Packit Service 2781ba
                                  */
Packit Service 2781ba
    {
Packit Service 2781ba
      buffer->abyss.x      = buffer->extent.x;
Packit Service 2781ba
      buffer->abyss.y      = buffer->extent.y;
Packit Service 2781ba
      buffer->abyss.width  = buffer->extent.width;
Packit Service 2781ba
      buffer->abyss.height = buffer->extent.height;
Packit Service 2781ba
    }
Packit Service 2781ba
  else if (buffer->abyss.width == 0 &&
Packit Service 2781ba
           buffer->abyss.height == 0)
Packit Service 2781ba
    {
Packit Service 2781ba
      g_warning ("peculiar abyss dimensions: %i,%i %ix%i",
Packit Service 2781ba
                 buffer->abyss.x,
Packit Service 2781ba
                 buffer->abyss.y,
Packit Service 2781ba
                 buffer->abyss.width,
Packit Service 2781ba
                 buffer->abyss.height);
Packit Service 2781ba
    }
Packit Service 2781ba
  else if (buffer->abyss.width == -1 ||
Packit Service 2781ba
           buffer->abyss.height == -1)
Packit Service 2781ba
    {
Packit Service 2781ba
      buffer->abyss.x      = GEGL_BUFFER (source)->abyss.x - buffer->shift_x;
Packit Service 2781ba
      buffer->abyss.y      = GEGL_BUFFER (source)->abyss.y - buffer->shift_y;
Packit Service 2781ba
      buffer->abyss.width  = GEGL_BUFFER (source)->abyss.width;
Packit Service 2781ba
      buffer->abyss.height = GEGL_BUFFER (source)->abyss.height;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  /* intersect our own abyss with parent's abyss if it exists
Packit Service 2781ba
   */
Packit Service 2781ba
  if (GEGL_IS_BUFFER (source))
Packit Service 2781ba
    {
Packit Service 2781ba
      GeglRectangle parent;
Packit Service 2781ba
      GeglRectangle request;
Packit Service 2781ba
      GeglRectangle self;
Packit Service 2781ba
Packit Service 2781ba
      parent.x = GEGL_BUFFER (source)->abyss.x - buffer->shift_x;
Packit Service 2781ba
      parent.y = GEGL_BUFFER (source)->abyss.y - buffer->shift_y;
Packit Service 2781ba
      parent.width = GEGL_BUFFER (source)->abyss.width;
Packit Service 2781ba
      parent.height = GEGL_BUFFER (source)->abyss.height;
Packit Service 2781ba
Packit Service 2781ba
      request.x = buffer->abyss.x;
Packit Service 2781ba
      request.y = buffer->abyss.y;
Packit Service 2781ba
      request.width = buffer->abyss.width;
Packit Service 2781ba
      request.height = buffer->abyss.height;
Packit Service 2781ba
Packit Service 2781ba
      gegl_rectangle_intersect (&self, &parent, &request);
Packit Service 2781ba
Packit Service 2781ba
      buffer->abyss.x      = self.x;
Packit Service 2781ba
      buffer->abyss.y      = self.y;
Packit Service 2781ba
      buffer->abyss.width  = self.width;
Packit Service 2781ba
      buffer->abyss.height = self.height;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  /* compute our own total shift <- this should probably happen
Packit Service 2781ba
   * approximatly first */
Packit Service 2781ba
  if (GEGL_IS_BUFFER (source))
Packit Service 2781ba
    {
Packit Service 2781ba
      GeglBuffer *source_buf;
Packit Service 2781ba
Packit Service 2781ba
      source_buf = GEGL_BUFFER (source);
Packit Service 2781ba
Packit Service 2781ba
      buffer->shift_x += source_buf->shift_x;
Packit Service 2781ba
      buffer->shift_y += source_buf->shift_y;
Packit Service 2781ba
    }
Packit Service 2781ba
  else
Packit Service 2781ba
    {
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  buffer->tile_storage = gegl_buffer_tile_storage (buffer);
Packit Service 2781ba
Packit Service 2781ba
  /* intialize the soft format to be equivalent to the actual
Packit Service 2781ba
   * format
Packit Service 2781ba
   */
Packit Service 2781ba
  buffer->soft_format = buffer->format;
Packit Service 2781ba
Packit Service 2781ba
  return object;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglTile *
Packit Service 2781ba
gegl_buffer_get_tile (GeglTileSource *source,
Packit Service 2781ba
                      gint        x,
Packit Service 2781ba
                      gint        y,
Packit Service 2781ba
                      gint        z)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglTileHandler *handler = GEGL_TILE_HANDLER (source);
Packit Service 2781ba
  GeglTile    *tile   = NULL;
Packit Service 2781ba
  source = handler->source;
Packit Service 2781ba
Packit Service 2781ba
  if (source)
Packit Service 2781ba
    tile = gegl_tile_source_get_tile (source, x, y, z);
Packit Service 2781ba
  else
Packit Service 2781ba
    g_assert (0);
Packit Service 2781ba
Packit Service 2781ba
  if (tile)
Packit Service 2781ba
    {
Packit Service 2781ba
      GeglBuffer *buffer = GEGL_BUFFER (handler);
Packit Service 2781ba
Packit Service 2781ba
      /* storing information in tile, to enable the dispose function of the
Packit Service 2781ba
       * tile instance to "hook" back to the storage with correct
Packit Service 2781ba
       * coordinates.
Packit Service 2781ba
       */
Packit Service 2781ba
      {
Packit Service 2781ba
        if (!tile->tile_storage)
Packit Service 2781ba
          {
Packit Service 2781ba
            gegl_tile_lock (tile);
Packit Service 2781ba
            tile->tile_storage = buffer->tile_storage;
Packit Service 2781ba
            gegl_tile_unlock (tile);
Packit Service 2781ba
            tile->rev--;
Packit Service 2781ba
          }
Packit Service 2781ba
        tile->x = x;
Packit Service 2781ba
        tile->y = y;
Packit Service 2781ba
        tile->z = z;
Packit Service 2781ba
      }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return tile;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
static gpointer
Packit Service 2781ba
gegl_buffer_command (GeglTileSource *source,
Packit Service 2781ba
                     GeglTileCommand command,
Packit Service 2781ba
                     gint            x,
Packit Service 2781ba
                     gint            y,
Packit Service 2781ba
                     gint            z,
Packit Service 2781ba
                     gpointer        data)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglTileHandler *handler = GEGL_TILE_HANDLER (source);
Packit Service 2781ba
  switch (command)
Packit Service 2781ba
    {
Packit Service 2781ba
      case GEGL_TILE_GET:
Packit Service 2781ba
        return gegl_buffer_get_tile (source, x, y, z);
Packit Service 2781ba
      default:
Packit Service 2781ba
        return gegl_tile_handler_source_command (handler, command, x, y, z, data);
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_buffer_class_init (GeglBufferClass *class)
Packit Service 2781ba
{
Packit Service 2781ba
  GObjectClass      *gobject_class       = G_OBJECT_CLASS (class);
Packit Service 2781ba
  parent_class                = g_type_class_peek_parent (class);
Packit Service 2781ba
  gobject_class->dispose      = gegl_buffer_dispose;
Packit Service 2781ba
  gobject_class->finalize     = gegl_buffer_finalize;
Packit Service 2781ba
  gobject_class->constructor  = gegl_buffer_constructor;
Packit Service 2781ba
  gobject_class->set_property = gegl_buffer_set_property;
Packit Service 2781ba
  gobject_class->get_property = gegl_buffer_get_property;
Packit Service 2781ba
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_PX_SIZE,
Packit Service 2781ba
                                   g_param_spec_int ("px-size", "pixel-size", "size of a single pixel in bytes.",
Packit Service 2781ba
                                                     0, G_MAXINT, 0,
Packit Service 2781ba
                                                     G_PARAM_READABLE));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_PIXELS,
Packit Service 2781ba
                                   g_param_spec_int ("pixels", "pixels", "total amount of pixels in image (width x height)",
Packit Service 2781ba
                                                     0, G_MAXINT, 0,
Packit Service 2781ba
                                                     G_PARAM_READABLE));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_WIDTH,
Packit Service 2781ba
                                   g_param_spec_int ("width", "width", "pixel width of buffer",
Packit Service 2781ba
                                                     -1, G_MAXINT, -1,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_HEIGHT,
Packit Service 2781ba
                                   g_param_spec_int ("height", "height", "pixel height of buffer",
Packit Service 2781ba
                                                     -1, G_MAXINT, -1,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_X,
Packit Service 2781ba
                                   g_param_spec_int ("x", "x", "local origin's offset relative to source origin",
Packit Service 2781ba
                                                     G_MININT / 2, G_MAXINT / 2, 0,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_Y,
Packit Service 2781ba
                                   g_param_spec_int ("y", "y", "local origin's offset relative to source origin",
Packit Service 2781ba
                                                     G_MININT / 2, G_MAXINT / 2, 0,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_ABYSS_WIDTH,
Packit Service 2781ba
                                   g_param_spec_int ("abyss-width", "abyss-width", "pixel width of abyss",
Packit Service 2781ba
                                                     -1, G_MAXINT, 0,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT_ONLY));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_ABYSS_HEIGHT,
Packit Service 2781ba
                                   g_param_spec_int ("abyss-height", "abyss-height", "pixel height of abyss",
Packit Service 2781ba
                                                     -1, G_MAXINT, 0,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT_ONLY));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_ABYSS_X,
Packit Service 2781ba
                                   g_param_spec_int ("abyss-x", "abyss-x", "",
Packit Service 2781ba
                                                     G_MININT / 2, G_MAXINT / 2, 0,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT_ONLY));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_ABYSS_Y,
Packit Service 2781ba
                                   g_param_spec_int ("abyss-y", "abyss-y", "",
Packit Service 2781ba
                                                     G_MININT / 2, G_MAXINT / 2, 0,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT_ONLY));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_SHIFT_X,
Packit Service 2781ba
                                   g_param_spec_int ("shift-x", "shift-x", "",
Packit Service 2781ba
                                                     G_MININT / 2, G_MAXINT / 2, 0,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT_ONLY));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_SHIFT_Y,
Packit Service 2781ba
                                   g_param_spec_int ("shift-y", "shift-y", "",
Packit Service 2781ba
                                                     G_MININT / 2, G_MAXINT / 2, 0,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT_ONLY));
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_FORMAT,
Packit Service 2781ba
                                   g_param_spec_pointer ("format", "format", "babl format",
Packit Service 2781ba
                                                         G_PARAM_READWRITE |
Packit Service 2781ba
                                                         G_PARAM_CONSTRUCT));
Packit Service 2781ba
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_BACKEND,
Packit Service 2781ba
                                   g_param_spec_pointer ("backend", "backend", "A custom tile-backend instance to use",
Packit Service 2781ba
                                                         G_PARAM_READWRITE |
Packit Service 2781ba
                                                         G_PARAM_CONSTRUCT));
Packit Service 2781ba
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_TILE_HEIGHT,
Packit Service 2781ba
                                   g_param_spec_int ("tile-height", "tile-height", "height of a tile",
Packit Service 2781ba
                                                     -1, G_MAXINT, gegl_config()->tile_height,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT_ONLY));
Packit Service 2781ba
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_TILE_WIDTH,
Packit Service 2781ba
                                   g_param_spec_int ("tile-width", "tile-width", "width of a tile",
Packit Service 2781ba
                                                     -1, G_MAXINT, gegl_config()->tile_width,
Packit Service 2781ba
                                                     G_PARAM_READWRITE |
Packit Service 2781ba
                                                     G_PARAM_CONSTRUCT_ONLY));
Packit Service 2781ba
Packit Service 2781ba
  g_object_class_install_property (gobject_class, PROP_PATH,
Packit Service 2781ba
                                   g_param_spec_string ("path", "Path",
Packit Service 2781ba
                                                        "URI to where the buffer is stored",
Packit Service 2781ba
                                     NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
Packit Service 2781ba
Packit Service 2781ba
  gegl_buffer_signals[CHANGED] =
Packit Service 2781ba
        g_signal_new ("changed",
Packit Service 2781ba
                  G_TYPE_FROM_CLASS (gobject_class),
Packit Service 2781ba
                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
Packit Service 2781ba
                  0,
Packit Service 2781ba
                  NULL, NULL,
Packit Service 2781ba
                  g_cclosure_marshal_VOID__BOXED,
Packit Service 2781ba
                  G_TYPE_NONE, 1,
Packit Service 2781ba
                  GEGL_TYPE_RECTANGLE);
Packit Service 2781ba
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
#ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS
Packit Service 2781ba
#define MAX_N_FUNCTIONS 100
Packit Service 2781ba
static gchar *
Packit Service 2781ba
gegl_buffer_get_alloc_stack (void)
Packit Service 2781ba
{
Packit Service 2781ba
  char  *result         = NULL;
Packit Service 2781ba
#ifndef HAVE_EXECINFO_H
Packit Service 2781ba
  result = g_strdup ("backtrace() not available for this platform\n");
Packit Service 2781ba
#else
Packit Service 2781ba
  void  *functions[MAX_N_FUNCTIONS];
Packit Service 2781ba
  int    n_functions    = 0;
Packit Service 2781ba
  char **function_names = NULL;
Packit Service 2781ba
  int    i              = 0;
Packit Service 2781ba
  int    result_size    = 0;
Packit Service 2781ba
Packit Service 2781ba
  n_functions = backtrace (functions, MAX_N_FUNCTIONS);
Packit Service 2781ba
  function_names = backtrace_symbols (functions, n_functions);
Packit Service 2781ba
Packit Service 2781ba
  for (i = 0; i < n_functions; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      result_size += strlen (function_names[i]);
Packit Service 2781ba
      result_size += 1; /* for '\n' */
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  result = g_new (gchar, result_size + 1);
Packit Service 2781ba
  result[0] = '\0';
Packit Service 2781ba
Packit Service 2781ba
  for (i = 0; i < n_functions; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      strcat (result, function_names[i]);
Packit Service 2781ba
      strcat (result, "\n");
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  free (function_names);
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
  return result;
Packit Service 2781ba
}
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
void gegl_bt (void);
Packit Service 2781ba
void gegl_bt (void)
Packit Service 2781ba
{
Packit Service 2781ba
#ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS
Packit Service 2781ba
  g_print ("%s\n", gegl_buffer_get_alloc_stack ());
Packit Service 2781ba
#endif
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_buffer_init (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  buffer->tile_width = 128;
Packit Service 2781ba
  buffer->tile_height = 64;
Packit Service 2781ba
  ((GeglTileSource*)buffer)->command = gegl_buffer_command;
Packit Service 2781ba
Packit Service 2781ba
  allocated_buffers++;
Packit Service 2781ba
Packit Service 2781ba
#ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS
Packit Service 2781ba
  buffer->alloc_stack_trace = gegl_buffer_get_alloc_stack ();
Packit Service 2781ba
  allocated_buffers_list = g_list_prepend (allocated_buffers_list, buffer);
Packit Service 2781ba
#endif
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
const GeglRectangle *
Packit Service 2781ba
gegl_buffer_get_extent (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
Packit Service 2781ba
Packit Service 2781ba
  return &(buffer->extent);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
GeglBuffer *
Packit Service 2781ba
gegl_buffer_new_ram (const GeglRectangle *extent,
Packit Service 2781ba
                     const Babl          *format)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle empty={0,0,0,0};
Packit Service 2781ba
Packit Service 2781ba
  if (extent==NULL)
Packit Service 2781ba
    extent = ∅
Packit Service 2781ba
Packit Service 2781ba
  if (format==NULL)
Packit Service 2781ba
    format = babl_format ("RGBA float");
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
                       "width", extent->width,
Packit Service 2781ba
                       "height", extent->height,
Packit Service 2781ba
                       "format", format,
Packit Service 2781ba
                       "path", "RAM",
Packit Service 2781ba
                       NULL);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglBuffer *
Packit Service 2781ba
gegl_buffer_new (const GeglRectangle *extent,
Packit Service 2781ba
                 const Babl          *format)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle empty={0,0,0,0};
Packit Service 2781ba
Packit Service 2781ba
  if (extent==NULL)
Packit Service 2781ba
    extent = ∅
Packit Service 2781ba
Packit Service 2781ba
  if (format==NULL)
Packit Service 2781ba
    format = babl_format ("RGBA float");
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
                       "width", extent->width,
Packit Service 2781ba
                       "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_new_for_backend (const GeglRectangle *extent,
Packit Service 2781ba
                             void                *backend)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle rect={0,0,0,0};
Packit Service 2781ba
  const Babl *format;
Packit Service 2781ba
Packit Service 2781ba
  /* if no extent is passed in inherit from backend */
Packit Service 2781ba
  if (extent==NULL)
Packit Service 2781ba
    {
Packit Service 2781ba
      extent = ▭
Packit Service 2781ba
      rect = gegl_tile_backend_get_extent (backend);
Packit Service 2781ba
      /* if backend didnt have a rect, make it an infinite plane  */
Packit Service 2781ba
      if (gegl_rectangle_is_empty (extent))
Packit Service 2781ba
        rect = gegl_rectangle_infinite_plane ();
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  /* use the format of the backend */
Packit Service 2781ba
  format = gegl_tile_backend_get_format (backend);
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
                       "width", extent->width,
Packit Service 2781ba
                       "height", extent->height,
Packit Service 2781ba
                       "format", format,
Packit Service 2781ba
                       "backend", backend,
Packit Service 2781ba
                       NULL);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
/* FIXME: this function needs optimizing, perhaps keep a pool
Packit Service 2781ba
 * of GeglBuffer shells that can be adapted to the needs
Packit Service 2781ba
 * on runtime, and recycling them through a hashtable?
Packit Service 2781ba
 */
Packit Service 2781ba
GeglBuffer*
Packit Service 2781ba
gegl_buffer_create_sub_buffer (GeglBuffer          *buffer,
Packit Service 2781ba
                               const GeglRectangle *extent)
Packit Service 2781ba
{
Packit Service 2781ba
  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
Packit Service 2781ba
Packit Service 2781ba
#if 1
Packit Service 2781ba
  if (extent == NULL || gegl_rectangle_equal (extent, &buffer->extent))
Packit Service 2781ba
    {
Packit Service 2781ba
      g_object_ref (buffer);
Packit Service 2781ba
      return buffer;
Packit Service 2781ba
    }
Packit Service 2781ba
#else
Packit Service 2781ba
   if (extent == NULL)
Packit Service 2781ba
      extent = gegl_buffer_get_extent (buffer);
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
  if (extent->width < 0 || extent->height < 0)
Packit Service 2781ba
    {
Packit Service 2781ba
      g_warning ("avoiding creating buffer of size: %ix%i returning an empty buffer instead.\n", extent->width, extent->height);
Packit Service 2781ba
      return g_object_new (GEGL_TYPE_BUFFER,
Packit Service 2781ba
                           "source", buffer,
Packit Service 2781ba
                           "x", extent->x,
Packit Service 2781ba
                           "y", extent->y,
Packit Service 2781ba
                           "width", 0,
Packit Service 2781ba
                           "height", 0,
Packit Service 2781ba
                           NULL);
Packit Service 2781ba
    }
Packit Service 2781ba
  return g_object_new (GEGL_TYPE_BUFFER,
Packit Service 2781ba
                       "source", buffer,
Packit Service 2781ba
                       "x", extent->x,
Packit Service 2781ba
                       "y", extent->y,
Packit Service 2781ba
                       "width", extent->width,
Packit Service 2781ba
                       "height", extent->height,
Packit Service 2781ba
                       NULL);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
typedef struct TileStorageCacheItem {
Packit Service 2781ba
  GeglTileStorage *storage;
Packit Service 2781ba
  gboolean         ram;
Packit Service 2781ba
  gint             tile_width;
Packit Service 2781ba
  gint             tile_height;
Packit Service 2781ba
  const void      *babl_fmt;
Packit Service 2781ba
} TileStorageCacheItem;
Packit Service 2781ba
Packit Service 2781ba
static GStaticMutex storage_cache_mutex = G_STATIC_MUTEX_INIT;
Packit Service 2781ba
static GSList *storage_cache = NULL;
Packit Service 2781ba
Packit Service 2781ba
/* returns TRUE if it could be done */
Packit Service 2781ba
gboolean gegl_tile_storage_cached_release (GeglTileStorage *storage);
Packit Service 2781ba
gboolean gegl_tile_storage_cached_release (GeglTileStorage *storage)
Packit Service 2781ba
{
Packit Service 2781ba
  TileStorageCacheItem *item = g_object_get_data (G_OBJECT (storage), "storage-cache-item");
Packit Service 2781ba
Packit Service 2781ba
  if (!item)
Packit Service 2781ba
    return FALSE;
Packit Service 2781ba
  g_static_mutex_lock (&storage_cache_mutex);
Packit Service 2781ba
  storage_cache = g_slist_prepend (storage_cache, item);
Packit Service 2781ba
  g_static_mutex_unlock (&storage_cache_mutex);
Packit Service 2781ba
  return TRUE;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void gegl_tile_storage_cache_cleanup (void);
Packit Service 2781ba
void gegl_tile_storage_cache_cleanup (void)
Packit Service 2781ba
{
Packit Service 2781ba
  g_static_mutex_lock (&storage_cache_mutex);
Packit Service 2781ba
  for (;storage_cache; storage_cache = g_slist_remove (storage_cache, storage_cache->data))
Packit Service 2781ba
    {
Packit Service 2781ba
      TileStorageCacheItem *item = storage_cache->data;
Packit Service 2781ba
      g_object_unref (item->storage);
Packit Service 2781ba
    }
Packit Service 2781ba
  g_static_mutex_unlock (&storage_cache_mutex);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglTileStorage *
Packit Service 2781ba
gegl_tile_storage_new_cached (gint tile_width, gint tile_height,
Packit Service 2781ba
                              const void *babl_fmt, gboolean use_ram)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglTileStorage *storage = NULL;
Packit Service 2781ba
  GSList *iter;
Packit Service 2781ba
  g_static_mutex_lock (&storage_cache_mutex);
Packit Service 2781ba
  for (iter = storage_cache; iter; iter = iter->next)
Packit Service 2781ba
    {
Packit Service 2781ba
      TileStorageCacheItem *item = iter->data;
Packit Service 2781ba
      if (item->babl_fmt == babl_fmt &&
Packit Service 2781ba
          item->tile_width == tile_width &&
Packit Service 2781ba
          item->tile_height == tile_height &&
Packit Service 2781ba
          item->ram == item->ram)
Packit Service 2781ba
       {
Packit Service 2781ba
         storage = item->storage;
Packit Service 2781ba
         storage_cache = g_slist_remove (storage_cache, item);
Packit Service 2781ba
         break;
Packit Service 2781ba
       }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  if (!storage)
Packit Service 2781ba
    {
Packit Service 2781ba
      TileStorageCacheItem *item = g_new0 (TileStorageCacheItem, 1);
Packit Service 2781ba
Packit Service 2781ba
      item->tile_width = tile_width;
Packit Service 2781ba
      item->tile_height = tile_height;
Packit Service 2781ba
      item->babl_fmt = babl_fmt;
Packit Service 2781ba
Packit Service 2781ba
      if (use_ram ||
Packit Service 2781ba
          !gegl_config()->swap ||
Packit Service 2781ba
          g_str_equal (gegl_config()->swap, "RAM") ||
Packit Service 2781ba
          g_str_equal (gegl_config()->swap, "ram"))
Packit Service 2781ba
        {
Packit Service 2781ba
          GeglTileBackend *backend;
Packit Service 2781ba
          item->ram = TRUE;
Packit Service 2781ba
          backend = g_object_new (GEGL_TYPE_TILE_BACKEND_RAM,
Packit Service 2781ba
                                  "tile-width", tile_width,
Packit Service 2781ba
                                  "tile-height", tile_height,
Packit Service 2781ba
                                  "format", babl_fmt,
Packit Service 2781ba
                                  NULL);
Packit Service 2781ba
          storage = gegl_tile_storage_new (backend);
Packit Service 2781ba
        }
Packit Service 2781ba
      else
Packit Service 2781ba
        {
Packit Service 2781ba
          static gint no = 1;
Packit Service 2781ba
          GeglTileBackend *backend;
Packit Service 2781ba
Packit Service 2781ba
          gchar *filename;
Packit Service 2781ba
          gchar *path;
Packit Service 2781ba
          item->ram = FALSE;
Packit Service 2781ba
Packit Service 2781ba
#if 0
Packit Service 2781ba
          filename = g_strdup_printf ("GEGL-%i-%s-%i.swap",
Packit Service 2781ba
                                      getpid (),
Packit Service 2781ba
                                      babl_name ((Babl *) babl_fmt),
Packit Service 2781ba
                                      no++);
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
          filename = g_strdup_printf ("%i-%i", getpid(), no);
Packit Service 2781ba
          g_atomic_int_inc (&no);
Packit Service 2781ba
          path = g_build_filename (gegl_config()->swap, filename, NULL);
Packit Service 2781ba
          g_free (filename);
Packit Service 2781ba
Packit Service 2781ba
          backend = g_object_new (GEGL_TYPE_TILE_BACKEND_FILE,
Packit Service 2781ba
                                  "tile-width", tile_width,
Packit Service 2781ba
                                  "tile-height", tile_height,
Packit Service 2781ba
                                  "format", babl_fmt,
Packit Service 2781ba
                                  "path", path,
Packit Service 2781ba
                                  NULL);
Packit Service 2781ba
          storage = gegl_tile_storage_new (backend);
Packit Service 2781ba
          g_free (path);
Packit Service 2781ba
        }
Packit Service 2781ba
      item->storage = storage;
Packit Service 2781ba
      g_object_set_data_full (G_OBJECT (storage), "storage-cache-item", item, g_free);
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  g_static_mutex_unlock (&storage_cache_mutex);
Packit Service 2781ba
  return storage;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglBuffer *
Packit Service 2781ba
gegl_buffer_new_from_format (const void *babl_fmt,
Packit Service 2781ba
                             gint        x,
Packit Service 2781ba
                             gint        y,
Packit Service 2781ba
                             gint        width,
Packit Service 2781ba
                             gint        height,
Packit Service 2781ba
                             gint        tile_width,
Packit Service 2781ba
                             gint        tile_height,
Packit Service 2781ba
                             gboolean    use_ram)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglTileStorage *tile_storage;
Packit Service 2781ba
  GeglBuffer  *buffer;
Packit Service 2781ba
Packit Service 2781ba
  tile_storage = gegl_tile_storage_new_cached (tile_width, tile_height, babl_fmt, use_ram);
Packit Service 2781ba
Packit Service 2781ba
  buffer = g_object_new (GEGL_TYPE_BUFFER,
Packit Service 2781ba
                         "source",      tile_storage,
Packit Service 2781ba
                         "x",           x,
Packit Service 2781ba
                         "y",           y,
Packit Service 2781ba
                         "width",       width,
Packit Service 2781ba
                         "height",      height,
Packit Service 2781ba
                         "tile-width",  tile_width,
Packit Service 2781ba
                         "tile-height", tile_height,
Packit Service 2781ba
                         NULL);
Packit Service 2781ba
Packit Service 2781ba
  g_object_unref (tile_storage);
Packit Service 2781ba
Packit Service 2781ba
  return buffer;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static const void *gegl_buffer_internal_get_format (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  g_assert (buffer);
Packit Service 2781ba
  if (buffer->format != NULL)
Packit Service 2781ba
    return buffer->format;
Packit Service 2781ba
  return gegl_tile_backend_get_format (gegl_buffer_backend (buffer));
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
const Babl *
Packit Service 2781ba
gegl_buffer_get_format (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  return buffer?buffer->format:NULL;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
const Babl *
Packit Service 2781ba
gegl_buffer_set_format (GeglBuffer *buffer,
Packit Service 2781ba
                        const Babl *format)
Packit Service 2781ba
{
Packit Service 2781ba
  if (format == NULL)
Packit Service 2781ba
    {
Packit Service 2781ba
      buffer->soft_format = buffer->format;
Packit Service 2781ba
      return buffer->soft_format;
Packit Service 2781ba
    }
Packit Service 2781ba
  if (babl_format_get_bytes_per_pixel (format) ==
Packit Service 2781ba
      babl_format_get_bytes_per_pixel (buffer->format))
Packit Service 2781ba
    {
Packit Service 2781ba
      buffer->soft_format = format;
Packit Service 2781ba
      return buffer->soft_format;
Packit Service 2781ba
    }
Packit Service 2781ba
  g_warning ("tried to set format of different bpp on buffer\n");
Packit Service 2781ba
  return NULL;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gboolean gegl_buffer_is_shared (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglTileBackend *backend = gegl_buffer_backend (buffer);
Packit Service 2781ba
  return backend->priv->shared;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gboolean gegl_buffer_try_lock (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  gboolean ret;
Packit Service 2781ba
  GeglTileBackend *backend = gegl_buffer_backend (buffer);
Packit Service 2781ba
  g_mutex_lock (buffer->tile_storage->mutex);
Packit Service 2781ba
  if (buffer->lock_count>0)
Packit Service 2781ba
    {
Packit Service 2781ba
      buffer->lock_count++;
Packit Service 2781ba
      g_mutex_unlock (buffer->tile_storage->mutex);
Packit Service 2781ba
      return TRUE;
Packit Service 2781ba
    }
Packit Service 2781ba
  if (gegl_buffer_is_shared(buffer))
Packit Service 2781ba
    ret =gegl_tile_backend_file_try_lock (GEGL_TILE_BACKEND_FILE (backend));
Packit Service 2781ba
  else
Packit Service 2781ba
    ret = TRUE;
Packit Service 2781ba
  if (ret)
Packit Service 2781ba
    buffer->lock_count++;
Packit Service 2781ba
  g_mutex_unlock (buffer->tile_storage->mutex);
Packit Service 2781ba
  return TRUE;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
/* this locking is for synchronising shared buffers */
Packit Service 2781ba
gboolean gegl_buffer_lock (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  while (gegl_buffer_try_lock (buffer)==FALSE)
Packit Service 2781ba
    {
Packit Service 2781ba
      g_print ("waiting to aquire buffer..");
Packit Service 2781ba
        g_usleep (100000);
Packit Service 2781ba
    }
Packit Service 2781ba
  return TRUE;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gboolean gegl_buffer_unlock (GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  gboolean ret = TRUE;
Packit Service 2781ba
  GeglTileBackend *backend = gegl_buffer_backend (buffer);
Packit Service 2781ba
  g_mutex_lock (buffer->tile_storage->mutex);
Packit Service 2781ba
  g_assert (buffer->lock_count >=0);
Packit Service 2781ba
  buffer->lock_count--;
Packit Service 2781ba
  g_assert (buffer->lock_count >=0);
Packit Service 2781ba
  if (buffer->lock_count == 0 && gegl_buffer_is_shared (buffer))
Packit Service 2781ba
    {
Packit Service 2781ba
      ret = gegl_tile_backend_file_unlock (GEGL_TILE_BACKEND_FILE (backend));
Packit Service 2781ba
    }
Packit Service 2781ba
  g_mutex_unlock (buffer->tile_storage->mutex);
Packit Service 2781ba
  return ret;
Packit Service 2781ba
}