Пример #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);
}
Пример #2
0
static void
gegl_buffer_finalize (GObject *object)
{
#ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS
  g_free (GEGL_BUFFER (object)->alloc_stack_trace);
  allocated_buffers_list = g_list_remove (allocated_buffers_list, object);
#endif

  g_free (GEGL_BUFFER (object)->path);
  de_allocated_buffers++;
  G_OBJECT_CLASS (parent_class)->finalize (object);
}
Пример #3
0
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
  GeglProperties   *o = GEGL_PROPERTIES (operation);
  GeglRectangle result = {0,0,0,0};

  load_buffer (o);

  result.width  = gegl_buffer_get_width (GEGL_BUFFER (o->user_data));
  result.height = gegl_buffer_get_height (GEGL_BUFFER (o->user_data));
  return result;
}
Пример #4
0
static gboolean
gimp_operation_normal_parent_process (GeglOperation        *operation,
                                      GeglOperationContext *context,
                                      const gchar          *output_prop,
                                      const GeglRectangle  *result,
                                      gint                  level)
{
#if 0
  /*  this code tries to be smart but is in fact just a too stupid
   *  copy from gegl's normal mode. to fix it, it needs to take
   *  mask and opacity into account
   */
  const GeglRectangle *in_extent  = NULL;
  const GeglRectangle *aux_extent = NULL;
  GObject             *input;
  GObject             *aux;

  /* get the raw values this does not increase the reference count */
  input = gegl_operation_context_get_object (context, "input");
  aux   = gegl_operation_context_get_object (context, "aux");

  /* pass the input/aux buffers directly through if they are not
   * overlapping
   */
  if (input)
    in_extent = gegl_buffer_get_abyss (GEGL_BUFFER (input));

  if (! input ||
      (aux && ! gegl_rectangle_intersect (NULL, in_extent, result)))
    {
      gegl_operation_context_set_object (context, "output", aux);
      return TRUE;
    }

  if (aux)
    aux_extent = gegl_buffer_get_abyss (GEGL_BUFFER (aux));

  if (! aux ||
      (input && ! gegl_rectangle_intersect (NULL, aux_extent, result)))
    {
      gegl_operation_context_set_object (context, "output", input);
      return TRUE;
    }
#endif

  /* chain up, which will create the needed buffers for our actual
   * process function
   */
  return GEGL_OPERATION_CLASS (parent_class)->process (operation, context,
                                                       output_prop, result,
                                                       level);
}
Пример #5
0
static gboolean
gegl_operation_filter_process (GeglOperation        *operation,
                               GeglOperationContext *context,
                               const gchar          *output_prop,
                               const GeglRectangle  *result,
                               gint                  level)
{
  GeglOperationFilterClass *klass;
  GeglBuffer               *input;
  GeglBuffer               *output;
  gboolean                  success = FALSE;

  klass = GEGL_OPERATION_FILTER_GET_CLASS (operation);

  g_assert (klass->process);

  if (strcmp (output_prop, "output"))
    {
      g_warning ("requested processing of %s pad on a filter", output_prop);
      return FALSE;
    }

  input  = gegl_operation_context_get_source (context, "input");
  output = gegl_operation_context_get_target (context, "output");

  success = klass->process (operation, input, output, result, level);

  if (output == GEGL_BUFFER (operation->node->cache))
    gegl_cache_computed (operation->node->cache, result);

  if (input != NULL)
    g_object_unref (input);
  return success;
}
Пример #6
0
static gboolean
gegl_nop_process (GeglOperation        *operation,
                  GeglOperationContext *context,
                  const gchar          *output_prop,
                  const GeglRectangle  *result,
                  gint                  level)
{
  GeglBuffer *input;

  if (strcmp (output_prop, "output"))
    {
      g_warning ("requested processing of %s pad on a nop", output_prop);
      return FALSE;
    }

  input = GEGL_BUFFER (gegl_operation_context_get_object (context, "input"));
  if (!input)
    {
      g_warning ("nop received NULL input");
      return FALSE;
    }

  gegl_operation_context_take_object (context, "output", g_object_ref (G_OBJECT (input)));
  return TRUE;
}
Пример #7
0
/**
 * gegl_graph_prepare:
 * @path: The traversal path
 * 
 * Prepare all nodes, initializing their output formats and have rects.
 */
