コード例 #1
0
ファイル: common.c プロジェクト: hendriksiedelmann/lime
Eina_Array *ea_copy(Eina_Array *a)
{
    int i;
    Eina_Array *b;
    if (ea_count(a))
        b = ea_new(ea_count(a));
    else
        b = ea_new(4);

    for(i=0; i<ea_count(a); i++)
        ea_push(b, ea_data(a, i));

    return b;
}
コード例 #2
0
ファイル: filter_gauss.c プロジェクト: hendriksiedelmann/lime
Filter *filter_gauss_blur_new(void)
{
  Filter *filter = filter_new(&filter_core_gauss);
  Meta *in, *out, *channel, *bitdepth, *color[3], *setting, *bound;
  Meta *ch_out[3];
  _Data *data = calloc(sizeof(_Data), 1);
  data->sigma = calloc(sizeof(float), 1);
  data->buf1 = malloc(BLURBUF);
  data->buf2 = malloc(BLURBUF);
  filter->fixme_outcount = 3;
  ea_push(filter->data, data);
  
  *data->sigma = 5.0;
  
  filter->mode_buffer = filter_mode_buffer_new();
  filter->mode_buffer->worker = &_worker;
  filter->mode_buffer->threadsafe = 1;
  filter->mode_buffer->area_calc = &_area_calc;
  filter->mode_buffer->data_new = &_gauss_data_new;
  
  bitdepth = meta_new_data(MT_BITDEPTH, filter, malloc(sizeof(int)));
  *(int*)(bitdepth->data) = BD_U8;
  bitdepth->replace = bitdepth;
  
  out = meta_new(MT_BUNDLE, filter);
  eina_array_push(filter->out, out);
  
  channel = meta_new_channel(filter, 1);
  color[0] = meta_new_data(MT_COLOR, filter, malloc(sizeof(int)));
  *(int*)(color[0]->data) = CS_LAB_L;
  meta_attach(channel, color[0]);
  meta_attach(channel, bitdepth);
  meta_attach(out, channel);
  ch_out[0] = channel;
  
  channel = meta_new_channel(filter, 2);
  color[1] = meta_new_data(MT_COLOR, filter, malloc(sizeof(int)));
  *(int*)(color[1]->data) = CS_LAB_A;
  meta_attach(channel, color[1]);
  meta_attach(channel, bitdepth);
  meta_attach(out, channel);
  ch_out[1] = channel;
  
  channel = meta_new_channel(filter, 3);
  color[2] = meta_new_data(MT_COLOR, filter, malloc(sizeof(int)));
  *(int*)(color[2]->data) = CS_LAB_B;
  meta_attach(channel, color[2]);
  meta_attach(channel, bitdepth);
  meta_attach(out, channel);
  ch_out[2] = channel;
  
  in = meta_new(MT_BUNDLE, filter);
  in->replace = out;
  eina_array_push(filter->in, in);
  
  channel = meta_new_channel(filter, 1);
  color[0]->replace = color[0];
  channel->replace = ch_out[0];
  meta_attach(channel, color[0]);
  meta_attach(channel, bitdepth);
  meta_attach(in, channel);
  
  channel = meta_new_channel(filter, 2);
  color[1]->replace = color[1];
  channel->replace = ch_out[1];
  meta_attach(channel, color[1]);
  meta_attach(channel, bitdepth);
  meta_attach(in, channel);
  
  channel = meta_new_channel(filter, 3);
  color[2]->replace = color[2];
  color[2]->replace = color[2];
  channel->replace = ch_out[2];
  meta_attach(channel, color[2]);
  meta_attach(channel, bitdepth);
  meta_attach(in, channel);
    
  setting = meta_new_data(MT_FLOAT, filter, data->sigma);
  meta_name_set(setting, "sigma");
  eina_array_push(filter->settings, setting);
  
  bound = meta_new_data(MT_FLOAT, filter, malloc(sizeof(int)));
  *(float*)bound->data = 0;
  meta_name_set(bound, "PARENT_SETTING_MIN");
  meta_attach(setting, bound);
  
  bound = meta_new_data(MT_FLOAT, filter, malloc(sizeof(int)));
  *(float*)bound->data = MAX_SIGMA;
  meta_name_set(bound, "PARENT_SETTING_MAX");
  meta_attach(setting, bound);
  
  return filter;
}
コード例 #3
0
void filter_fill_thread_data(Filter *f, int thread_id)
{
  if (f->mode_buffer->data_new)
    while (ea_count(f->data) <= thread_id)
      ea_push(f->data, f->mode_buffer->data_new(f, ea_data(f->data, 0)));
}
コード例 #4
0
ファイル: render.c プロジェクト: hendriksiedelmann/lime
//render area with external threading
void lime_render_area(Rect *area, Filter *f, int thread_id)
{
  int j;
  Render_Node *waiter;
  Render_Node *job;
  Dim *ch_dim;
  
  if (!f)
    return;
  
  lime_lock();
  
  lime_config_test(f);
  
  lime_filter_config_ref(f);
  
  ch_dim = meta_child_data_by_type(ea_data(f->node->con_ch_in, 0), MT_IMGSIZE);
  
  assert(area->corner.x < DIV_SHIFT_ROUND_UP(ch_dim->width, area->corner.scale));
  assert(area->corner.y < DIV_SHIFT_ROUND_UP(ch_dim->height, area->corner.scale));
  
  Render_State *state = render_state_new(area, f);
  
  while ((job = render_state_getjob(state))) {
    assert(job->need == 0);
    
    if (job->mode == MODE_CLOBBER || job->mode == MODE_INPUT) {
      assert(job->tile->refs > 0);
      filter_render_tile(job, thread_id);
    }
    //MODE_ITER
    else if (job->mode == MODE_ITER) {
      if (job->f->mode_iter->finish)
	job->f->mode_iter->finish(job->f);
    }
    else
      abort();

    if (job->tile && job->tile->want)
      while(ea_count(job->tile->want)) {
	waiter = ea_pop(job->tile->want);
        if (waiter->mode != MODE_ITER) {
          for(j=0;j<ea_count(waiter->f_source);j++)
            if (filter_hash_value_get(ea_data(waiter->f_source, j)) == job->tile->filterhash)
              //FIXME channel selection, use paired channels not blindly the same number!
              clobbertile_add(ea_data(waiter->inputs, j), ea_data(job->tile->channels, j));
        }
	waiter->need--;
	if (!waiter->need) {
	  ea_push(waiter->state->ready, waiter);
	  waiter->state->pending--;
	}
	//FIXME add proper interface!
	else if (!strcmp(waiter->f->fc->shortname, "savejpeg") || !strcmp(waiter->f->fc->shortname, "savetiff"))
          cache_stats_print();
      }
    
    if (job->tile)
      job->tile->refs--;

    render_node_del(job);
  }
  
  render_state_del(state);
  
  lime_filter_config_unref(f);
  lime_unlock();
}
コード例 #5
0
ファイル: render.c プロジェクト: hendriksiedelmann/lime
//return 0 on success
Render_Node *render_state_getjob( Render_State *state)
{
  int i;
  Rect area;
  Tilehash hash;
  Render_Node *node;
  Tile *tile;
  Render_Node *jobnode;
  int found;
  struct timespec t_start;
  struct timespec t_stop;
  
  if (ea_count(state->ready))
    return ea_pop(state->ready);
  
  if (!ea_count(state->currstate)) {
    
    if (state->pending) {
      
      if (!ea_count(state->ready)) {
        clock_gettime(CLOCK_MONOTONIC,&t_start);
        lime_unlock();
        while(state->pending && !ea_count(state->ready)) {
          usleep(1000);
          lime_lock();
          lime_unlock();
        }
        lime_lock();
        
        clock_gettime(CLOCK_MONOTONIC,&t_stop);
        printf("we were blocked!\n");
        global_stat_thread_blocked += t_stop.tv_sec - t_start.tv_sec
        +  (t_stop.tv_nsec - t_start.tv_nsec)*1.0/1000000000.0;
      }
      
      assert(ea_count(state->ready));
      
      return ea_pop(state->ready);
    }

    return NULL;
  }

  node = ea_data(state->currstate, ea_count(state->currstate)-1);
    
  while (node) {
    if (!end_of_iteration(node)) {
      area.corner.x = node->pos.x;
      area.corner.y = node->pos.y;
      area.corner.scale = node->pos.scale;
      area.width = node->tw;
      area.height = node->th;
      
      hash = tile_hash_calc(filter_get_input_filter(node->f, node->channel), &area);
         
      if ((tile = cache_tile_get(&hash))) {
	
	cache_stats_update(tile, 1, 0, 0, 0);
	  
	assert(node->mode);
	  
	//check if we're alredy waiting for this tile on another channel
	found = 0;
	if (tile->want)
	  for(i=0;i<ea_count(tile->want);i++)
	    if (node == ea_data(tile->want, i)) {
	      found = 1;
	      break;
	  }
	  
	  if (found) {
	    //do nothing, we just continue
	    
	  }
	  else if (!tile->channels) {
	    //tile is not yet rendered, push ref
	    
	    if (!tile->want)
	      tile->want = eina_array_new(4);

	    node->need++;
	    ea_push(tile->want, node);
	  }
	  else {
	    if (node->mode == MODE_CLOBBER) {
	      //TODO attention: we assume channels are always processed in the same order
	      clobbertile_add(ea_data(node->inputs, node->channel), ea_data(tile->channels, node->channel));
	      assert(ea_count(node->inputs) > node->channel);
	    }
	    else if (node->mode == MODE_ITER) {
	      node->f->mode_iter->worker(node->f, ea_data(tile->channels, node->channel), node->channel, NULL, NULL, 0);
	    }
	    else
	      abort();
	  }
	  
	incnode(node);
      }
      //this node does not need any input tiles
      else if (!ea_count(node->f_source_curr->node->con_ch_in)) {
	jobnode = render_node_new(node->f_source_curr, tile_new(&area, hash, node->f_source_curr, node->f, node->depth), state, node->depth+1);
	assert(jobnode->f->fixme_outcount);
	cache_tile_add(jobnode->tile);
	cache_stats_update(jobnode->tile, 0, 1, 0, 0);

	//don't incnode so parent node will recheck for this tile
	//the parent will propably be added to tile->need
	return jobnode;
      }
      //node needs input tiles
      else {
	tile = tile_new(&area, hash, node->f_source_curr, node->f, node->depth);
	cache_stats_update(tile, 0, 1, 0, 0);
	if (node->f->fixme_outcount);
	  cache_tile_add(tile);
        
	jobnode = render_node_new(node->f_source_curr, tile, state, node->depth+1);
        
        tile->want = eina_array_new(4);
        node->need++;
        ea_push(tile->want, node);
        //FIXME this incnode would cause problems with tiffsave!
        //incnode(node);
        
        node = jobnode;
        
	//don't incnode so parent node will recheck for this tile
	//the parent will propably be added to tile->need
	
	ea_push(state->currstate, node);
	//to lock it in the currstate array
	node->need += 1000;
      }
    }
    else {
      //all inputs have been processed
      //this doesn't mean that all inputs are available
      jobnode = node;
      
      node = ea_pop(state->currstate);
      node->need -= 1000;
      
      assert(node == jobnode);

      if (jobnode->need) {
	//what happens with jobnode?
	//why this code??
	if (ea_count(state->currstate))
	  node = ea_data(state->currstate, ea_count(state->currstate)-1);
	else
	  node = NULL;
	state->pending++;
      }
      else
	return jobnode;
    }
  }
  
  if (ea_count(state->ready))
    return ea_pop(state->ready);
    
  if (state->pending) {
    lime_unlock();
    while(state->pending && !ea_count(state->ready)) {
      usleep(1000);
      lime_lock();
      lime_unlock();
    }

    lime_lock();
    
    assert(ea_count(state->ready));

    return ea_pop(state->ready);
  } 
  
  return NULL;
}
コード例 #6
0
ファイル: render.c プロジェクト: hendriksiedelmann/lime
void filter_render_tile(Render_Node *job, int thread_id)
{
  int i;
  struct timespec t_start;
  struct timespec t_stop;
  Eina_Array *channels;
  
  assert(job->f->mode_buffer);
  assert(job->f->mode_buffer->worker != NULL);
  assert(!job->tile->channels);
  assert(job->tile->refs);
  assert(job->mode != MODE_ITER);
  
  if (job->f->fixme_outcount) {
    channels = eina_array_new(4);
  
    for(i=0;i<job->f->fixme_outcount;i++)
      ea_push(channels, tiledata_new(&job->tile->area, 1, job->tile));
  }
  else
    channels = 0;

  if (channels)
    assert(cache_tile_get(&job->tile->hash) != NULL);
  
  if (job->f->prepare && job->f->prepared_hash != job->f->hash.hash) {
    job->f->prepare(job->f);
    job->f->prepared_hash = job->f->hash.hash;
  }
  
  if (job->f->mode_buffer->threadsafe)
    lime_unlock();
  
  if (job->f->mode_buffer->threadsafe)
    filter_fill_thread_data(job->f, thread_id);
  /*else {
   *     if (!job->f->lock) {
   * job->f->lock = calloc(sizeof(pthread_mutex_t),1);
   * pthread_mutex_init(job->f->lock, NULL);
   }
   pthread_mutex_lock(job->f->lock);
   }*/
  
  clock_gettime(CLOCK_THREAD_CPUTIME_ID,&t_start);
  
  if (job->f->mode_buffer->threadsafe)
    job->f->mode_buffer->worker(job->f, job->inputs, channels, &job->tile->area, thread_id);
  else
    job->f->mode_buffer->worker(job->f, job->inputs, channels, &job->tile->area, 0);
    
  
  clock_gettime(CLOCK_THREAD_CPUTIME_ID,&t_stop);
  
  //if (!job->f->mode_buffer->threadsafe)
  //  pthread_mutex_unlock(job->f->lock);
  
  if (job->f->mode_buffer->threadsafe)
    lime_lock();
  
  job->tile->time = t_stop.tv_sec*1000000000 - t_start.tv_sec*1000000000
  +  t_stop.tv_nsec - t_start.tv_nsec;
  
  job->tile->channels = channels;
  cache_stats_update(job->tile, 0, 0, job->tile->time, 0);
  
  //printf("render add %p filter %s\n", job->tile, job->f->fc->shortname);
  //???
  //if (job->f->fixme_outcount)
  //  cache_tile_channelmem_add(job->tile);
}
コード例 #7
0
ファイル: render.c プロジェクト: hendriksiedelmann/lime
//f_source: source-filter by channel
Render_Node *render_node_new(Filter *f, Tile *tile, Render_State *state, int depth)
{
  int i;
  Rect inputs_area;
  Render_Node *node = calloc(sizeof(Render_Node), 1);
  Rect *area;
  
  if (tile)
    area = &tile->area;
  else
    area = NULL;
  
  node->state = state;
  node->depth = depth;

  if (f->node->con_ch_in && ea_count(f->node->con_ch_in))
      node->f_source = eina_array_new(4);
  
  for(i=0;i<ea_count(f->node->con_ch_in);i++)
    ea_push(node->f_source,  filter_get_input_filter(f, i));

  
  node->f = f;
  node->tile = tile;
  
  node->inputs = eina_array_new(4);
  
  if (node->f_source && f->mode_iter) {
    node->mode = MODE_ITER;
    
    node->iter = f->mode_iter->iter_new(f, area, node->f_source, &node->pos, &node->channel);
    
    node->f_source_curr = ea_data(node->f_source, node->channel);
        
    node->tw = tw_get(node->f_source_curr, node->area.corner.scale);
    node->th = th_get(node->f_source_curr, node->area.corner.scale);
  }
  else if (node->f_source && f->mode_buffer) {
    node->mode = MODE_CLOBBER;
    
    node->channel = 0;

    assert(area);
    
    filter_calc_valid_req_area(f, area, &node->area);
    
    node->f_source_curr = ea_data(node->f_source, node->channel);
        
    node->tw = tw_get(node->f_source_curr, node->area.corner.scale);
    node->th = th_get(node->f_source_curr, node->area.corner.scale);
    
    assert(f->node->con_ch_in && ea_count(f->node->con_ch_in));
  
    if (node->area.corner.x >= 0)
      node->pos.x = (node->area.corner.x/node->tw)*node->tw;
    else
      node->pos.x = ((node->area.corner.x-node->tw+1)/node->tw)*node->tw;
    if (node->area.corner.y >= 0)
      node->pos.y = (node->area.corner.y/node->th)*node->th;
    else
      node->pos.y = ((node->area.corner.y-node->th+1)/node->th)*node->th;
    node->pos.scale = node->area.corner.scale;

    //this is the input provided to filtes, so it will always be as large as actually requested by the filter
    filter_calc_req_area(f, area, &inputs_area);
    
    for(i=0;i<ea_count(f->node->con_ch_in);i++)
      ea_push(node->inputs, tiledata_new(&inputs_area, 1, NULL));
  }
  else
    node->mode = MODE_INPUT;

  
  return node;
}
コード例 #8
0
Filter *filter_down_new(void)
{
  Filter *filter = filter_new(&filter_core_down);
  Meta *in, *out, *channel, *bitdepth, *setting, *bound;
  Meta *ch_out[3];
  _Data *data = calloc(sizeof(_Data), 1);
  filter->fixme_outcount = 3;
  ea_push(filter->data, data);
  
  filter->mode_buffer = filter_mode_buffer_new();
  filter->mode_buffer->worker = &_worker_linear;
  filter->mode_buffer->area_calc = &_area_calc;
  filter->setting_changed = &_setting_changed;
  
  bitdepth = meta_new_data(MT_BITDEPTH, filter, malloc(sizeof(int)));
  *(int*)(bitdepth->data) = BD_U8;
  bitdepth->replace = bitdepth;
  
  out = meta_new(MT_BUNDLE, filter);
  eina_array_push(filter->out, out);
  
  channel = meta_new_channel(filter, 1);
  data->color[0] = meta_new_data(MT_COLOR, filter, malloc(sizeof(int)));
  *(int*)(data->color[0]->data) = CS_LAB_L;
  meta_attach(channel, data->color[0]);
  meta_attach(channel, bitdepth);
  meta_attach(out, channel);
  ch_out[0] = channel;
  
  channel = meta_new_channel(filter, 2);
  data->color[1] = meta_new_data(MT_COLOR, filter, malloc(sizeof(int)));
  *(int*)(data->color[1]->data) = CS_LAB_A;
  meta_attach(channel, data->color[1]);
  meta_attach(channel, bitdepth);
  meta_attach(out, channel);
  ch_out[1] = channel;
  
  channel = meta_new_channel(filter, 3);
  data->color[2] = meta_new_data(MT_COLOR, filter, malloc(sizeof(int)));
  *(int*)(data->color[2]->data) = CS_LAB_B;
  meta_attach(channel, data->color[2]);
  meta_attach(channel, bitdepth);
  meta_attach(out, channel);
  ch_out[2] = channel;
  
  in = meta_new(MT_BUNDLE, filter);
  in->replace = out;
  eina_array_push(filter->in, in);
  
  channel = meta_new_channel(filter, 1);
  data->color[0]->replace = data->color[0];
  channel->replace = ch_out[0];
  meta_attach(channel, data->color[0]);
  meta_attach(channel, bitdepth);
  meta_attach(in, channel);
  
  channel = meta_new_channel(filter, 2);
  data->color[1]->replace = data->color[1];
  channel->replace = ch_out[1];
  meta_attach(channel, data->color[1]);
  meta_attach(channel, bitdepth);
  meta_attach(in, channel);
  
  channel = meta_new_channel(filter, 3);
  data->color[2]->replace = data->color[2];
  channel->replace = ch_out[2];
  meta_attach(channel, data->color[2]);
  meta_attach(channel, bitdepth);
  meta_attach(in, channel);
    
  setting = meta_new_data(MT_INT, filter, &data->colorspace);
  meta_name_set(setting, "colorspace");
  eina_array_push(filter->settings, setting);
  
  bound = meta_new_data(MT_INT, filter, malloc(sizeof(int)));
  *(int*)bound->data = 0;
  meta_name_set(bound, "PARENT_SETTING_MIN");
  meta_attach(setting, bound);
  
  bound = meta_new_data(MT_INT, filter, malloc(sizeof(int)));
  *(int*)bound->data = 1;
  meta_name_set(bound, "PARENT_SETTING_MAX");
  meta_attach(setting, bound);
  
  return filter;
}