static GThreadPool *thread_pool (void)
{
  static GThreadPool *pool = NULL;
  if (!pool)
  {
    pool =  g_thread_pool_new (thread_process, NULL, gegl_config_threads (),
        FALSE, NULL);
  }
  return pool;
}
GeglBufferIterator *
gegl_buffer_iterator_empty_new (void)
{
  GeglBufferIterator *iter = g_slice_new (GeglBufferIterator);
  iter->priv               = g_slice_new (GeglBufferIteratorPriv);

  iter->priv->num_buffers = 0;
  iter->priv->state       = GeglIteratorState_Start;

  threaded = gegl_config_threads () > 1;

  return iter;
}
Exemple #3
0
void
gegl_buffer_sample_cleanup (GeglBuffer *buffer)
{
  gboolean threaded;

  g_return_if_fail (GEGL_IS_BUFFER (buffer));

  if (! buffer->sampler)
    return;

  threaded = gegl_config_threads ()>1;

  if (threaded)
    g_mutex_lock (&gegl_buffer_sampler_mutex);

  if (buffer->sampler)
    {
      g_object_unref (buffer->sampler);
      buffer->sampler = NULL;
    }

  if (threaded)
    g_mutex_unlock (&gegl_buffer_sampler_mutex);
}
Exemple #4
0
void
gegl_buffer_sample_at_level (GeglBuffer       *buffer,
                             gdouble           x,
                             gdouble           y,
                             GeglMatrix2      *scale,
                             gpointer          dest,
                             const Babl       *format,
                             gint              level,
                             GeglSamplerType   sampler_type,
                             GeglAbyssPolicy   repeat_mode)
{
  /*
  if (sampler_type == GEGL_SAMPLER_NEAREST && format == buffer->soft_format)
  {
    GeglRectangle rect = {floorf (x), floorf(y), 1, 1};
    gegl_buffer_get (buffer, &rect, 1, NULL, dest, GEGL_AUTO_ROWSTRIDE, repeat_mode);
    return;
  }*/

  if (!format)
    format = buffer->soft_format;

  if (gegl_cl_is_accelerated ())
  {
    GeglRectangle rect = {floorf (x), floorf(y), 1, 1};
    gegl_buffer_cl_cache_flush (buffer, &rect);
  }

  /* unset the cached sampler if it dosn't match the needs */
  if (buffer->sampler == NULL ||
      (buffer->sampler != NULL &&
          (buffer->sampler_type != sampler_type || buffer->sampler_format != format)))
    {
      gboolean  threaded = gegl_config_threads () > 1;
      GType desired_type = gegl_sampler_gtype_from_enum (sampler_type);

      if (threaded)
        g_mutex_lock (&gegl_buffer_sampler_mutex);

      if (buffer->sampler)
      {
        g_object_unref (buffer->sampler);
        buffer->sampler = NULL;
        buffer->sampler_type = 0;
      }

      buffer->sampler_type = sampler_type;
      buffer->sampler = g_object_new (desired_type,
                                      "buffer", buffer,
                                      "format", format,
                                      "level", level,
                                      NULL);
      buffer->sampler_format = format;
      gegl_sampler_prepare (buffer->sampler);

      if (threaded)
        g_mutex_unlock (&gegl_buffer_sampler_mutex);
    }

  buffer->sampler->get(buffer->sampler, x, y, scale, dest, repeat_mode);
}
  static gboolean