void
gegl_graph_prepare (GeglGraphTraversal *path)
{
  GList *list_iter = NULL;
  
  for (list_iter = path->dfs_path; list_iter; list_iter = list_iter->next)
  {
    GeglNode *node = GEGL_NODE (list_iter->data);
    GeglOperation *operation = node->operation;
    
    g_mutex_lock (&node->mutex);

    gegl_operation_prepare (operation);
    node->have_rect = gegl_operation_get_bounding_box (operation);
    node->valid_have_rect = TRUE;

    if (node->cache)
      {
        gegl_buffer_set_extent (GEGL_BUFFER (node->cache),
                                &node->have_rect);
      }

    g_mutex_unlock (&node->mutex);
    
    if (!g_hash_table_contains (path->contexts, node))
      {
        GeglOperationContext *context = gegl_operation_context_new (node->operation);
        
        g_hash_table_insert (path->contexts,
                             node,
                             context);
      }
  }
}
Пример #8
0
/**
 * mypaint_gegl_tiled_surface_set_buffer:
 * @buffer: (transfer full): The buffer which shall back this surface.
 *
 */
void
mypaint_gegl_tiled_surface_set_buffer(MyPaintGeglTiledSurface *self, GeglBuffer *buffer)
{
    if (buffer && self->buffer == buffer) {
        return;
    }

    if (self->buffer) {
        g_object_unref(self->buffer);
    }

    if (buffer) {
        g_return_if_fail(GEGL_IS_BUFFER(buffer));
        g_object_ref(buffer);
        self->buffer = buffer;
    } else {
        // Using GeglBuffer with aligned tiles for zero-copy access
        self->buffer = GEGL_BUFFER(g_object_new(GEGL_TYPE_BUFFER,
                          "x", self->extent_rect.x, "y", self->extent_rect.y,
                          "width", self->extent_rect.width, "height", self->extent_rect.height,
                          "format", self->format,
                          "tile-width", self->parent.tile_size, "tile-height", self->parent.tile_size,
                          NULL));
    }
    g_assert(GEGL_IS_BUFFER(self->buffer));


    self->parent.threadsafe_tile_requests = buffer_is_native(self);
}
Пример #9
0
static gboolean
gegl_operation_source_process (GeglOperation        *operation,
                               GeglOperationContext *context,
                               const gchar          *output_prop,
                               const GeglRectangle  *result,
                               gint                  level)
{
  GeglOperationSourceClass *klass = GEGL_OPERATION_SOURCE_GET_CLASS (operation);
  GeglBuffer               *output;
  gboolean                  success;

  if (strcmp (output_prop, "output"))
    {
      g_warning ("requested processing of %s pad on a source operation", output_prop);
      return FALSE;
    }

  g_assert (klass->process);
  output = gegl_operation_context_get_target (context, "output");
  success = klass->process (operation, output, result, level);

  if (output == GEGL_BUFFER (operation->node->cache))
    gegl_cache_computed (operation->node->cache, result);

  return success;
}
Пример #10
0
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
  GeglRectangle result = {0,0,0,0};
  GeglChantO   *o = GEGL_CHANT_PROPERTIES (operation);

  load_buffer (o);

  if (o->chant_data)
    {
      result.width  = gegl_buffer_get_width  (GEGL_BUFFER (o->chant_data));
      result.height = gegl_buffer_get_height (GEGL_BUFFER (o->chant_data));
    }

  return result;
}
static gboolean gegl_operation_point_filter_op_process
                              (GeglOperation       *operation,
                               GeglOperationContext *context,
                               const gchar          *output_pad,
                               const GeglRectangle  *roi)
{
  GeglBuffer               *input;
  GeglBuffer               *output;
  gboolean                  success = FALSE;

  input = gegl_operation_context_get_source (context, "input");

  if (gegl_can_do_inplace_processing (operation, input, roi))
    {
      output = g_object_ref (input);
      gegl_operation_context_take_object (context, "output", G_OBJECT (output));
    }
  else
    {
      output = gegl_operation_context_get_target (context, "output");
    }

  success = gegl_operation_point_filter_process (operation, input, output, roi);
  if (output == GEGL_BUFFER (operation->node->cache))
    gegl_cache_computed (operation->node->cache, roi);

  if (input != NULL)
    g_object_unref (input);
  return success;
}
Пример #12
0
static void
my_set_property (GObject  *gobject,
                 guint         property_id,
                 const GValue *value,
                 GParamSpec   *pspec)
{
    GeglOperation *operation = GEGL_OPERATION (gobject);
    GeglProperties *o = GEGL_PROPERTIES (operation);
    Priv *p = get_priv(o);
    GObject *buffer = NULL;

    switch (property_id)
    {
    case PROP_buffer:
        if (o->buffer) {
            // Invariant: valid buffer should always have valid signal handler
            g_assert(p->buffer_changed_handler > 0);
            g_signal_handler_disconnect (o->buffer, p->buffer_changed_handler);
            /* XXX: should decrement signal connected count */
        }
        buffer = G_OBJECT (g_value_get_object (value));
        if (buffer) {
            p->buffer_changed_handler = gegl_buffer_signal_connect (GEGL_BUFFER(buffer), "changed", G_CALLBACK(buffer_changed), operation);
        }
        break;
    default:
        break;
    }

    /* The set_property provided by the chant system does the
     * storing and reffing/unreffing of the input properties */
    set_property(gobject, property_id, value, pspec);
}
Пример #13
0
static void
set_property (GObject      *object,
              guint         property_id,
              const GValue *value,
              GParamSpec   *pspec)
{
  GeglSampler *self = GEGL_SAMPLER (object);

  switch (property_id)
    {
      case PROP_BUFFER:
        gegl_sampler_set_buffer (self, GEGL_BUFFER (g_value_get_object (value)));
        break;

      case PROP_FORMAT:
        self->format = g_value_get_pointer (value);
        break;

      case PROP_LEVEL:
        self->lvel = g_value_get_int  (value);
        break;

      default:
        break;
    }
}
Пример #14
0
GeglBuffer *
gegl_operation_context_get_source (GeglOperationContext *context,
                                   const gchar          *padname)
{
  GeglBuffer *input;

  input = GEGL_BUFFER (gegl_operation_context_dup_object (context, padname));
  return input;
}
Пример #15
0
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
  GeglRectangle result = {0,0,0,0};
  GeglBuffer   *buffer = ensure_buffer (operation);

  result = *gegl_buffer_get_extent (GEGL_BUFFER (buffer));
  return result;
}
Пример #16
0
static void
load_buffer (GeglProperties *op_raw_load)
{
  if (!op_raw_load->user_data)
    {
      FILE  *pfp;
      gchar *command;
      gint   width, height, val_max;
      gchar  newline;

      command = g_strdup_printf ("dcraw -4 -c '%s'\n", op_raw_load->path);
      pfp = popen (command, PIPE_MODE);
      g_free (command);

      if (fscanf (pfp, "P6 %d %d %d %c",
         &width, &height, &val_max, &newline) != 4)
        {
          pclose (pfp);
          g_warning ("not able to aquire raw data");
          return;
        }

        {
          GeglRectangle extent = { 0, 0, 0, 0 };
          extent.width = width;
          extent.height = height;
          op_raw_load->user_data = (gpointer) gegl_buffer_new (&extent,
                                                   babl_format_new (
                                                     babl_model ("RGB"),
                                                     babl_type ("u16"),
                                                     babl_component ("G"),
                                                     babl_component ("B"),
                                                     babl_component ("R"),
                                                     NULL));
        }
         {

           guint16 *buf = g_new (guint16, width * height * 3);
           fread (buf, 1, width * height * 3 * 2, pfp);
           gegl_buffer_set (GEGL_BUFFER (op_raw_load->user_data),
                            NULL,
                            0,
                            babl_format_new (
                                        babl_model ("RGB"),
                                        babl_type ("u16"),
                                        babl_component ("G"),
                                        babl_component ("B"),
                                        babl_component ("R"),
                                        NULL),
                            buf,
                            GEGL_AUTO_ROWSTRIDE
                           );
           g_free (buf);
         }
       fclose (pfp);
    }
}
Пример #17
0
static void
load_buffer (GeglProperties *op_raw_load)
{
  if (!op_raw_load->user_data)
    {
      FILE  *pfp;
      gchar *command;

      gint width, height, val_max;
      char newline;

      command = g_strdup_printf ("dcraw -j -d -4 -c '%s'\n", op_raw_load->path);
      pfp = popen (command, PIPE_MODE);
      g_free (command);

      if (fscanf (pfp, "P6 %d %d %d %c",
                  &width, &height, &val_max, &newline) != 4)
        {
          pclose (pfp);
          g_warning ("not able to aquire raw data");
          return;
        }

      {
        GeglRectangle extent = { 0, 0, width, height };
        op_raw_load->user_data = (void*)gegl_buffer_new (&extent, babl_format ("Y u16"));
      }
         {
           guchar *buf = g_new (guchar, width * height * 3 * 2);
           fread (buf, 1, width * height * 3 * 2, pfp);
           if(strstr (op_raw_load->path, "rawbayerS")){
             gint i;
             for (i=0;i<width*height*3;i++)
               {
                guchar tmp = buf[i*2];
                buf[i*2] = buf[i*2+1];
                buf[i*2+1] = tmp;
               }
           }
           gegl_buffer_set (GEGL_BUFFER (op_raw_load->user_data),
                            NULL,
                            0,
                            babl_format_new (
                                 babl_model ("RGB"),
                                 babl_type ("u16"),
                                 babl_component ("R"),
                                 babl_component ("G"),
                                 babl_component ("B"),
                                 NULL),
                            buf,
                            GEGL_AUTO_ROWSTRIDE);
           g_free (buf);
         }
       fclose (pfp);
    }
}
Пример #18
0
static void
gegl_cache_init (GeglCache *self)
{
    self->node = NULL;
    self->mutex = g_mutex_new ();

    /* thus providing a default value for GeglCache, that overrides the NULL
     * from GeglBuffer */
    GEGL_BUFFER (self)->format = (gpointer) babl_format ("R'G'B'A u8");
}
static gboolean
photos_operation_svg_multiply_operation_process (GeglOperation *operation,
                                                 GeglOperationContext *context,
                                                 const gchar *output_pad,
                                                 const GeglRectangle *roi,
                                                 gint level)
{
  GObject *aux;
  GObject *input;
  const GeglRectangle *aux_bbox = NULL;
  const GeglRectangle *in_bbox = NULL;
  gboolean ret_val = TRUE;

  aux = gegl_operation_context_get_object (context, "aux");
  if (aux != NULL)
    aux_bbox = gegl_buffer_get_abyss (GEGL_BUFFER (aux));

  input = gegl_operation_context_get_object (context, "input");
  if (input != NULL)
    in_bbox = gegl_buffer_get_abyss (GEGL_BUFFER (input));

  if (aux == NULL || (input != NULL && !gegl_rectangle_intersect (NULL, aux_bbox, roi)))
    {
      gegl_operation_context_set_object (context, "output", input);
      goto out;
    }

  if (input == NULL || (aux != NULL && !gegl_rectangle_intersect (NULL, in_bbox, roi)))
    {
      gegl_operation_context_set_object (context, "output", aux);
      goto out;
    }

  ret_val = GEGL_OPERATION_CLASS (photos_operation_svg_multiply_parent_class)->process (operation,
                                                                                        context,
                                                                                        output_pad,
                                                                                        roi,
                                                                                        level);

 out:
  return ret_val;
}
Пример #20
0
static void
gegl_buffer_source_prepare (GeglOperation *operation)
{
    const Babl *format = NULL;
    GeglProperties *o = GEGL_PROPERTIES (operation);

    if (o->buffer)
        format = gegl_buffer_get_format (GEGL_BUFFER (o->buffer));

    gegl_operation_set_format (operation, "output", format);
}
/* we replicate the process function from GeglOperationComposer to be
 * able to bail out earlier for some common processing time pitfalls
 */
