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 */ }
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; }
/* 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; }