Commit 6bf6bf03 authored by Thomas Hellstrom's avatar Thomas Hellstrom
Browse files

drm/vmwgfx: Convert screen targets to new helpers v3



Also implements the missing readback function and
fixes page flip in case of no event.

v2:
- Adapt to the work done for screen targets for 2d, in particular
Handle proxy surface updates.
- Remove execbuf quirks since we now use fifo reserve / commit.
- Revert the initial placement of vmw dma buffers.

v3: Address review comments.

Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarSinclair Yeh <syeh@vmware.com>
parent 10b1e0ca
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -343,9 +343,6 @@ enum vmw_display_unit_type {
};


#define VMW_QUIRK_DST_SID_OK (1U << 0)
#define VMW_QUIRK_SRC_SID_OK (1U << 1)

struct vmw_sw_context{
	struct drm_open_hash res_ht;
	bool res_ht_initialized;
@@ -368,7 +365,6 @@ struct vmw_sw_context{
	struct vmw_resource *error_resource;
	struct vmw_ctx_binding_state staged_bindings;
	struct list_head staged_cmd_res;
	uint32_t quirks;
};

struct vmw_legacy_display;
@@ -842,7 +838,6 @@ extern int vmw_execbuf_process(struct drm_file *file_priv,
			       void *kernel_commands,
			       uint32_t command_size,
			       uint64_t throttle_us,
			       uint32_t quirks,
			       struct drm_vmw_fence_rep __user
			       *user_fence_rep,
			       struct vmw_fence_obj **out_fence);
+5 −19
Original line number Diff line number Diff line
@@ -675,16 +675,11 @@ static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,

	cmd = container_of(header, struct vmw_sid_cmd, header);

	if (!(sw_context->quirks & VMW_QUIRK_SRC_SID_OK)) {
	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
				user_surface_converter,
				&cmd->body.src.sid, NULL);
		if (ret != 0)
	if (ret)
		return ret;
	}

	if (sw_context->quirks & VMW_QUIRK_DST_SID_OK)
		return 0;

	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
				 user_surface_converter,
@@ -1266,9 +1261,6 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
	if (unlikely(suffix->maximumOffset > bo_size))
		suffix->maximumOffset = bo_size;

	if (sw_context->quirks & VMW_QUIRK_DST_SID_OK)
		goto out_no_surface;

	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
				user_surface_converter, &cmd->dma.host.sid,
				NULL);
@@ -1507,9 +1499,6 @@ static int vmw_cmd_update_gb_image(struct vmw_private *dev_priv,

	cmd = container_of(header, struct vmw_gb_surface_cmd, header);

	if (sw_context->quirks & VMW_QUIRK_SRC_SID_OK)
		return 0;

	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
				 user_surface_converter,
				 &cmd->body.image.sid, NULL);
@@ -2554,7 +2543,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
			void *kernel_commands,
			uint32_t command_size,
			uint64_t throttle_us,
			uint32_t quirks,
			struct drm_vmw_fence_rep __user *user_fence_rep,
			struct vmw_fence_obj **out_fence)
{
@@ -2609,7 +2597,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
	sw_context->fp = vmw_fpriv(file_priv);
	sw_context->cur_reloc = 0;
	sw_context->cur_val_buf = 0;
	sw_context->quirks = quirks;
	INIT_LIST_HEAD(&sw_context->resource_list);
	sw_context->cur_query_bo = dev_priv->pinned_bo;
	sw_context->last_query_ctx = NULL;
@@ -2921,7 +2908,6 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
	ret = vmw_execbuf_process(file_priv, dev_priv,
				  (void __user *)(unsigned long)arg->commands,
				  NULL, arg->command_size, arg->throttle_us,
				  0,
				  (void __user *)(unsigned long)arg->fence_rep,
				  NULL);
	ttm_read_unlock(&dev_priv->reservation_sem);
+119 −30
Original line number Diff line number Diff line
@@ -427,10 +427,9 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
						   clips, NULL, NULL, 0, 0,
						   num_clips, inc, NULL);
	else
		ret = vmw_kms_stdu_do_surface_dirty(dev_priv, file_priv,
						    &vfbs->base,
						    clips, num_clips,
						    inc);
		ret = vmw_kms_stdu_surface_dirty(dev_priv, &vfbs->base,
						 clips, NULL, NULL, 0, 0,
						 num_clips, inc, NULL);

	vmw_fifo_flush(dev_priv, false);
	ttm_read_unlock(&dev_priv->reservation_sem);