static gboolean
gegl_operation_composer_process2 (GeglOperation        *operation,
                                  GeglOperationContext *context,
                                  const gchar          *output_prop,
                                  const GeglRectangle  *result)
{
  GeglOperationComposerClass *klass   = GEGL_OPERATION_COMPOSER_GET_CLASS (operation);
  GeglBuffer                 *input;
  GeglBuffer                 *aux;
  GeglBuffer                 *output;
  gboolean                    success = FALSE;

  if (strcmp (output_prop, "output"))
    {
      g_warning ("requested processing of %s pad on a composer", output_prop);
      return FALSE;
    }

  input = gegl_operation_context_get_source (context, "input");
  aux   = gegl_operation_context_get_source (context, "aux");

  if (gegl_can_do_inplace_processing (operation, input, result))
    {
      output = g_object_ref (input);
      gegl_operation_context_take_object (context, "output", G_OBJECT (output));
    }
  else
    output = gegl_operation_context_get_target (context, "output");
    
    {
      gboolean done = FALSE;

      if (result->width == 0 ||
          result->height == 0)
        done = TRUE;

      success = done;
      if (!done)
        {
          success = klass->process (operation, input, aux, output, result);

          if (output == GEGL_BUFFER (operation->node->cache))
            gegl_cache_computed (operation->node->cache, result);
        }
      if (input)
         g_object_unref (input);
      if (aux)
         g_object_unref (aux);
    }

  return success;
}
GeglBuffer *
gegl_operation_context_get_source (GeglOperationContext *context,
                                   const gchar          *padname)
{
  GeglBuffer     *real_input;
  GeglBuffer     *input;

  real_input = GEGL_BUFFER (gegl_operation_context_get_object (context, padname));
  if (!real_input)
    return NULL;
  input = g_object_ref (real_input);
  return input;
}
Пример #23
0
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
    GeglRectangle result = {0,0,0,0};
    GeglProperties   *o = GEGL_PROPERTIES (operation);

    if (!o->buffer)
    {
        return result;
    }
    result = *gegl_buffer_get_extent (GEGL_BUFFER (o->buffer));
    return result;
}
Пример #24
0
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         const GeglRectangle *result)
{
    GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);

    if (o->buffer)
    {
        GeglBuffer *output = GEGL_BUFFER (o->buffer);

        gegl_buffer_copy (input, result, output, result);
    }

    return TRUE;
}
Пример #25
0
static gboolean
gegl_operation_composer_process (GeglOperation        *operation,
                                 GeglOperationContext *context,
                                 const gchar          *output_prop,
                                 const GeglRectangle  *result,
                                 gint                  level)
{
  GeglOperationComposerClass *klass   = GEGL_OPERATION_COMPOSER_GET_CLASS (operation);
  GeglBuffer                 *input;
  GeglBuffer                 *aux;
  GeglBuffer                 *output;
  gboolean                    success = FALSE;

  if (strcmp (output_prop, "output"))
    {
      g_warning ("requested processing of %s pad on a composer", output_prop);
      return FALSE;
    }

  input = gegl_operation_context_get_source (context, "input");
  aux   = gegl_operation_context_get_source (context, "aux");
  output = gegl_operation_context_get_target (context, "output");

  /* A composer with a NULL aux, can still be valid, the
   * subclass has to handle it.
   */
  if (input != NULL ||
      aux != NULL)
    {
      success = klass->process (operation, input, aux, output, result, level);

      if (output == GEGL_BUFFER (operation->node->cache))
        gegl_cache_computed (operation->node->cache, result);

      if (input)
        g_object_unref (input);
      if (aux)
        g_object_unref (aux);
    }
  else
    {
      g_warning ("%s received NULL input and aux",
                 gegl_node_get_debug_name (operation->node));
    }

  return success;
}
Пример #26
0
static GObject *
gegl_cache_constructor (GType                  type,
                        guint                  n_params,
                        GObjectConstructParam *params)
{
    GObject   *object;
    GeglCache *self;

    object = G_OBJECT_CLASS (gegl_cache_parent_class)->constructor (type,
             n_params,
             params);
    self = GEGL_CACHE (object);

    self->valid_region = gegl_region_new ();
    self->format       = GEGL_BUFFER (self)->format;

    return object;
}
Пример #27
0
static gboolean
process (GeglOperation         *operation,
         GeglOperationContext  *context,
         const gchar           *output_pad,
         const GeglRectangle   *result,
         gint                   level)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  GeglBuffer     *output;

  load_buffer (o);
  g_assert (o->user_data);
  g_assert (g_str_equal (output_pad, "output"));

  output = GEGL_BUFFER (o->user_data);
  g_object_ref (output);
  gegl_operation_context_take_object (context, "output", G_OBJECT (output));
  return TRUE;
}
Пример #28
0
void
gegl_cache_invalidate (GeglCache           *self,
                       const GeglRectangle *roi)
{
#if 0
    if (roi)
    {
        gegl_buffer_clear (GEGL_BUFFER (self), roi);
    }
    else
    {
        g_warning ("XXX: full invalidation of GeglCache NYI\n");
    }
#endif

    g_mutex_lock (self->mutex);

    if (roi)
    {
        GeglRectangle expanded = gegl_rectangle_expand (roi);

        GeglRegion *temp_region;
        temp_region = gegl_region_rectangle (&expanded);
        gegl_region_subtract (self->valid_region, temp_region);
        gegl_region_destroy (temp_region);
        g_signal_emit (self, gegl_cache_signals[INVALIDATED], 0,
                       roi, NULL);
    }
    else
    {
        GeglRectangle rect = { 0, 0, 0, 0 }; /* should probably be the extent of the cache */
        if (self->valid_region)
            gegl_region_destroy (self->valid_region);
        self->valid_region = gegl_region_new ();
        g_signal_emit (self, gegl_cache_signals[INVALIDATED], 0,
                       &rect, NULL);
    }
    g_mutex_unlock (self->mutex);
}
Пример #29
0
gint gegl_buffer_leaks (void)
{
#ifdef GEGL_BUFFER_DEBUG_ALLOCATIONS
  {
    GList *leaked_buffer = NULL;

    for (leaked_buffer = allocated_buffers_list;
         leaked_buffer != NULL;
         leaked_buffer = leaked_buffer->next)
      {
        GeglBuffer *buffer = GEGL_BUFFER (leaked_buffer->data);

        g_printerr ("\n"
                   "Leaked buffer allocation stack trace:\n");
        g_printerr ("%s\n", buffer->alloc_stack_trace);
      }
  }
  g_list_free (allocated_buffers_list);
  allocated_buffers_list = NULL;
#endif

  return allocated_buffers - de_allocated_buffers;
}
GeglBuffer *
gegl_operation_context_get_target (GeglOperationContext *context,
                                   const gchar          *padname)
{
  GeglBuffer          *output;
  const GeglRectangle *result;
  const Babl          *format;
  GeglNode            *node;
  GeglOperation       *operation;

#if 0
  g_return_val_if_fail (GEGL_IS_OPERATION_CONTEXT (context), NULL);
#endif

  operation = context->operation;
  node = operation->node; /* <ick */
  format = gegl_operation_get_format (operation, padname);

  if (format == NULL)
    {
      g_warning ("no format for %s presuming RGBA float\n",
                 gegl_node_get_debug_name (node));
      format = babl_format ("RGBA float");
    }
  g_assert (format != NULL);
  g_assert (!strcmp (padname, "output"));

  result = &context->result_rect;

  if (result->width == 0 ||
      result->height == 0)
    {
      output = g_object_ref (emptybuf());
    }
  else if (node->dont_cache == FALSE &&
      ! GEGL_OPERATION_CLASS (G_OBJECT_GET_CLASS (operation))->no_cache)
    {
      GeglBuffer    *cache;
      cache = GEGL_BUFFER (gegl_node_get_cache (node));

      /* Only use the cache if the result is within the cache
       * extent. This is certainly not optimal. My gut feeling is that
       * the current caching mechanism needs to be redesigned
       */
      if (gegl_rectangle_contains (gegl_buffer_get_extent (cache), result))
        {
          output = g_object_ref (cache);
        }
      else
        {
          output = gegl_buffer_new_ram (result, format);
        }
    }
  else
    {
      output = gegl_buffer_new_ram (result, format);
    }

  gegl_operation_context_take_object (context, padname, G_OBJECT (output));
  return output;
}