Example #1
0
//FIXME on sinks should replace old connection!
Con *filter_connect_real(Filter *source, int out, Filter *sink, int in)
{
  Con *con = malloc(sizeof(Con));
  
  con->source = eina_array_data_get(source->out, out);
  con->sink = eina_array_data_get(sink->in, in);
  
  if (!source->node->con_trees_out)
    source->node->con_trees_out = eina_array_new(1);
  
  if (!sink->node->con_trees_in)
    sink->node->con_trees_in = eina_array_new(1);
  
  if (ea_count(source->node->con_trees_out)) {
    printf("WARNING: have con_trees_out\n");
    while (ea_count(source->node->con_trees_out))
      ea_pop(source->node->con_trees_out);
  }
  if (ea_count(sink->node->con_trees_in)) {
    printf("WARNING: have con_trees_in\n");
    while (ea_count(sink->node->con_trees_in))
      ea_pop(sink->node->con_trees_in);
  }
  
  eina_array_push(source->node->con_trees_out, con);
  eina_array_push(sink->node->con_trees_in, con);
  
  filter_hash_invalidate(source);
  
  return con;
}
Example #2
0
void con_del_real(Con *con)
{
  if (con->source->filter->node->con_trees_out 
	  && ea_count(con->source->filter->node->con_trees_out))
    ea_pop(con->source->filter->node->con_trees_out);
  if (con->sink->filter->node->con_trees_in 
	  && ea_count(con->sink->filter->node->con_trees_in))
    ea_pop(con->sink->filter->node->con_trees_in);
  
  assert(!ea_count(con->source->filter->node->con_trees_out));
  assert(!ea_count(con->sink->filter->node->con_trees_in));
  
  free(con);
}
Example #3
0
void con_del(Con *con)
{
  //FIXME als del real?
    if (con->source->filter->node_orig->con_trees_out 
	  && ea_count(con->source->filter->node_orig->con_trees_out))
    ea_pop(con->source->filter->node_orig->con_trees_out);
  if (con->sink->filter->node_orig->con_trees_in 
	  && ea_count(con->sink->filter->node_orig->con_trees_in))
    ea_pop(con->sink->filter->node_orig->con_trees_in);
  
  assert(!ea_count(con->source->filter->node_orig->con_trees_out));
  assert(!ea_count(con->sink->filter->node_orig->con_trees_in));
  
  free(con);
}
Example #4
0
//FIXME on sinks should replace old connection!
Con *filter_connect(Filter *source, int out, Filter *sink, int in)
{
  Con *con = malloc(sizeof(Con));
  
  //no composition yet
  assert(in == 0);
  assert(out == 0);
  
  assert(source->in);
  assert(sink->out);
  
  lime_config_reset(sink);
  lime_config_reset(source);
  
  con->source = eina_array_data_get(source->out, out);
  con->sink = eina_array_data_get(sink->in, in);
  
  if (!source->node_orig->con_trees_out)
    source->node_orig->con_trees_out = eina_array_new(1);
  
  if (!sink->node_orig->con_trees_in)
    sink->node_orig->con_trees_in = eina_array_new(1);
  
  if (!ea_count(source->node_orig->con_trees_out))
    eina_array_push(source->node_orig->con_trees_out, con);
  else {
    while (ea_count(source->node_orig->con_trees_out))
      con_del(ea_pop(source->node_orig->con_trees_out));
    eina_array_push(source->node_orig->con_trees_out, con);
  }
  
  if (!ea_count(sink->node_orig->con_trees_in))
    eina_array_push(sink->node_orig->con_trees_in, con);
  else {
    while (ea_count(sink->node_orig->con_trees_in))
      con_del(ea_pop(sink->node_orig->con_trees_in));
    eina_array_push(sink->node_orig->con_trees_in, con);
  }
  
  filter_hash_invalidate(source);
  
  return con;
}
Example #5
0
void filter_del(Filter *f)
{
  Eina_Hash *metas;
  
  lime_config_reset(f);
  
  pthread_mutex_destroy(&f->lock);
  
  /*if (f->node->con_trees_in && ea_count(f->node->con_trees_in))
    filter_deconfigure(((Con*)ea_data(f->node->con_trees_in, 0))->source->filter);*/
  
  if (f->node->con_trees_in) {
    if (ea_count(f->node->con_trees_in))
      con_del_real(ea_pop(f->node->con_trees_in));
    eina_array_free(f->node->con_trees_in);
    f->node->con_trees_in = NULL;
  }
  
  if (f->node->con_trees_out) {
    if (ea_count(f->node->con_trees_out))
      con_del_real(ea_pop(f->node->con_trees_out));
    eina_array_free(f->node->con_trees_out);
    f->node->con_trees_out = NULL;
  }
  
  if (f->node_orig->con_trees_in) {
    if (ea_count(f->node_orig->con_trees_in))
      con_del(ea_pop(f->node_orig->con_trees_in));
    eina_array_free(f->node_orig->con_trees_in);
    f->node_orig->con_trees_in = NULL;
  }
  
  if (f->node_orig->con_trees_out) {
    if (ea_count(f->node_orig->con_trees_out))
      con_del(ea_pop(f->node_orig->con_trees_out));
    eina_array_free(f->node_orig->con_trees_out);
    f->node_orig->con_trees_out = NULL;
  }
  
  if (f->node->con_ch_in)
    eina_array_free(f->node->con_ch_in);
  
  if (f->del)
    f->del(f);
  else
    printf("FIXME! del filter %s!\n", f->fc->shortname);
  
  while(ea_count(f->metas))
    meta_del(ea_pop(f->metas));
  
  eina_array_free(f->metas);
  eina_array_free(f->in);
  eina_array_free(f->out);
  eina_array_free(f->tune);
  eina_array_free(f->settings);
  eina_array_free(f->core);
  fg_node_del(f->node);
  fg_node_del(f->node_orig); 
  
  eina_array_free(f->data);
  
  if (f->mode_buffer)
    filter_mode_buffer_del(f->mode_buffer);
  if (f->mode_iter)
    filter_mode_iter_del(f->mode_iter);
  
  if (f->tw_s)
    free(f->tw_s);
  if (f->th_s)
    free(f->th_s);
    
  free(f);
}
Example #6
0
//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();
}
Example #7
0
//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;
}