Skip to content

Commit

Permalink
drm/vmwgfx: Convert screen targets to new helpers v3
Browse files Browse the repository at this point in the history
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: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Sinclair Yeh <syeh@vmware.com>
  • Loading branch information
Thomas Hellstrom committed Aug 5, 2015
1 parent 10b1e0c commit 6bf6bf0
Show file tree
Hide file tree
Showing 6 changed files with 534 additions and 679 deletions.
5 changes: 0 additions & 5 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
24 changes: 5 additions & 19 deletions drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
return ret;
}

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

return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
149 changes: 119 additions & 30 deletions drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -467,10 +466,14 @@ 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");
}
}

return -ENOSYS;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}


Expand Down Expand Up @@ -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,
Expand All @@ -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;

Expand Down Expand Up @@ -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;
}
37 changes: 25 additions & 12 deletions drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -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
Expand Down Expand Up @@ -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,
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_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);
int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer *framebuffer,
struct drm_clip_rect *clips,
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,
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
2 changes: 1 addition & 1 deletion drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Loading

0 comments on commit 6bf6bf0

Please sign in to comment.