void
gimp_tile_handler_projection_invalidate (GimpTileHandlerProjection *projection,
                                         gint                       x,
                                         gint                       y,
                                         gint                       width,
                                         gint                       height)
{
  cairo_rectangle_int_t rect = { x, y, width, height };
  gint                  tile_x1;
  gint                  tile_y1;
  gint                  tile_x2;
  gint                  tile_y2;
  gint                  tile_x;
  gint                  tile_y;

  g_return_if_fail (GIMP_IS_TILE_HANDLER_PROJECTION (projection));

  cairo_region_union_rectangle (projection->dirty_region, &rect);

  tile_x1 = x / projection->tile_width;
  tile_y1 = y / projection->tile_height;
  tile_x2 = (x + width  - 1) / projection->tile_width;
  tile_y2 = (y + height - 1) / projection->tile_height;

  for (tile_y = tile_y1; tile_y <= tile_y2; tile_y++)
    {
      for (tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
        {
          gimp_tile_handler_projection_void_pyramid (GEGL_TILE_SOURCE (projection),
                                                     tile_x / 2,  tile_y / 2, 1);
        }
    }
}
Esempio n. 2
0
static void
gegl_buffer_dispose (GObject *object)
{
  GeglBuffer  *buffer  = GEGL_BUFFER (object);
  GeglTileHandler *handler = GEGL_TILE_HANDLER (object);

  gegl_buffer_sample_cleanup (buffer);

  if (gegl_cl_is_accelerated ())
    gegl_buffer_cl_cache_invalidate (GEGL_BUFFER (object), NULL);

  if (handler->source &&
      GEGL_IS_TILE_STORAGE (handler->source))
    {
      GeglTileBackend *backend = gegl_buffer_backend (buffer);

      /* only flush non-internal backends,. */
      if (!(GEGL_IS_TILE_BACKEND_FILE (backend) ||
            GEGL_IS_TILE_BACKEND_RAM (backend) ||
            GEGL_IS_TILE_BACKEND_TILE_DIR (backend)))
        gegl_buffer_flush (buffer);

      gegl_tile_source_reinit (GEGL_TILE_SOURCE (handler->source));

#if 0
      g_object_unref (handler->source);
      handler->source = NULL; /* this might be a dangerous way of marking that we have already voided */
#endif
    }

  _gegl_buffer_drop_hot_tile (buffer);

  G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gimp_tile_handler_projection_init (GimpTileHandlerProjection *projection)
{
  GeglTileSource *source = GEGL_TILE_SOURCE (projection);

  source->command = gimp_tile_handler_projection_command;

  projection->dirty_region = cairo_region_create ();
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
gboolean gegl_tile_store (GeglTile *tile)
{
  if (gegl_tile_is_stored (tile))
    return TRUE;
  if (tile->tile_storage == NULL)
    return FALSE;
  return gegl_tile_source_set_tile (GEGL_TILE_SOURCE (tile->tile_storage),
                                    tile->x,
                                    tile->y,
                                    tile->z,
                                    tile);
}
Esempio n. 6
0
static void
gegl_tile_void_pyramid (GeglTile *tile)
{
  if (tile->tile_storage &&
      tile->tile_storage->seen_zoom &&
      tile->z == 0) /* we only accepting voiding the base level */
    {
      _gegl_tile_void_pyramid (GEGL_TILE_SOURCE (tile->tile_storage),
                               tile->x/2,
                               tile->y/2,
                               tile->z+1);
      return;
    }
}
Esempio n. 7
0
GeglTileBackend *
gegl_buffer_backend2 (GeglBuffer *buffer)
{
  GeglTileSource *tmp = GEGL_TILE_SOURCE (buffer);

  if (!tmp)
    return NULL;

  do
    {
      tmp = GEGL_TILE_HANDLER (tmp)->source;
    } while (tmp &&
             !GEGL_IS_TILE_BACKEND (tmp));
  if (!tmp &&
      !GEGL_IS_TILE_BACKEND (tmp))
    return NULL;

  return (GeglTileBackend *) tmp;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
static void
gegl_tile_backend_file_load_index (GeglTileBackendFile *self,
                                   gboolean             block)
{
  GeglBufferHeader new_header;
  GList           *iter;
  GeglTileBackend *backend;
  goffset offset = 0;
  goffset max=0;
  gint tile_size;

  /* compute total from and next pre alloc by monitoring tiles as they
   * are added here
   */
  /* reload header */
  new_header = gegl_buffer_read_header (self->i, &offset)->header;
  self->foffset = 256;

  while (new_header.flags & GEGL_FLAG_LOCKED)
    {
      g_usleep (50000);
      new_header = gegl_buffer_read_header (self->i, &offset)->header;
      self->foffset = 256;
    }

  if (new_header.rev == self->header.rev)
    {
      GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "header not changed: %s", self->path);
      return;
    }
  else
    {
      self->header=new_header;
      GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "loading index: %s", self->path);
    }

  tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  offset      = self->header.next;
  self->tiles = gegl_buffer_read_index (self->i, &offset);
  self->foffset = -1;
  backend     = GEGL_TILE_BACKEND (self);

  for (iter = self->tiles; iter; iter=iter->next)
    {
      GeglBufferItem *item = iter->data;

      GeglBufferItem *existing = g_hash_table_lookup (self->index, item);

      if (item->tile.offset > max)
        max = item->tile.offset + tile_size;

      if (existing)
        {
          if (existing->tile.rev == item->tile.rev)
            {
              g_assert (existing->tile.offset == item->tile.offset);
              existing->tile = item->tile;
              g_free (item);
              continue;
            }
          else
            {
              GeglTileStorage *storage =
                (void*)gegl_tile_backend_peek_storage (backend);
              GeglRectangle rect;
              g_hash_table_remove (self->index, existing);

              gegl_tile_source_refetch (GEGL_TILE_SOURCE (storage),
                                        existing->tile.x,
                                        existing->tile.y,
                                        existing->tile.z);

              if (existing->tile.z == 0)
                {
                  rect.width = self->header.tile_width;
                  rect.height = self->header.tile_height;
                  rect.x = existing->tile.x * self->header.tile_width;
                  rect.y = existing->tile.y * self->header.tile_height;
                }
              g_free (existing);

              g_signal_emit_by_name (storage, "changed", &rect, NULL);
            }
        }
      g_hash_table_insert (self->index, iter->data, iter->data);
    }
  g_list_free (self->tiles);
  g_slist_free (self->free_list);
  self->free_list      = NULL;
  self->next_pre_alloc = max; /* if bigger than own? */
  self->total          = max;
  self->tiles          = NULL;
}
Esempio n. 11
0
static GObject *
gegl_buffer_constructor (GType                  type,
                         guint                  n_params,
                         GObjectConstructParam *params)
{
  GObject         *object;
  GeglBuffer      *buffer;
  GeglTileBackend *backend;
  GeglTileHandler *handler;
  GeglTileSource  *source;

  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);

  buffer  = GEGL_BUFFER (object);
  handler = GEGL_TILE_HANDLER (object);
  source  = handler->source;
  backend = gegl_buffer_backend (buffer);

  if (source)
    {
      if (GEGL_IS_TILE_STORAGE (source))
        buffer->format = GEGL_TILE_STORAGE (source)->format;
      else if (GEGL_IS_BUFFER (source))
        buffer->format = GEGL_BUFFER (source)->format;
    }
  else
    {
      if (buffer->backend)
        {
          backend = buffer->backend;
          buffer->format = gegl_tile_backend_get_format (backend);
        }
      else
        {
          gboolean use_ram = FALSE;
          const char *maybe_path = NULL;

          if (!buffer->format)
            {
              g_warning ("Buffer constructed without format, assuming RGBA float");
              buffer->format = babl_format("RGBA float");
            }

          /* make a new backend & storage */

          if (buffer->path)
            maybe_path = buffer->path;
          else
            maybe_path = gegl_config ()->swap;

          if (maybe_path)
            use_ram = g_ascii_strcasecmp (maybe_path, "ram") == 0;
          else
            use_ram = TRUE;

          if (use_ram == TRUE)
            {
              backend = g_object_new (GEGL_TYPE_TILE_BACKEND_RAM,
                                      "tile-width", buffer->tile_width,
                                      "tile-height", buffer->tile_height,
                                      "format", buffer->format,
                                      NULL);
            }
          else
            {
              if (buffer->path)
                {
                  backend = g_object_new (GEGL_TYPE_TILE_BACKEND_FILE,
                                          "tile-width", buffer->tile_width,
                                          "tile-height", buffer->tile_height,
                                          "format", buffer->format,
                                          "path", buffer->path,
                                          NULL);
                }
              else
                {
                  gchar *path = get_next_swap_path();

                  backend = g_object_new (GEGL_TYPE_TILE_BACKEND_FILE,
                                          "tile-width", buffer->tile_width,
                                          "tile-height", buffer->tile_height,
                                          "format", buffer->format,
                                          "path", path,
                                          NULL);
                  g_free (path);
                }
            }

          buffer->backend = backend;
        }

      source = GEGL_TILE_SOURCE (gegl_tile_storage_new (backend));
      gegl_tile_handler_set_source ((GeglTileHandler*)(buffer), source);
      g_object_unref (source);
      g_object_unref (backend);
    }

   /* Connect to the changed signal of source, this is used by some backends
    * (e.g. File) to notify of outside changes to the buffer.
    */
  if (GEGL_IS_TILE_STORAGE (source))
    {
      g_signal_connect (source, "changed",
                        G_CALLBACK (gegl_buffer_storage_changed),
                        buffer);
    }

  g_assert (backend);

  if (buffer->extent.width == -1 ||
      buffer->extent.height == -1) /* no specified extents,
                                      inheriting from source */
    {
      if (GEGL_IS_BUFFER (source))
        {
          buffer->extent.x = GEGL_BUFFER (source)->extent.x;
          buffer->extent.y = GEGL_BUFFER (source)->extent.y;
          buffer->extent.width  = GEGL_BUFFER (source)->extent.width;
          buffer->extent.height = GEGL_BUFFER (source)->extent.height;
        }
      else if (GEGL_IS_TILE_STORAGE (source))
        {
          buffer->extent.x = 0;
          buffer->extent.y = 0;
          buffer->extent.width  = GEGL_TILE_STORAGE (source)->width;
          buffer->extent.height = GEGL_TILE_STORAGE (source)->height;
        }
      else
        {
          buffer->extent.x = 0;
          buffer->extent.y = 0;
          buffer->extent.width  = 0;
          buffer->extent.height = 0;
        }
    }

  buffer->abyss_tracks_extent = FALSE;

  if (buffer->abyss.width == 0 &&
      buffer->abyss.height == 0 &&
      buffer->abyss.x == 0 &&
      buffer->abyss.y == 0)      /* 0 sized extent == inherit buffer extent
                                  */
    {
      buffer->abyss.x             = buffer->extent.x;
      buffer->abyss.y             = buffer->extent.y;
      buffer->abyss.width         = buffer->extent.width;
      buffer->abyss.height        = buffer->extent.height;
      buffer->abyss_tracks_extent = TRUE;
    }
  else if (buffer->abyss.width == 0 &&
           buffer->abyss.height == 0)
    {
      g_warning ("peculiar abyss dimensions: %i,%i %ix%i",
                 buffer->abyss.x,
                 buffer->abyss.y,
                 buffer->abyss.width,
                 buffer->abyss.height);
    }
  else if (buffer->abyss.width == -1 ||
           buffer->abyss.height == -1)
    {
      buffer->abyss.x      = GEGL_BUFFER (source)->abyss.x - buffer->shift_x;
      buffer->abyss.y      = GEGL_BUFFER (source)->abyss.y - buffer->shift_y;
      buffer->abyss.width  = GEGL_BUFFER (source)->abyss.width;
      buffer->abyss.height = GEGL_BUFFER (source)->abyss.height;
    }

  /* intersect our own abyss with parent's abyss if it exists
   */
  if (GEGL_IS_BUFFER (source))
    {
      GeglRectangle parent;
      GeglRectangle request;
      GeglRectangle self;

      parent.x = GEGL_BUFFER (source)->abyss.x - buffer->shift_x;
      parent.y = GEGL_BUFFER (source)->abyss.y - buffer->shift_y;
      parent.width = GEGL_BUFFER (source)->abyss.width;
      parent.height = GEGL_BUFFER (source)->abyss.height;

      request.x = buffer->abyss.x;
      request.y = buffer->abyss.y;
      request.width = buffer->abyss.width;
      request.height = buffer->abyss.height;

      gegl_rectangle_intersect (&self, &parent, &request);

      /* Don't have the abyss track the extent if the intersection is
       * not the entire extent. Otherwise, setting the extent identical
       * to itself could suddenly make the abyss bigger. */
      if (buffer->abyss_tracks_extent &&
          (buffer->extent.x      != self.x ||
           buffer->extent.y      != self.y ||
           buffer->extent.width  != self.width ||
           buffer->extent.height != self.height) )
        {
          buffer->abyss_tracks_extent = FALSE;
        }

      buffer->abyss.x      = self.x;
      buffer->abyss.y      = self.y;
      buffer->abyss.width  = self.width;
      buffer->abyss.height = self.height;
    }

  /* compute our own total shift <- this should probably happen
   * approximatly first */
  if (GEGL_IS_BUFFER (source))
    {
      GeglBuffer *source_buf;

      source_buf = GEGL_BUFFER (source);

      buffer->shift_x += source_buf->shift_x;
      buffer->shift_y += source_buf->shift_y;
    }
  else
    {
    }

  buffer->tile_storage = gegl_buffer_tile_storage (buffer);

  /* intialize the soft format to be equivalent to the actual
   * format
   */
  buffer->soft_format = buffer->format;

  return object;
}