gegl_operation_composer3_process (GeglOperation        *operation,
    GeglOperationContext *context,
    const gchar          *output_prop,
    const GeglRectangle  *result,
    gint                  level)
{
  GeglOperationComposer3Class *klass   = GEGL_OPERATION_COMPOSER3_GET_CLASS (operation);
  GeglBuffer                  *input;
  GeglBuffer                  *aux;
  GeglBuffer                  *aux2;
  GeglBuffer                  *output;
  gboolean                     success = FALSE;

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

  if (result->width == 0 || result->height == 0)
  {
    output = gegl_operation_context_get_target (context, "output");
    return TRUE;
  }

  input = gegl_operation_context_get_source (context, "input");
  output = gegl_operation_context_get_output_maybe_in_place (operation,
                                                             context,
                                                             input,
                                                             result);

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

  /* A composer with a NULL aux, can still be valid, the
   * subclass has to handle it.
   */
  if (input != NULL ||
      aux != NULL ||
      aux2 != NULL)
    {
      if (gegl_operation_use_threading (operation, result))
      {
        gint threads = gegl_config_threads ();
        GThreadPool *pool = thread_pool ();
        ThreadData thread_data[GEGL_MAX_THREADS];
        gint pending = threads;

        if (result->width > result->height)
        {
          gint bit = result->width / threads;
          for (gint j = 0; j < threads; j++)
          {
            thread_data[j].roi.y = result->y;
            thread_data[j].roi.height = result->height;
            thread_data[j].roi.x = result->x + bit * j;
            thread_data[j].roi.width = bit;
          }
          thread_data[threads-1].roi.width = result->width - (bit * (threads-1));
        }
        else
        {
          gint bit = result->height / threads;
          for (gint j = 0; j < threads; j++)
          {
            thread_data[j].roi.x = result->x;
            thread_data[j].roi.width = result->width;
            thread_data[j].roi.y = result->y + bit * j;
            thread_data[j].roi.height = bit;
          }
          thread_data[threads-1].roi.height = result->height - (bit * (threads-1));
        }
        for (gint i = 0; i < threads; i++)
        {
          thread_data[i].klass = klass;
          thread_data[i].operation = operation;
          thread_data[i].input = input;
          thread_data[i].aux = aux;
          thread_data[i].aux2 = aux2;
          thread_data[i].output = output;
          thread_data[i].pending = &pending;
          thread_data[i].level = level;
          thread_data[i].success = TRUE;
        }

        for (gint i = 1; i < threads; i++)
          g_thread_pool_push (pool, &thread_data[i], NULL);
        thread_process (&thread_data[0], NULL);

        while (g_atomic_int_get (&pending)) {};
        
        success = thread_data[0].success;
      }
      else
      {
        success = klass->process (operation, input, aux, aux2, output, result, level);
      }

      g_clear_object (&input);
      g_clear_object (&aux);
      g_clear_object (&aux2);
    }
  else
    {
      g_warning ("%s received NULL input, aux, and aux2",
                 gegl_node_get_operation (operation->node));
    }

  return success;
}
Exemple #6
0
static void inline
gegl_sampler_get_pixel (GeglSampler    *sampler,
                        gint            x,
                        gint            y,
                        gpointer        data,
                        GeglAbyssPolicy repeat_mode)
{
  GeglSamplerNearest *nearest_sampler = (GeglSamplerNearest*)(sampler);
  GeglBuffer *buffer = sampler->buffer;
  const GeglRectangle *abyss = &buffer->abyss;
  guchar              *buf   = data;

  if (y <  abyss->y ||
      x <  abyss->x ||
      y >= abyss->y + abyss->height ||
      x >= abyss->x + abyss->width)
    {
      switch (repeat_mode)
      {
        case GEGL_ABYSS_CLAMP:
          x = CLAMP (x, abyss->x, abyss->x+abyss->width-1);
          y = CLAMP (y, abyss->y, abyss->y+abyss->height-1);
          break;

        case GEGL_ABYSS_LOOP:
          x = abyss->x + GEGL_REMAINDER (x - abyss->x, abyss->width);
          y = abyss->y + GEGL_REMAINDER (y - abyss->y, abyss->height);
          break;

        case GEGL_ABYSS_BLACK:
          {
            gfloat color[4] = {0.0, 0.0, 0.0, 1.0};
            babl_process (babl_fish (gegl_babl_rgba_linear_float (), sampler->format),
                          color,
                          buf,
                          1);
            return;
          }

        case GEGL_ABYSS_WHITE:
          {
            gfloat color[4] = {1.0, 1.0, 1.0, 1.0};
            babl_process (babl_fish (gegl_babl_rgba_linear_float (),
                                     sampler->format),
                          color,
                          buf,
                          1);
            return;
          }

        default:
        case GEGL_ABYSS_NONE:
          memset (buf, 0x00, babl_format_get_bytes_per_pixel (sampler->format));
          return;
      }
    }

  gegl_buffer_lock (sampler->buffer);

  {
    gint tile_width  = buffer->tile_width;
    gint tile_height = buffer->tile_height;
    gint tiledy      = y + buffer->shift_y;
    gint tiledx      = x + buffer->shift_x;
    gint indice_x    = gegl_tile_indice (tiledx, tile_width);
    gint indice_y    = gegl_tile_indice (tiledy, tile_height);

    GeglTile *tile = nearest_sampler->hot_tile;

    if (!(tile &&
          tile->x == indice_x &&
          tile->y == indice_y))
      {
        if (gegl_config_threads()>1)
          g_rec_mutex_lock (&buffer->tile_storage->mutex);

        if (tile)
          gegl_tile_unref (tile);

        tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
                                          indice_x, indice_y,
                                          0);
        nearest_sampler->hot_tile = tile;

        if (gegl_config_threads()>1)
          g_rec_mutex_unlock (&buffer->tile_storage->mutex);
      }

    if (tile)
      {
        gint tile_origin_x = indice_x * tile_width;
        gint tile_origin_y = indice_y * tile_height;
        gint       offsetx = tiledx - tile_origin_x;
        gint       offsety = tiledy - tile_origin_y;

        guchar *tp = gegl_tile_get_data (tile) + (offsety * tile_width + offsetx) * nearest_sampler->buffer_bpp;

        babl_process (sampler->fish, tp, buf, 1);
      }
  }

  gegl_buffer_unlock (sampler->buffer);
}
Exemple #7
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  = (GeglBuffer*)gegl_operation_context_dup_object (context, "input");
  output = gegl_operation_context_get_output_maybe_in_place (operation,
                                                             context,
                                                             input,
                                                             result);

  if (gegl_operation_use_threading (operation, result))
  {
    gint threads = gegl_config_threads ();
    GeglSplitStrategy split_strategy = GEGL_SPLIT_STRATEGY_AUTO;
    GThreadPool *pool = thread_pool ();
    ThreadData thread_data[GEGL_MAX_THREADS];
    gint pending = threads;

    if (klass->get_split_strategy)
    {
      split_strategy = klass->get_split_strategy (operation, context,
                                                  output_prop, result, level);
    }

    if (split_strategy == GEGL_SPLIT_STRATEGY_AUTO)
    {
      if (result->width > result->height)
        split_strategy = GEGL_SPLIT_STRATEGY_VERTICAL;
      else
        split_strategy = GEGL_SPLIT_STRATEGY_HORIZONTAL;
    }

    if (split_strategy == GEGL_SPLIT_STRATEGY_VERTICAL)
    {
      gint bit = result->width / threads;
      for (gint j = 0; j < threads; j++)
      {
        thread_data[j].roi.y = result->y;
        thread_data[j].roi.height = result->height;
        thread_data[j].roi.x = result->x + bit * j;
        thread_data[j].roi.width = bit;
      }
      thread_data[threads-1].roi.width = result->width - (bit * (threads-1));
    }
    else if (split_strategy == GEGL_SPLIT_STRATEGY_HORIZONTAL)
    {
      gint bit = result->height / threads;
      for (gint j = 0; j < threads; j++)
      {
        thread_data[j].roi.x = result->x;
        thread_data[j].roi.width = result->width;
        thread_data[j].roi.y = result->y + bit * j;
        thread_data[j].roi.height = bit;
      }
      thread_data[threads-1].roi.height = result->height - (bit * (threads-1));
    }
    else
    {
      g_return_val_if_reached (FALSE);
    }
    for (gint i = 0; i < threads; i++)
    {
      thread_data[i].klass = klass;
      thread_data[i].operation = operation;
      thread_data[i].context = context;
      thread_data[i].output = output;
      thread_data[i].pending = &pending;
      thread_data[i].level = level;
      thread_data[i].success = TRUE;
    }

    for (gint i = 1; i < threads; i++)
      g_thread_pool_push (pool, &thread_data[i], NULL);
    thread_process (&thread_data[0], g_object_ref (input));

    while (g_atomic_int_get (&pending)) {};

    success = thread_data[0].success;
  }
  else
  {
    success = klass->process (operation, input, output, result, level);
  }

  g_clear_object (&input);
  return success;
}