Exemplo n.º 1
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);
}
Exemplo n.º 2
0
static GeglTile *
get_tile (GeglTileSource *gegl_tile_source,
          gint            x,
          gint            y,
          gint            z)
{
  GeglTileSource       *source = ((GeglTileHandler *) gegl_tile_source)->source;
  GeglTileHandlerEmpty *empty  = (GeglTileHandlerEmpty *) gegl_tile_source;
  GeglTile             *tile   = NULL;

  if (source)
    tile = gegl_tile_source_get_tile (source, x, y, z);
  if (tile)
    return tile;

  if (G_UNLIKELY(!empty->tile))
    {
      gint tile_size = gegl_tile_backend_get_tile_size (empty->backend);
      empty->tile    = gegl_tile_new (tile_size);
      memset (gegl_tile_get_data (empty->tile), 0x00, tile_size);
      empty->tile->is_zero_tile = 1;
    }

  return gegl_tile_handler_dup_tile (GEGL_TILE_HANDLER (empty),
                                     empty->tile, x, y, z);
}
Exemplo n.º 3
0
GeglTileHandler *
gimp_tile_handler_projection_new (GeglNode *graph)
{
  GimpTileHandlerProjection *projection;

  g_return_val_if_fail (GEGL_IS_NODE (graph), NULL);

  projection = g_object_new (GIMP_TYPE_TILE_HANDLER_PROJECTION, NULL);

  projection->graph = g_object_ref (graph);

  return GEGL_TILE_HANDLER (projection);
}
Exemplo n.º 4
0
static gpointer
gegl_buffer_command (GeglTileSource *source,
                     GeglTileCommand command,
                     gint            x,
                     gint            y,
                     gint            z,
                     gpointer        data)
{
  GeglTileHandler *handler = GEGL_TILE_HANDLER (source);
  switch (command)
    {
      case GEGL_TILE_GET:
        return gegl_buffer_get_tile (source, x, y, z);
      default:
        return gegl_tile_handler_source_command (handler, command, x, y, z, data);
    }
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
static GeglTile *
get_tile (GeglTileSource *gegl_tile_source,
          gint            x,
          gint            y,
          gint            z)
{
  GeglTileSource      *source = ((GeglTileHandler *) gegl_tile_source)->source;
  GeglTileHandlerZoom *zoom   = (GeglTileHandlerZoom *) gegl_tile_source;
  GeglTile            *tile   = NULL;
  const Babl          *format = gegl_tile_backend_get_format (zoom->backend);
  GeglTileStorage     *tile_storage;
  gint                 tile_width;
  gint                 tile_height;
  gint                 tile_size;

  if (source)
    tile = gegl_tile_source_get_tile (source, x, y, z);

  if (tile)
    return tile;

  if (z == 0)/* at base level with no tile found->send null, and shared empty
               tile will be used instead */
    {
      return NULL;
    }

  tile_storage = _gegl_tile_handler_get_tile_storage ((GeglTileHandler *) zoom);

  if (z > tile_storage->seen_zoom)
    tile_storage->seen_zoom = z;

  g_object_get (zoom->backend,
                "tile-width", &tile_width,
                "tile-height", &tile_height,
                "tile-size", &tile_size,
                NULL);

  {
    gint      i, j;
    GeglTile *source_tile[2][2] = { { NULL, NULL }, { NULL, NULL } };

    for (i = 0; i < 2; i++)
      for (j = 0; j < 2; j++)
        {
          /* we get the tile from ourselves, to make successive rescales work
           * correctly */
            source_tile[i][j] = gegl_tile_source_get_tile (gegl_tile_source,
                                                          x * 2 + i, y * 2 + j, z - 1);
        }

    if (source_tile[0][0] == NULL &&
        source_tile[0][1] == NULL &&
        source_tile[1][0] == NULL &&
        source_tile[1][1] == NULL)
      {
        return NULL;   /* no data from level below, return NULL and let GeglTileHandlerEmpty
                          fill in the shared empty tile */
      }

    g_assert (tile == NULL);

    tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (zoom), x, y, z);

    gegl_tile_lock (tile);

    for (i = 0; i < 2; i++)
      for (j = 0; j < 2; j++)
        {
          if (source_tile[i][j])
            {
              set_half (tile, source_tile[i][j], tile_width, tile_height, format, i, j);
              gegl_tile_unref (source_tile[i][j]);
            }
          else
            {
              set_blank (tile, tile_width, tile_height, format, i, j);
            }
        }
    gegl_tile_unlock (tile);
  }

  return tile;
}
Exemplo n.º 7
0
static GeglTile *
gimp_tile_handler_projection_validate (GeglTileSource *source,
                                       GeglTile       *tile,
                                       gint            x,
                                       gint            y)
{
  GimpTileHandlerProjection *projection;
  cairo_region_t            *tile_region;
  cairo_rectangle_int_t      tile_rect;

  projection = GIMP_TILE_HANDLER_PROJECTION (source);

  if (cairo_region_is_empty (projection->dirty_region))
    return tile;

  tile_region = cairo_region_copy (projection->dirty_region);

  tile_rect.x      = x * projection->tile_width;
  tile_rect.y      = y * projection->tile_height;
  tile_rect.width  = projection->tile_width;
  tile_rect.height = projection->tile_height;

  cairo_region_intersect_rectangle (tile_region, &tile_rect);

  if (! cairo_region_is_empty (tile_region))
    {
      gint tile_bpp;
      gint tile_stride;
      gint n_rects;
      gint i;

      if (! tile)
        tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (source),
                                              x, y, 0);

      cairo_region_subtract_rectangle (projection->dirty_region, &tile_rect);

      tile_bpp    = babl_format_get_bytes_per_pixel (projection->format);
      tile_stride = tile_bpp * projection->tile_width;

      gegl_tile_lock (tile);

      n_rects = cairo_region_num_rectangles (tile_region);

#if 0
      g_printerr ("%d ", n_rects);
#endif

      for (i = 0; i < n_rects; i++)
        {
          cairo_rectangle_int_t blit_rect;

          cairo_region_get_rectangle (tile_region, i, &blit_rect);

#if 0
          g_printerr ("constructing projection at %d %d %d %d\n",
                      blit_rect.x,
                      blit_rect.y,
                      blit_rect.width,
                      blit_rect.height);
#endif

          gegl_node_blit (projection->graph, 1.0,
                          GEGL_RECTANGLE (blit_rect.x,
                                          blit_rect.y,
                                          blit_rect.width,
                                          blit_rect.height),
                          projection->format,
                          gegl_tile_get_data (tile) +
                          (blit_rect.y % projection->tile_height) * tile_stride +
                          (blit_rect.x % projection->tile_width)  * tile_bpp,
                          tile_stride,
                          GEGL_ABYSS_NONE);
        }

      gegl_tile_unlock (tile);
    }

  cairo_region_destroy (tile_region);

  return tile;
}
Exemplo n.º 8
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;
}