@@ -467,6 +466,10 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
	case vmw_du_screen_object:
		return vmw_kms_sou_readback(dev_priv, file_priv, vfb,
					    user_fence_rep, vclips, num_clips);
	case vmw_du_screen_target:
		return vmw_kms_stdu_dma(dev_priv, file_priv, vfb,
					user_fence_rep, NULL, vclips, num_clips,
					1, false, true);
	default:
		WARN_ONCE(true,
			  "Readback called with invalid display system.\n");
@@ -632,20 +635,23 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
		increment = 2;
	}

	if (dev_priv->ldu_priv) {
		ret = vmw_kms_ldu_do_dmabuf_dirty(dev_priv, &vfbd->base,
						  flags, color,
						  clips, num_clips, increment);
	} else if (dev_priv->active_display_unit == vmw_du_screen_object) {
	switch (dev_priv->active_display_unit) {
	case vmw_du_screen_target:
		ret = vmw_kms_stdu_dma(dev_priv, NULL, &vfbd->base, NULL,
				       clips, NULL, num_clips, increment,
				       true, true);
		break;
	case vmw_du_screen_object:
		ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, &vfbd->base,
						  clips, num_clips, increment,
						  true,
						  NULL);
	} else {
		ret = vmw_kms_stdu_do_surface_dirty(dev_priv, file_priv,
						    &vfbd->base,
						    clips, num_clips,
						    increment);
		break;
	default:
		ret = -ENOSYS;
		WARN_ONCE(true,
			  "Dirty called with invalid display system.\n");
		break;
	}

	vmw_fifo_flush(dev_priv, false);
@@ -721,9 +727,9 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev,
{
	uint32_t format;
	struct drm_vmw_size content_base_size;
	struct vmw_resource *res;
	int ret;


	switch (mode_cmd->depth) {
	case 32:
	case 24:
@@ -762,15 +768,18 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev,
		return ret;
	}

	/* Use the same MOB backing for surface */
	vmw_dmabuf_reference(dmabuf_mob);

	(*srf_out)->res.backup = dmabuf_mob;
	res = &(*srf_out)->res;

	/* FIXME:  Waiting for fbdev rework to do a proper reserve/pin */
	ret = vmw_resource_validate(&(*srf_out)->res);
	/* Reserve and switch the backing mob. */
	mutex_lock(&res->dev_priv->cmdbuf_mutex);
	(void) vmw_resource_reserve(res, false, true);
	vmw_dmabuf_unreference(&res->backup);
	res->backup = vmw_dmabuf_reference(dmabuf_mob);
	res->backup_offset = 0;
	vmw_resource_unreserve(res, NULL, 0);
	mutex_unlock(&res->dev_priv->cmdbuf_mutex);

	return ret;
	return 0;
}


@@ -987,6 +996,7 @@ int vmw_kms_generic_present(struct vmw_private *dev_priv,
					    num_clips, 1, NULL);
}


