Пример #1
0
/**
 * Send the fifo command to create a screen.
 */
static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
			       struct vmw_screen_object_unit *sou,
			       uint32_t x, uint32_t y,
			       struct drm_display_mode *mode)
{
	size_t fifo_size;

	struct {
		struct {
			uint32_t cmdType;
		} header;
		SVGAScreenObject obj;
	} *cmd;

	BUG_ON(!sou->buffer);

	fifo_size = sizeof(*cmd);
	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
	/* The hardware has hung, nothing we can do about it here. */
	if (unlikely(cmd == NULL)) {
		DRM_ERROR("Fifo reserve failed.\n");
		return -ENOMEM;
	}

	memset(cmd, 0, fifo_size);
	cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN;
	cmd->obj.structSize = sizeof(SVGAScreenObject);
	cmd->obj.id = sou->base.unit;
	cmd->obj.flags = SVGA_SCREEN_HAS_ROOT |
		(sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
	cmd->obj.size.width = mode->hdisplay;
	cmd->obj.size.height = mode->vdisplay;
	if (sou->base.is_implicit) {
		cmd->obj.root.x = x;
		cmd->obj.root.y = y;
	} else {
		cmd->obj.root.x = sou->base.gui_x;
		cmd->obj.root.y = sou->base.gui_y;
	}
	sou->base.set_gui_x = cmd->obj.root.x;
	sou->base.set_gui_y = cmd->obj.root.y;

	/* Ok to assume that buffer is pinned in vram */
	vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
	cmd->obj.backingStore.pitch = mode->hdisplay * 4;

	vmw_fifo_commit(dev_priv, fifo_size);

	sou->defined = true;

	return 0;
}
Пример #2
0
/**
 * vmw_stdu_dmabuf_fifo_commit - Callback to fill in and submit a DMA command.
 *
 * @dirty: The closure structure.
 *
 * Fills in the missing fields in a DMA command, and optionally encodes
 * a screen target update command, depending on transfer direction.
 */
static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)
{
    struct vmw_stdu_dirty *ddirty =
        container_of(dirty, struct vmw_stdu_dirty, base);
    struct vmw_screen_target_display_unit *stdu =
        container_of(dirty->unit, typeof(*stdu), base);
    struct vmw_stdu_dma *cmd = dirty->cmd;
    struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
    SVGA3dCmdSurfaceDMASuffix *suffix =
        (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits];
    size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix);

    if (!dirty->num_hits) {
        vmw_fifo_commit(dirty->dev_priv, 0);
        return;
    }

    cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
    cmd->header.size = sizeof(cmd->body) + blit_size;
    vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr);
    cmd->body.guest.pitch = ddirty->pitch;
    cmd->body.host.sid = stdu->display_srf->res.id;
    cmd->body.host.face = 0;
    cmd->body.host.mipmap = 0;
    cmd->body.transfer = ddirty->transfer;
    suffix->suffixSize = sizeof(*suffix);
    suffix->maximumOffset = ddirty->buf->base.num_pages * PAGE_SIZE;

    if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) {
        blit_size += sizeof(struct vmw_stdu_update);

        vmw_stdu_populate_update(&suffix[1], stdu->base.unit,
                                 ddirty->left, ddirty->right,
                                 ddirty->top, ddirty->bottom);
    }

    vmw_fifo_commit(dirty->dev_priv, sizeof(*cmd) + blit_size);

    ddirty->left = ddirty->top = S32_MAX;
    ddirty->right = ddirty->bottom = S32_MIN;
}
Пример #3
0
static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv,
				  struct vmw_framebuffer *framebuffer)
{
	struct vmw_dma_buffer *buf =
		container_of(framebuffer, struct vmw_framebuffer_dmabuf,
			     base)->buffer;
	int depth = framebuffer->base.depth;
	struct {
		uint32_t header;
		SVGAFifoCmdDefineGMRFB body;
	} *cmd;

	/* Emulate RGBA support, contrary to svga_reg.h this is not
	 * supported by hosts. This is only a problem if we are reading
	 * this value later and expecting what we uploaded back.
	 */
	if (depth == 32)
		depth = 24;

	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
	if (!cmd) {
		DRM_ERROR("Out of fifo space for dirty framebuffer command.\n");
		return -ENOMEM;
	}

