Beispiel #1
0
static void linear_shortcut (GeglBufferIterator *iter)
{
  GeglBufferIteratorPriv *priv = iter->priv;
  SubIterState *sub0 = &priv->sub_iter[0];
  int index;
  int re_use_first[16] = {0,};

  for (index = priv->num_buffers-1; index >=0 ; index--)
  {
    SubIterState *sub = &priv->sub_iter[index];

    sub->real_roi    = sub0->full_rect;
    iter->roi[index] = sub0->full_rect;
    iter->length = iter->roi[0].width * iter->roi[0].height;

    if (priv->sub_iter[0].buffer == sub->buffer && index != 0)
    {
      if (sub->format == priv->sub_iter[0].format)
        re_use_first[index] = 1;
    }

    if (!re_use_first[index])
    {
      gegl_buffer_lock (sub->buffer);
      if (index == 0)
        get_tile (iter, index);
      else
      {
        if (sub->buffer->tile_width == sub->buffer->extent.width 
            && sub->buffer->tile_height == sub->buffer->extent.height
            && sub->buffer->extent.x == iter->roi[index].x
            && sub->buffer->extent.y == iter->roi[index].y)
        {
          get_tile (iter, index);
        }
        else
          get_indirect (iter, index);
      }
    }
  }
  for (index = 1; index < priv->num_buffers; index++)
  {
    if (re_use_first[index])
    {
      g_print ("!\n");
      iter->data[index] = iter->data[0];
    }
  }

  priv->state = GeglIteratorState_Invalid; /* quit on next iterator_next */
}
Beispiel #2
0
static void
load_rects (GeglBufferIterator *iter)
{
  GeglBufferIteratorPriv *priv = iter->priv;
  GeglIteratorState next_state = GeglIteratorState_InTile;
  int index;

  for (index = 0; index < priv->num_buffers; index++)
    {
      if (needs_indirect_read (iter, index))
        get_indirect (iter, index);
      else
        get_tile (iter, index);

      if ((next_state != GeglIteratorState_InRows) && needs_rows (iter, index))
        {
          next_state = GeglIteratorState_InRows;
        }
    }

  if (next_state == GeglIteratorState_InRows)
    {
      if (iter->roi[0].height == 1)
        next_state = GeglIteratorState_InTile;

      priv->remaining_rows = iter->roi[0].height - 1;

      for (index = 0; index < priv->num_buffers; index++)
        {
          SubIterState *sub = &priv->sub_iter[index];

          int offset_x = iter->roi[index].x - sub->real_roi.x;
          int offset_y = iter->roi[index].y - sub->real_roi.y;

          iter->data[index] = ((char *)iter->data[index]) + (offset_y * sub->row_stride + offset_x * sub->format_bpp);
          iter->roi[index].height = 1;
        }
    }

  iter->length = iter->roi[0].width * iter->roi[0].height;
  priv->state  = next_state;
}
Beispiel #3
0
/* This looks in the virtqueue and for the first available buffer, and converts
 * it to an iovec for convenient access.  Since descriptors consist of some
 * number of output then some number of input descriptors, it's actually two
 * iovecs, but we pack them into one and note how many of each there were.
 *
 * This function returns the descriptor number found, or vq->num (which
 * is never a valid descriptor number) if none was found. */
unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
			   struct iovec iov[], unsigned int iov_size,
			   unsigned int *out_num, unsigned int *in_num,
			   struct vhost_log *log, unsigned int *log_num)
{
	struct vring_desc desc;
	unsigned int i, head, found = 0;
	u16 last_avail_idx;
	int ret;

	/* Check it isn't doing very strange things with descriptor numbers. */
	last_avail_idx = vq->last_avail_idx;
	if (get_user(vq->avail_idx, &vq->avail->idx)) {
		vq_err(vq, "Failed to access avail idx at %p\n",
		       &vq->avail->idx);
		return vq->num;
	}

	if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) {
		vq_err(vq, "Guest moved used index from %u to %u",
		       last_avail_idx, vq->avail_idx);
		return vq->num;
	}

	/* If there's nothing new since last we looked, return invalid. */
	if (vq->avail_idx == last_avail_idx)
		return vq->num;

	/* Only get avail ring entries after they have been exposed by guest. */
	smp_rmb();

	/* Grab the next descriptor number they're advertising, and increment
	 * the index we've seen. */
	if (get_user(head, &vq->avail->ring[last_avail_idx % vq->num])) {
		vq_err(vq, "Failed to read head: idx %d address %p\n",
		       last_avail_idx,
		       &vq->avail->ring[last_avail_idx % vq->num]);
		return vq->num;
	}

	/* If their number is silly, that's an error. */
	if (head >= vq->num) {
		vq_err(vq, "Guest says index %u > %u is available",
		       head, vq->num);
		return vq->num;
	}

	/* When we start there are none of either input nor output. */
	*out_num = *in_num = 0;
	if (unlikely(log))
		*log_num = 0;

	i = head;
	do {
		unsigned iov_count = *in_num + *out_num;
		if (i >= vq->num) {
			vq_err(vq, "Desc index is %u > %u, head = %u",
			       i, vq->num, head);
			return vq->num;
		}
		if (++found > vq->num) {
			vq_err(vq, "Loop detected: last one at %u "
			       "vq size %u head %u\n",
			       i, vq->num, head);
			return vq->num;
		}
		ret = copy_from_user(&desc, vq->desc + i, sizeof desc);
		if (ret) {
			vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
			       i, vq->desc + i);
			return vq->num;
		}
		if (desc.flags & VRING_DESC_F_INDIRECT) {
			ret = get_indirect(dev, vq, iov, iov_size,
					   out_num, in_num,
					   log, log_num, &desc);
			if (ret < 0) {
				vq_err(vq, "Failure detected "
				       "in indirect descriptor at idx %d\n", i);
				return vq->num;
			}
			continue;
		}

		ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
				     iov_size - iov_count);
		if (ret < 0) {
			vq_err(vq, "Translation failure %d descriptor idx %d\n",
			       ret, i);
			return vq->num;
		}
		if (desc.flags & VRING_DESC_F_WRITE) {
			/* If this is an input descriptor,
			 * increment that count. */
			*in_num += ret;
			if (unlikely(log)) {
				log[*log_num].addr = desc.addr;
				log[*log_num].len = desc.len;
				++*log_num;
			}
		} else {
			/* If it's an output descriptor, they're all supposed
			 * to come before any input descriptors. */
			if (*in_num) {
				vq_err(vq, "Descriptor has out after in: "
				       "idx %d\n", i);
				return vq->num;
			}
			*out_num += ret;
		}
	} while ((i = next_desc(&desc)) != -1);

	/* On success, increment avail index. */
	vq->last_avail_idx++;
	return head;
}