int vmw_kms_present(struct vmw_private *dev_priv,
		    struct drm_file *file_priv,
		    struct vmw_framebuffer *vfb,
@@ -998,13 +1008,23 @@ int vmw_kms_present(struct vmw_private *dev_priv,
{
	int ret;

	if (dev_priv->active_display_unit == vmw_du_screen_target)
		ret = vmw_kms_stdu_present(dev_priv, file_priv, vfb, sid,
					   destX, destY, clips, num_clips);
	else
		ret = vmw_kms_generic_present(dev_priv, file_priv, vfb,
					      surface, sid, destX, destY,
					      clips, num_clips);
	switch (dev_priv->active_display_unit) {
	case vmw_du_screen_target:
		ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, clips,
						 &surface->res, destX, destY,
						 num_clips, 1, NULL);
		break;
	case vmw_du_screen_object:
		ret = vmw_kms_generic_present(dev_priv, file_priv, vfb, surface,
					      sid, destX, destY, clips,
					      num_clips);
		break;
	default:
		WARN_ONCE(true,
			  "Present called with invalid display system.\n");
		ret = -ENOSYS;
		break;
	}
	if (ret)
		return ret;

@@ -1882,3 +1902,72 @@ void vmw_kms_helper_resource_finish(struct vmw_resource *res,
	vmw_resource_unreserve(res, NULL, 0);
	mutex_unlock(&res->dev_priv->cmdbuf_mutex);
}

/**
 * vmw_kms_update_proxy - Helper function to update a proxy surface from
 * its backing MOB.
 *
 * @res: Pointer to the surface resource
 * @clips: Clip rects in framebuffer (surface) space.
 * @num_clips: Number of clips in @clips.
 * @increment: Integer with which to increment the clip counter when looping.
 * Used to skip a predetermined number of clip rects.
 *
 * This function makes sure the proxy surface is updated from its backing MOB
 * using the region given by @clips. The surface resource @res and its backing
 * MOB needs to be reserved and validated on call.
 */
int vmw_kms_update_proxy(struct vmw_resource *res,
			 const struct drm_clip_rect *clips,
			 unsigned num_clips,
			 int increment)
{
	struct vmw_private *dev_priv = res->dev_priv;
	struct drm_vmw_size *size = &vmw_res_to_srf(res)->base_size;
	struct {
		SVGA3dCmdHeader header;
		SVGA3dCmdUpdateGBImage body;
	} *cmd;
	SVGA3dBox *box;
	size_t copy_size = 0;
	int i;

	if (!clips)
		return 0;

	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips);
	if (!cmd) {
		DRM_ERROR("Couldn't reserve fifo space for proxy surface "
			  "update.\n");
		return -ENOMEM;
	}

	for (i = 0; i < num_clips; ++i, clips += increment, ++cmd) {
		box = &cmd->body.box;

		cmd->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
		cmd->header.size = sizeof(cmd->body);
		cmd->body.image.sid = res->id;
		cmd->body.image.face = 0;
		cmd->body.image.mipmap = 0;

		if (clips->x1 > size->width || clips->x2 > size->width ||
		    clips->y1 > size->height || clips->y2 > size->height) {
			DRM_ERROR("Invalid clips outsize of framebuffer.\n");
			return -EINVAL;
		}

		box->x = clips->x1;
		box->y = clips->y1;
		box->z = 0;
		box->w = clips->x2 - clips->x1;
		box->h = clips->y2 - clips->y1;
		box->d = 1;

		copy_size += sizeof(*cmd);
	}

	vmw_fifo_commit(dev_priv, copy_size);

	return 0;
}
+25 −12
Original line number Diff line number Diff line
@@ -239,6 +239,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
		     struct drm_vmw_rect *vclips,
		     uint32_t num_clips);


/*
 * Legacy display unit functions - vmwgfx_ldu.c
 */
@@ -249,6 +250,10 @@ int vmw_kms_ldu_do_dmabuf_dirty(struct vmw_private *dev_priv,
				unsigned flags, unsigned color,
				struct drm_clip_rect *clips,
				unsigned num_clips, int increment);
int vmw_kms_update_proxy(struct vmw_resource *res,
			 const struct drm_clip_rect *clips,
			 unsigned num_clips,
			 int increment);

/*
 * Screen Objects display functions - vmwgfx_scrn.c
@@ -282,17 +287,25 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv,
 */
int vmw_kms_stdu_init_display(struct vmw_private *dev_priv);
int vmw_kms_stdu_close_display(struct vmw_private *dev_priv);
int vmw_kms_stdu_do_surface_dirty(struct vmw_private *dev_priv,
				  struct drm_file *file_priv,
int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
			       struct vmw_framebuffer *framebuffer,
			       struct drm_clip_rect *clips,
				  unsigned num_clips, int increment);
int vmw_kms_stdu_present(struct vmw_private *dev_priv,
			       struct drm_vmw_rect *vclips,
			       struct vmw_resource *srf,
			       s32 dest_x,
			       s32 dest_y,
			       unsigned num_clips, int inc,
			       struct vmw_fence_obj **out_fence);
int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
		     struct drm_file *file_priv,
		     struct vmw_framebuffer *vfb,
			 uint32_t user_handle,
			 int32_t dest_x, int32_t dest_y,
			 struct drm_vmw_rect *clips,
			 uint32_t num_clips);
		     struct drm_vmw_fence_rep __user *user_fence_rep,
		     struct drm_clip_rect *clips,
		     struct drm_vmw_rect *vclips,
		     uint32_t num_clips,
		     int increment,
		     bool to_surface,
		     bool interruptible);


#endif
+1 −1
Original line number Diff line number Diff line
@@ -497,7 +497,7 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,

	ret = vmw_dmabuf_init(dev_priv, &user_bo->dma, size,
			      (dev_priv->has_mob) ?
			      &vmw_mob_placement :
			      &vmw_sys_placement :
			      &vmw_vram_sys_placement, true,
			      &vmw_user_dmabuf_destroy);
	if (unlikely(ret != 0))
Loading