	cmd->header = SVGA_CMD_DEFINE_GMRFB;
	cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel;
	cmd->body.format.colorDepth = depth;
	cmd->body.format.reserved = 0;
	cmd->body.bytesPerLine = framebuffer->base.pitches[0];
	/* Buffer is reserved in vram or GMR */
	vmw_bo_get_guest_ptr(&buf->base, &cmd->body.ptr);
	vmw_fifo_commit(dev_priv, sizeof(*cmd));

	return 0;
}
Пример #4
0
/**
 * Send put command to hw.
 *
 * Returns
 * -ERESTARTSYS if interrupted by a signal.
 */
static int vmw_overlay_send_put(struct vmw_private *dev_priv,
				struct vmw_dma_buffer *buf,
				struct drm_vmw_control_stream_arg *arg,
				bool interruptible)
{
	struct vmw_escape_video_flush *flush;
	size_t fifo_size;
	bool have_so = dev_priv->sou_priv ? true : false;
	int i, num_items;
	SVGAGuestPtr ptr;

	struct {
		struct vmw_escape_header escape;
		struct {
			uint32_t cmdType;
			uint32_t streamId;
		} header;
	} *cmds;
	struct {
		uint32_t registerId;
		uint32_t value;
	} *items;

	/* defines are a index needs + 1 */
	if (have_so)
		num_items = SVGA_VIDEO_DST_SCREEN_ID + 1;
	else
		num_items = SVGA_VIDEO_PITCH_3 + 1;

	fifo_size = sizeof(*cmds) + sizeof(*flush) + sizeof(*items) * num_items;

	cmds = vmw_fifo_reserve(dev_priv, fifo_size);
	/* hardware has hung, can't do anything here */
	if (!cmds)
		return -ENOMEM;

	items = (typeof(items))&cmds[1];
	flush = (struct vmw_escape_video_flush *)&items[num_items];

	/* the size is header + number of items */
	fill_escape(&cmds->escape, sizeof(*items) * (num_items + 1));

	cmds->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
	cmds->header.streamId = arg->stream_id;

	/* the IDs are neatly numbered */
	for (i = 0; i < num_items; i++)
		items[i].registerId = i;

	vmw_bo_get_guest_ptr(&buf->base, &ptr);
	ptr.offset += arg->offset;

	items[SVGA_VIDEO_ENABLED].value     = true;
	items[SVGA_VIDEO_FLAGS].value       = arg->flags;
	items[SVGA_VIDEO_DATA_OFFSET].value = ptr.offset;
	items[SVGA_VIDEO_FORMAT].value      = arg->format;
	items[SVGA_VIDEO_COLORKEY].value    = arg->color_key;
	items[SVGA_VIDEO_SIZE].value        = arg->size;
	items[SVGA_VIDEO_WIDTH].value       = arg->width;
	items[SVGA_VIDEO_HEIGHT].value      = arg->height;
	items[SVGA_VIDEO_SRC_X].value       = arg->src.x;
	items[SVGA_VIDEO_SRC_Y].value       = arg->src.y;
	items[SVGA_VIDEO_SRC_WIDTH].value   = arg->src.w;
	items[SVGA_VIDEO_SRC_HEIGHT].value  = arg->src.h;
	items[SVGA_VIDEO_DST_X].value       = arg->dst.x;
	items[SVGA_VIDEO_DST_Y].value       = arg->dst.y;
	items[SVGA_VIDEO_DST_WIDTH].value   = arg->dst.w;
	items[SVGA_VIDEO_DST_HEIGHT].value  = arg->dst.h;
	items[SVGA_VIDEO_PITCH_1].value     = arg->pitch[0];
	items[SVGA_VIDEO_PITCH_2].value     = arg->pitch[1];
	items[SVGA_VIDEO_PITCH_3].value     = arg->pitch[2];
	if (have_so) {
		items[SVGA_VIDEO_DATA_GMRID].value    = ptr.gmrId;
		items[SVGA_VIDEO_DST_SCREEN_ID].value = SVGA_ID_INVALID;
	}

	fill_flush(flush, arg->stream_id);

	vmw_fifo_commit(dev_priv, fifo_size);

	return 0;
}