📄 vino.c
字号:
dprintk("vino_queue_free_with_count(): freeing buffer %d\n", i); vino_free_buffer(q->buffer[i]); kfree(q->buffer[i]); } q->type = VINO_MEMORY_NONE; q->magic = 0;}static void vino_queue_free(struct vino_framebuffer_queue *q){ dprintk("vino_queue_free():\n"); if (q->magic != VINO_QUEUE_MAGIC) return; if (q->type != VINO_MEMORY_MMAP) return; mutex_lock(&q->queue_mutex); vino_queue_free_with_count(q, q->length); mutex_unlock(&q->queue_mutex);}static int vino_queue_init(struct vino_framebuffer_queue *q, unsigned int *length){ unsigned int i; int ret = 0; dprintk("vino_queue_init(): length = %d\n", *length); if (q->magic == VINO_QUEUE_MAGIC) { dprintk("vino_queue_init(): queue already initialized!\n"); return -EINVAL; } if (q->type != VINO_MEMORY_NONE) { dprintk("vino_queue_init(): queue already initialized!\n"); return -EINVAL; } if (*length < 1) return -EINVAL; mutex_lock(&q->queue_mutex); if (*length > VINO_FRAMEBUFFER_COUNT_MAX) *length = VINO_FRAMEBUFFER_COUNT_MAX; q->length = 0; for (i = 0; i < *length; i++) { dprintk("vino_queue_init(): allocating buffer %d\n", i); q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer), GFP_KERNEL); if (!q->buffer[i]) { dprintk("vino_queue_init(): kmalloc() failed\n"); ret = -ENOMEM; break; } ret = vino_allocate_buffer(q->buffer[i], VINO_FRAMEBUFFER_SIZE); if (ret) { kfree(q->buffer[i]); dprintk("vino_queue_init(): " "vino_allocate_buffer() failed\n"); break; } q->buffer[i]->id = i; if (i > 0) { q->buffer[i]->offset = q->buffer[i - 1]->offset + q->buffer[i - 1]->size; } else { q->buffer[i]->offset = 0; } spin_lock_init(&q->buffer[i]->state_lock); dprintk("vino_queue_init(): buffer = %d, offset = %d, " "size = %d\n", i, q->buffer[i]->offset, q->buffer[i]->size); } if (ret) { vino_queue_free_with_count(q, i); *length = 0; } else { q->length = *length; vino_fifo_init(&q->in, q->length); vino_fifo_init(&q->out, q->length); q->type = VINO_MEMORY_MMAP; q->magic = VINO_QUEUE_MAGIC; } mutex_unlock(&q->queue_mutex); return ret;}static struct vino_framebuffer *vino_queue_add(struct vino_framebuffer_queue *q, unsigned int id){ struct vino_framebuffer *ret = NULL; unsigned int total; unsigned long flags; dprintk("vino_queue_add(): id = %d\n", id); if (q->magic != VINO_QUEUE_MAGIC) { return ret; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) goto out; if (id >= q->length) goto out; /* not needed?: if (vino_fifo_full(&q->out)) { goto out; }*/ /* check that outgoing queue isn't already full * (or that it won't become full) */ total = vino_fifo_get_used(&q->in) + vino_fifo_get_used(&q->out); if (total >= q->length) goto out; if (vino_fifo_enqueue(&q->in, id)) goto out; ret = q->buffer[id];out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}static struct vino_framebuffer *vino_queue_transfer(struct vino_framebuffer_queue *q){ struct vino_framebuffer *ret = NULL; struct vino_framebuffer *fb; int id; unsigned long flags; dprintk("vino_queue_transfer():\n"); if (q->magic != VINO_QUEUE_MAGIC) { return ret; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) goto out; // now this actually removes an entry from the incoming queue if (vino_fifo_dequeue(&q->in, &id)) { goto out; } dprintk("vino_queue_transfer(): id = %d\n", id); fb = q->buffer[id]; // we have already checked that the outgoing queue is not full, but... if (vino_fifo_enqueue(&q->out, id)) { printk(KERN_ERR "vino_queue_transfer(): " "outgoing queue is full, this shouldn't happen!\n"); goto out; } ret = fb;out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}/* returns true/false */static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q, unsigned int id){ int ret = 0; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return ret; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) goto out; ret = vino_fifo_has_id(&q->in, id);out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}/* returns true/false */static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q, unsigned int id){ int ret = 0; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return ret; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) goto out; ret = vino_fifo_has_id(&q->out, id);out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}static int vino_queue_get_incoming(struct vino_framebuffer_queue *q, unsigned int *used){ int ret = 0; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return VINO_QUEUE_ERROR; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) { ret = VINO_QUEUE_ERROR; goto out; } *used = vino_fifo_get_used(&q->in);out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q, unsigned int *used){ int ret = 0; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return VINO_QUEUE_ERROR; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) { ret = VINO_QUEUE_ERROR; goto out; } *used = vino_fifo_get_used(&q->out);out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}#if 0 /* keep */;static int vino_queue_get_total(struct vino_framebuffer_queue *q, unsigned int *total){ int ret = 0; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return VINO_QUEUE_ERROR; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) { ret = VINO_QUEUE_ERROR; goto out; } *total = vino_fifo_get_used(&q->in) + vino_fifo_get_used(&q->out);out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}#endifstatic struct vino_framebuffer *vino_queue_peek(struct vino_framebuffer_queue *q, unsigned int *id){ struct vino_framebuffer *ret = NULL; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return ret; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) goto out; if (vino_fifo_peek(&q->in, id)) { goto out; } ret = q->buffer[*id];out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}static struct vino_framebuffer *vino_queue_remove(struct vino_framebuffer_queue *q, unsigned int *id){ struct vino_framebuffer *ret = NULL; unsigned long flags; dprintk("vino_queue_remove():\n"); if (q->magic != VINO_QUEUE_MAGIC) { return ret; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) goto out; if (vino_fifo_dequeue(&q->out, id)) { goto out; } dprintk("vino_queue_remove(): id = %d\n", *id); ret = q->buffer[*id];out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}static structvino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q, unsigned int id){ struct vino_framebuffer *ret = NULL; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return ret; } spin_lock_irqsave(&q->queue_lock, flags); if (q->length == 0) goto out; if (id >= q->length) goto out; ret = q->buffer[id]; out: spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q){ unsigned int length = 0; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return length; } spin_lock_irqsave(&q->queue_lock, flags); length = q->length; spin_unlock_irqrestore(&q->queue_lock, flags); return length;}static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q){ unsigned int i; int ret = 0; unsigned long flags; if (q->magic != VINO_QUEUE_MAGIC) { return ret; } spin_lock_irqsave(&q->queue_lock, flags); for (i = 0; i < q->length; i++) { if (q->buffer[i]->map_count > 0) { ret = 1; break; } } spin_unlock_irqrestore(&q->queue_lock, flags); return ret;}/* VINO functions *//* execute with input_lock locked */static void vino_update_line_size(struct vino_channel_settings *vcs){ unsigned int w = vcs->clipping.right - vcs->clipping.left; unsigned int d = vcs->decimation; unsigned int bpp = vino_data_formats[vcs->data_format].bpp; unsigned int lsize; dprintk("update_line_size(): before: w = %d, d = %d, " "line_size = %d\n", w, d, vcs->line_size); /* line size must be multiple of 8 bytes */ lsize = (bpp * (w / d)) & ~7; w = (lsize / bpp) * d; vcs->clipping.right = vcs->clipping.left + w; vcs->line_size = lsize; dprintk("update_line_size(): after: w = %d, d = %d, " "line_size = %d\n", w, d, vcs->line_size);}/* execute with input_lock locked */static void vino_set_clipping(struct vino_channel_settings *vcs, unsigned int x, unsigned int y, unsigned int w, unsigned int h){ unsigned int maxwidth, maxheight; unsigned int d; maxwidth = vino_data_norms[vcs->data_norm].width; maxheight = vino_data_norms[vcs->data_norm].height; d = vcs->decimation; y &= ~1; /* odd/even fields */ if (x > maxwidth) { x = 0; } if (y > maxheight) { y = 0; } if (((w / d) < VINO_MIN_WIDTH) || ((h / d) < VINO_MIN_HEIGHT)) { w = VINO_MIN_WIDTH * d; h = VINO_MIN_HEIGHT * d; } if ((x + w) > maxwidth) { w = maxwidth - x; if ((w / d) < VINO_MIN_WIDTH) x = maxwidth - VINO_MIN_WIDTH * d; } if ((y + h) > maxheight) { h = maxheight - y; if ((h / d) < VINO_MIN_HEIGHT) y = maxheight - VINO_MIN_HEIGHT * d; } vcs->clipping.left = x; vcs->clipping.top = y; vcs->clipping.right = x + w; vcs->clipping.bottom = y + h; vino_update_line_size(vcs); dprintk("clipping %d, %d, %d, %d / %d - %d\n", vcs->clipping.left, vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom, vcs->decimation, vcs->line_size);}/* execute with input_lock locked */static inline void vino_set_default_clipping(struct vino_channel_settings *vcs){ vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width, vino_data_norms[vcs->data_norm].height);}/* execute with input_lock locked */static void vino_set_scaling(struct vino_channel_settings *vcs, unsigned int w, unsigned int h){ unsigned int x, y, curw, curh, d; x = vcs->clipping.left; y = vcs->clipping.top; curw = vcs->clipping.right - vcs->clipping.left; curh = vcs->clipping.bottom - vcs->clipping.top; d = max(curw / w, curh / h); dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n", w, h, curw, curh, d); if (d < 1) { d = 1; } else if (d > 8) { d = 8; } vcs->decimation = d; vino_set_clipping(vcs, x, y, w * d, h * d); dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left, vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom, vcs->decimation, vcs->line_size);}/* execute with input_lock locked */static inline void vino_set_default_scaling(struct vino_channel_settings *vcs){ vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left, vcs->clipping.bottom - vcs->clipping.top);}/* execute with input_lock locked */static void vino_set_framerate(struct vino_channel_settings *vcs, unsigned int fps){ unsigned int mask; switch (vcs->data_norm) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -