Пример #1
0
void *filter_core_by_name(Filter *f, const char *name)
{
  int i;
  for(i=0;i<ea_count(f->core);i++)
    if (!strcmp(name, ((Meta*)ea_data(f->core, i))->name))
      return ((Meta*)ea_data(f->core, i))->data;
    
  return NULL;
}
Пример #2
0
void *filter_core_by_type(Filter *f, int type)
{
  int i;
  for(i=0;i<ea_count(f->core);i++)
    if (type == ((Meta*)ea_data(f->core, i))->type)
      return ((Meta*)ea_data(f->core, i))->data;
    
  return NULL;
}
Пример #3
0
void *filter_core_by_subtype(Filter *f, int type, char *subtype)
{
  int i;
  for(i=0;i<ea_count(f->core);i++)
    if (type == ((Meta*)ea_data(f->core, i))->type
        && ((Meta*)ea_data(f->core, i))->type_str
        && !strcmp(((Meta*)ea_data(f->core, i))->type_str, subtype))
      return ((Meta*)ea_data(f->core, i))->data;
    
  return NULL;
}
Пример #4
0
//FIXME leaves out the last filter (which should be the sink!), add check if it really is the sink?
char *lime_filter_chain_serialize(Filter *f)
{
  int i;
  //FIXME handle large settings
  char *buf = malloc(4096);
  char *str = buf;
  Meta *m;
  
  buf[0] = '\0';
  
  while (f && f->node_orig->con_trees_out &&  ea_count(f->node_orig->con_trees_out)) {
    str += sprintf(str, "%s", f->fc->shortname);
    for(i=0;i<ea_count(f->settings);i++) {
      m = ea_data(f->settings, i);
      if (m->data)
        switch (m->type) {
          case MT_INT :
            str += sprintf(str, ":%s=%d", m->name, *(int*)m->data);
            break;
          case MT_FLOAT : 
            str += sprintf(str, ":%s=%f", m->name, *(float*)m->data);
            break;
          case MT_STRING : 
            assert(!strchr((char*)m->data, ':'));
            str += sprintf(str, ":%s=%s", m->name, string_escape_colon((char*)m->data));
            break;
      }
    else
      printf("no data for %s\n", m->name);
    }
    
    if (f->node_orig->con_trees_out &&  ea_count(f->node_orig->con_trees_out))
      f = ((Con*)ea_data(f->node_orig->con_trees_out, 0))->sink->filter;
    else
      f = NULL;

    /* FIXME
    if (f->out && ea_count(f->out))
      f = eina_array_data_get(f->out, 0);
    else
      f = NULL;*/
    
    if (f && f->node_orig->con_trees_out &&  ea_count(f->node_orig->con_trees_out))
      str += sprintf(str, ",");
  }
  
  if (buf[0] == '\0') {
    free(buf);
    buf = NULL;
  }
  
  return buf;
}
Пример #5
0
static int _setting_changed(Filter *f)
{
  _Data *data = ea_data(f->data, 0);
  
  switch (data->colorspace) {
    case 0 : 
      *(int*)(data->color[0]->data) = CS_RGB_R;
      *(int*)(data->color[1]->data) = CS_RGB_G;
      *(int*)(data->color[2]->data) = CS_RGB_B;
      f->mode_buffer->worker = &_worker_gamma;
      break;
    case 1 : 
      *(int*)(data->color[0]->data) = CS_LAB_L;
      *(int*)(data->color[1]->data) = CS_LAB_A;
      *(int*)(data->color[2]->data) = CS_LAB_B;
      f->mode_buffer->worker = &_worker_linear;
      break;
    case 2 : 
      *(int*)(data->color[0]->data) = CS_YUV_Y;
      *(int*)(data->color[1]->data) = CS_YUV_U;
      *(int*)(data->color[2]->data) = CS_YUV_V;
      f->mode_buffer->worker = &_worker_linear;
      break;
    default :
      abort();    
  }
  
  return 0;
}
Пример #6
0
int lime_setting_string_set(Filter *f, const char *setting, const char *value)
{
  int i;
  Meta *m;
  const char *str;
  
  if (!ea_count(f->settings))
    return -1;
  
  str = eina_stringshare_add(value);
  
  for(i=0;i<ea_count(f->settings);i++) {
    m = ea_data(f->settings, i);
    if (!strcmp(setting, m->name)) {
      m->data = str;
      
      filter_hash_invalidate(f);
      
      if (f->setting_changed)
	f->setting_changed(f);
      
      lime_config_reset(f);
      return 0;
    }
  }
  
  eina_stringshare_del(str);
  return -1;
}
Пример #7
0
Filter *filter_chain_first_filter(Filter *f)
{
  while (f->node_orig->con_trees_in && ea_count(f->node_orig->con_trees_in))
    f = ((Con*)ea_data(f->node_orig->con_trees_in, 0))->source->filter;
  
  return f;
}
Пример #8
0
Filter *filter_chain_last_filter(Filter *f)
{
  while (f->node_orig->con_trees_out && ea_count(f->node_orig->con_trees_out))
    f = ((Con*)ea_data(f->node_orig->con_trees_out, 0))->sink->filter;
  
  return f;
}
Пример #9
0
void filter_calc_valid_req_area(Filter *f, Rect *area, Rect *req_area)
{
  Dim *ch_dim;
  int x, y, w, h;
  int div;
  
  //calc area
  filter_calc_req_area(f, area, req_area);
  
  //restrict to prev filters output 
  assert(f->node->con_ch_in && ea_count(f->node->con_ch_in));
  ch_dim = meta_child_data_by_type(ea_data(f->node->con_ch_in, 0), MT_IMGSIZE);
  
  div = 1u<<req_area->corner.scale;

  x = ch_dim->x/div;
  y = ch_dim->y/div;
  w = ch_dim->width/div;
  h = ch_dim->height/div;
  
  if (x > req_area->corner.x) {
    req_area->width = req_area->width - x + req_area->corner.x;
    req_area->corner.x = x;
  }
  if (y > req_area->corner.y) {
    req_area->height = req_area->height - y + req_area->corner.y;
    req_area->corner.y = y;
  }
  if (x + w < req_area->corner.x + req_area->width)
    req_area->width = x + w - req_area->corner.x;
  if (y + h < req_area->corner.y + req_area->height)
    req_area->height = y + h - req_area->corner.y;
}
Пример #10
0
int lime_setting_int_set(Filter *f, const char *setting, int value)
{
  int i;
  Meta *m;
  
  if (!ea_count(f->settings))
    return -1;
  
  for(i=0;i<ea_count(f->settings);i++) {
    m = ea_data(f->settings, i);
    if (!strcmp(setting, m->name)) {
      assert(m->data);
      *(int*)m->data = value;
      
      filter_hash_invalidate(f);
      
      if (f->setting_changed)
        f->setting_changed(f);
      
      lime_config_reset(f);
      return 0;
    }
  }
  
  return -1;
}
Пример #11
0
static void _meta_array2hash(Eina_Hash *hash, Eina_Array *trees)
{
  int i;

  for(i=0;i<ea_count(trees);i++)
    _meta2hash(hash, ea_data(trees, i));
}
Пример #12
0
Filter *filter_chain_next_filter(Filter *f)
{
  if (f->node_orig->con_trees_out && ea_count(f->node_orig->con_trees_out)) {
    return ((Con*)ea_data(f->node_orig->con_trees_out, 0))->sink->filter;
  }
  
  return NULL;
}
Пример #13
0
void render_state_print(Render_State *state, int t_id) 
{
  int i;
  
  printf("%4d ", t_id);
  
  for(i=0;i<ea_count(state->currstate);i++) {
    printf("%4dx%4d ", ((Render_Node*)ea_data(state->currstate, i))->pos.x, ((Render_Node*)ea_data(state->currstate, i))->pos.y);
  }
  
  printf("\n");
}
Пример #14
0
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;
}
Пример #15
0
static void _worker_linear(Filter *f, Eina_Array *in, Eina_Array *out, Rect *area, int thread_id)
{
  int ch;
  int i, j;
  Tiledata *in_td, *out_td;
  Rect *in_area;
  
  assert(in && ea_count(in) == 3);
  assert(out && ea_count(out) == 3);
  
  in_area = &((Tiledata*)ea_data(in, 0))->area;
  
  if (area->corner.scale)
    for(ch=0;ch<3;ch++) {
      in_td = (Tiledata*)ea_data(in, ch);
      out_td = (Tiledata*)ea_data(out, ch);
      
      for(j=0;j<DEFAULT_TILE_SIZE*2;j+=2)
	for(i=0;i<DEFAULT_TILE_SIZE*2;i+=2)
	  tileptr8(out_td, i/2+area->corner.x, j/2+area->corner.y)[0] = 
	  (tileptr8(in_td, i+in_area->corner.x, j+in_area->corner.y)[0]
	  +tileptr8(in_td, i+1+in_area->corner.x, j+in_area->corner.y)[0]
	  +tileptr8(in_td, i+in_area->corner.x, j+1+in_area->corner.y)[0]
	  +tileptr8(in_td, i+1+in_area->corner.x, j+1+in_area->corner.y)[0]
	  +2
	  ) / 4;
    }
    else
      for(ch=0;ch<3;ch++) {
	in_td = (Tiledata*)ea_data(in, ch);
	out_td = (Tiledata*)ea_data(out, ch);
	assert(in_td->area.width == out_td->area.width);
	assert(in_td->area.height == out_td->area.height);
	memcpy(out_td->data, in_td->data, out_td->area.width*out_td->area.height);
      }
      
}
Пример #16
0
static void _area_calc(Filter *f, Rect *in, Rect *out)
{
  _Data *data = ea_data(f->data, 0);
  uint32_t render_r, actual_r;
  
  actual_r = r_calc(*data->sigma, in->corner.scale)/16;
  
  render_r = actual_r+1;
  
  out->corner.scale = in->corner.scale;
  out->corner.x = in->corner.x - render_r*3;
  out->corner.y = in->corner.y - render_r*3;
  out->width = in->width + 2*render_r*3;
  out->height = in->height + 2*render_r*3;
}
Пример #17
0
int lime_setting_type_get(Filter *f, const char *setting)
{  
  int i;
  Meta *m;
  
  if (!ea_count(f->settings))
    return -1;
  
  for(i=0;i<ea_count(f->settings);i++) {
    m = ea_data(f->settings, i);
    if (!strcmp(setting, m->name))
      return m->type;
  }
  
  return -1;
}
Пример #18
0
void incnode(Render_Node *node)
{
  if (node->mode == MODE_CLOBBER) {
    node->pos.x += node->tw;
    if (node->pos.x >= node->area.corner.x+node->area.width) {
      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;
      node->pos.y += node->th;
      
      if (node->pos.y >= node->area.corner.y+node->area.height) {
	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->channel++;
	if (node->channel < ea_count(node->f_source)) {
	  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);
	  
	  filter_calc_valid_req_area(node->f, &node->tile->area, &node->area);
	  
	  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;
	}
      }
    }
  }
  else if (node->mode == MODE_ITER) {
    node->f->mode_iter->iter_next(node->iter, &node->pos, &node->channel);
    
    node->tw = tw_get(node->f_source_curr, node->pos.scale);
    node->th = th_get(node->f_source_curr, node->pos.scale);
  }
  else
    abort();
}
Пример #19
0
void render_node_del(Render_Node *node)
{
  int i;
  
  if (node->inputs) {
    for(i=0;i<ea_count(node->inputs);i++)
      tiledata_del(ea_data(node->inputs, i));
    eina_array_free(node->inputs);
  }
  
  if (node->f_source)
    eina_array_free(node->f_source);
  
  if (node->tile && !cache_tile_get(&node->tile->hash))
    tile_del(node->tile);
  
  free(node);
}
Пример #20
0
//gives the predecessor according to channel
Filter *filter_get_input_filter(Filter *f,  int channel)
{
  Filter *input;
  
  if (!f->node->con_ch_in)
    return NULL;
  
  if (ea_count(f->node->con_ch_in) <= channel)
    return NULL;
  
  input = ((Meta*)ea_data(f->node->con_ch_in, channel))->filter;
  
  //FIXME too simple, channels?
  while (!input->mode_buffer && !input->mode_iter)
    input = filter_get_input_filter(input,  channel);
  
  return input;
}
Пример #21
0
void filter_hash_recalc(Filter *f)
{
  Filter *next;
  int i;
  int len;
    
  len = snprintf(f->hash.data, 1020, "%u%s", f->hash.prevhash, f->fc->shortname);
  
  if (len >= 1020)
    abort();
  
  for(i=0;i<ea_count(f->settings);i++) {
    len += mt_data_snprint(&f->hash.data[len], 
			   1024-len,
			   ((Meta*)ea_data(f->settings, i))->type,
			   ((Meta*)ea_data(f->settings, i))->data);
    if (len >= 1020)
      abort();
  }
  
  for(i=0;i<ea_count(f->tune);i++) {
    if (!((Meta*)ea_data(f->tune, i))->data) {
      printf("FIXME! no data for tune %d (%s) in %s\n", i, ((Meta*)ea_data(f->tune, i))->name, f->fc->shortname);
      continue;
    }
    //assert(((Meta*)ea_data(f->tune, i))->data);
    len += mt_data_snprint(&f->hash.data[len], 
			   1024-len,
			   ((Meta*)ea_data(f->tune, i))->type,
			   ((Meta*)ea_data(f->tune, i))->data);
    if (len >= 1020)
      abort();
  }
  
  len += snprintf(&f->hash.data[len], 1024-len, "tail");
  
  f->hash.len = len;
  f->hash.hash = eina_hash_superfast(f->hash.data, len);
    
  if (f->node->con_trees_out && ea_count(f->node->con_trees_out)) {
    assert(ea_count(f->node->con_trees_out) == 1);
    
    next = ((Con *)ea_data(f->node->con_trees_out, 0))->sink->filter;
    next->hash.prevhash = f->hash.hash;
    filter_hash_recalc(next);
  }
}
Пример #22
0
static void _worker(Filter *f, Eina_Array *in, Eina_Array *out, Rect *area, int thread_id)
{ 
  int i, j, ch;
  int w, h;
  uint16_t *output;
  uint16_t *input;
  uint16_t *pos;
  int scale;
  _Data *data = ea_data(f->data, 0);
  Tiledata *in_td, *out_td;
  Rect in_area;
  lfModifier *mod;
  float *coords;
  float x, y;
  float fx, fy;
  
  assert(in && ea_count(in) == 1);
  assert(out && ea_count(out) == 1);
  
  hack_tiledata_fixsize_mt(6, ea_data(out, 0));
  
  in_td = ((Tiledata*)ea_data(in, 0));
  in_area = in_td->area;
  input = in_td->data;
  out_td = ((Tiledata*)ea_data(out, 0));
  output = out_td->data;  
  
  //has been executed by area calc! (hacky?)
  assert(data->common->exif_loaded);
  
  if (check_exif(data)) {
    printf("FIXME: lensfun pass through if lens not identified! %d\n", data->common->exif_loaded);
    return;
  }
  
  if (area->corner.scale) {
    scale = area->corner.scale-1;
    w = ((Dim*)data->common->dim_in_meta->data)->width;
    h = ((Dim*)data->common->dim_in_meta->data)->height;
    
    mod = lf_modifier_new(data->common->lens, data->common->lens->CropFactor, w>>scale, h>>scale);
    lf_modifier_initialize(mod, data->common->lens, LF_PF_U16, data->common->f, data->common->f_num, data->common->f_dist, 0.0, LF_RECTILINEAR, LF_MODIFY_ALL, 0);
    
    coords = malloc(2*3*sizeof(float)*area->width);
    
    //FIXME fix negative y and x rounding (->fx)
    
    for(j=0;j<area->height;j++) {
      lf_modifier_apply_subpixel_geometry_distortion(mod, area->corner.x, area->corner.y+j, area->width, 1, coords);
      for(i=0;i<area->width;i++)
        for(ch=0;ch<3;ch++) {
          //FIXME can we realiably catch this in area_calc?
          x = coords[i*2*3+ch*2];
          y = coords[i*2*3+ch*2+1];
          if (x < in_area.corner.x || x >= in_area.corner.x+in_area.width-1)
            continue;
          if (y < in_area.corner.y || y >= in_area.corner.y+in_area.height-1)
            continue;
          fx = x-(int)x;
          fy = y-(int)y;
          pos = tileptr16_3(in_td, x, y) + ch;
          tileptr16_3(out_td, area->corner.x+i, area->corner.y+j)[ch] = 
            pos[0]*(1.0-fx)*(1.0-fy)
            +pos[3]*(fx)*(1.0-fy)
            +pos[in_area.width*3]*(1.0-fx)*(fy)
            +pos[in_area.width*3+3]*(fx)*(fy);
        }
    }
    
    lf_modifier_destroy(mod);
    free(coords);
  }
Пример #23
0
static void _worker(Filter *f, Eina_Array *in, Eina_Array *out, Rect *area, int thread_id)
{
  _Data *data = ea_data(f->data, thread_id);
  uint32_t render_r, frac, actual_r;
  int ch;
  int i, j;
  int x, y;
  Rect *in_area;
  
  actual_r = r_calc(*data->sigma, area->corner.scale);
  
  frac = actual_r % 16;
  actual_r = actual_r / 16;
  
  render_r = actual_r+1;
  
  Tiledata buf_t1;
  Tiledata buf_t2;
  Rect buf_area;
  
  _area_calc(f, area, &buf_area);
  
  buf_t1.area = buf_area;
  buf_t2.area = buf_area;
  buf_t1.data = data->buf1;
  buf_t2.data = data->buf2;
   
  assert(in && ea_count(in) == 3);
  assert(out && ea_count(out) == 3);

  in_area = &((Tiledata*)ea_data(in, 0))->area;
    
  for(ch=0;ch<3;ch++) {
    if (!render_r) {
      assert(area->corner.x == in_area->corner.x);
      
      memcpy(((Tiledata*)ea_data(out, ch))->data,
	     ((Tiledata*)ea_data(in, ch))->data,
	     DEFAULT_TILE_AREA);
    }
    else {
    for(i=0;i<(DEFAULT_TILE_SIZE+2*render_r*3);i++) {
      x = i+area->corner.x-render_r*3;
      y = area->corner.y-2*render_r;
      _accu_blur(x, y, ea_data(in, ch), &buf_t1, actual_r, 2*render_r, in_area->width, buf_area.width, frac);
    }
    for(i=0;i<(DEFAULT_TILE_SIZE+2*render_r*3);i++) {
      x = i+area->corner.x-render_r*3;
      y = area->corner.y-render_r;
      _accu_blur(x, y, &buf_t1, &buf_t2, actual_r, render_r, buf_area.width, buf_area.width, frac);
    }
    for(i=0;i<(DEFAULT_TILE_SIZE+2*actual_r*3);i++) {
      x = i+area->corner.x-actual_r*3;
      y = area->corner.y;
      _accu_blur(x, y, &buf_t2, &buf_t1, actual_r, 0, buf_area.width, buf_area.width, frac);
    }
      
    for(j=0;j<DEFAULT_TILE_SIZE;j++) {
      x = area->corner.x-2*render_r;
      y = j+area->corner.y;
      
      _accu_blur_x(x, y, &buf_t1, &buf_t2, actual_r, 2*render_r, frac);
    }
    for(j=0;j<DEFAULT_TILE_SIZE;j++) {
      x = area->corner.x-render_r;
      y = j+area->corner.y;
      
      _accu_blur_x(x, y, &buf_t2, &buf_t1, actual_r, render_r, frac);
    }
    for(j=0;j<DEFAULT_TILE_SIZE;j++) {
      x = area->corner.x;
      y = j+area->corner.y;
      
      _accu_blur_x(x, y, &buf_t1, ea_data(out, ch), actual_r, 0, frac);
    }
    }
  }

}
Пример #24
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)));
}
Пример #25
0
//FIXME check if setting does exist, give some debug info if parsing fails!
Eina_List *lime_filter_chain_deserialize(char *str)
{
  int i;
  int checksettings;
  Meta *m;
  Filter *f, *last_f = NULL;
  Eina_List *filters = NULL;
  
  str = strdup(str);
  
  char *last = str + strlen(str);
  char *next = str;
  char *next_comma;
  char *cur = str;
  const char *setting;
  char *tmp;
  while (cur) {
    next = next_single_colon(cur);
    next_comma = strchr(cur, ',');
    if (next || next_comma) {
      if (next && (next < next_comma || !next_comma)) {
        printf("%s with settings\n", cur);
        checksettings = 1;
        *next = '\0';
        f = lime_filter_new(cur);
      }
      else if (next_comma && (next > next_comma || !next)) {
        printf("%s no settings\n", cur);
        checksettings = 0;
        *next_comma = '\0';
        f = lime_filter_new(cur);
        cur = next_comma+1;
        next = NULL;
      }
      else {
        //FIXME  check rethink?
        abort();
      }
    }
    else {
      printf("%s last filter no settings\n", cur);
      checksettings = 0;
      f = lime_filter_new(cur);
      next = NULL;
      cur = NULL;
    }
    
    if (!f) {
      printf("no filter for %s\n", cur);
      return NULL;
    }
    
    if (next && next+1 < last)
      cur = next+1;
    else
      checksettings = 0;
    
    //f = fc->filter_new_f();
    
    if (last_f)
      lime_filter_connect(last_f, f);
    
    last_f = f;
    
    filters = eina_list_append(filters, f);
    
    //settings
    if (cur && checksettings) {
      next = strchr(cur, '=');
      if (strchr(cur, ',') && next > strchr(cur, ','))
        break;
      while (next) {
        *next = '\0';
        
          setting = cur;
          assert(next+1 < last);
          cur = next+1;
  
        if (!ea_count(f->settings)) {
          printf("no settings for %s\n", f->fc->name);
          return NULL;
        }
  
        for(i=0;i<ea_count(f->settings);i++) {
          m = ea_data(f->settings, i);
          if (!strncmp(setting, m->name, strlen(setting))) {
            setting = m->name;
            break;
          }
        }
            
        switch (lime_setting_type_get(f, setting)) {
          case MT_INT :
            lime_setting_int_set(f, setting, atoi(cur));
            break;
          case MT_FLOAT :
            lime_setting_float_set(f, setting, atof(cur));
            break;
	  case MT_STRING :
            tmp = strdup(cur);
            if (next_single_colon(tmp))
              *next_single_colon(tmp) = '\0';
            if (strchr(tmp, ','))
              *strchr(tmp, ',') = '\0';
            lime_setting_string_set(f, setting, string_unescape_colon(tmp));
	    printf("set %s to %s\n", setting, string_unescape_colon(tmp));
            free(tmp);
            break;
          default :
            if (lime_setting_type_get(f, setting) == -1)
              printf("setting %s for filter %s not known (filter implementation changed?)\n", setting, f->fc->name);
            else
              printf("FIXME implement type %s settings parsing\n", mt_type_str(lime_setting_type_get(f, setting)));
        }
          
          next = next_single_colon(cur);
          if (next && next+1 < last && (!strchr(cur, ',') || next < strchr(cur, ','))) {
            cur = next+1;
            next = strchr(cur, '=');
          }
          else
            next = NULL;
        
        
      }
      
      if (cur)
        cur = strchr(cur, ',');
      if (cur)
        cur++;
    }
    
    if (cur >= last)
      cur = NULL;
      
  }
  
  free(str);
  
  return filters;
}
Пример #26
0
//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;
}
Пример #27
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;
}
Пример #28
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();
}