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: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
This commit is contained in:
parent
10b1e0ca9c
commit
6bf6bf03b3
|
@ -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 vmw_sw_context{
|
||||||
struct drm_open_hash res_ht;
|
struct drm_open_hash res_ht;
|
||||||
bool res_ht_initialized;
|
bool res_ht_initialized;
|
||||||
|
@ -368,7 +365,6 @@ struct vmw_sw_context{
|
||||||
struct vmw_resource *error_resource;
|
struct vmw_resource *error_resource;
|
||||||
struct vmw_ctx_binding_state staged_bindings;
|
struct vmw_ctx_binding_state staged_bindings;
|
||||||
struct list_head staged_cmd_res;
|
struct list_head staged_cmd_res;
|
||||||
uint32_t quirks;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vmw_legacy_display;
|
struct vmw_legacy_display;
|
||||||
|
@ -842,7 +838,6 @@ extern int vmw_execbuf_process(struct drm_file *file_priv,
|
||||||
void *kernel_commands,
|
void *kernel_commands,
|
||||||
uint32_t command_size,
|
uint32_t command_size,
|
||||||
uint64_t throttle_us,
|
uint64_t throttle_us,
|
||||||
uint32_t quirks,
|
|
||||||
struct drm_vmw_fence_rep __user
|
struct drm_vmw_fence_rep __user
|
||||||
*user_fence_rep,
|
*user_fence_rep,
|
||||||
struct vmw_fence_obj **out_fence);
|
struct vmw_fence_obj **out_fence);
|
||||||
|
|
|
@ -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);
|
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,
|
||||||
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
|
user_surface_converter,
|
||||||
user_surface_converter,
|
&cmd->body.src.sid, NULL);
|
||||||
&cmd->body.src.sid, NULL);
|
if (ret)
|
||||||
if (ret != 0)
|
return 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,
|
return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
|
||||||
user_surface_converter,
|
user_surface_converter,
|
||||||
|
@ -1266,9 +1261,6 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
|
||||||
if (unlikely(suffix->maximumOffset > bo_size))
|
if (unlikely(suffix->maximumOffset > bo_size))
|
||||||
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,
|
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
|
||||||
user_surface_converter, &cmd->dma.host.sid,
|
user_surface_converter, &cmd->dma.host.sid,
|
||||||
NULL);
|
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);
|
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,
|
return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
|
||||||
user_surface_converter,
|
user_surface_converter,
|
||||||
&cmd->body.image.sid, NULL);
|
&cmd->body.image.sid, NULL);
|
||||||
|
@ -2554,7 +2543,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
|
||||||
void *kernel_commands,
|
void *kernel_commands,
|
||||||
uint32_t command_size,
|
uint32_t command_size,
|
||||||
uint64_t throttle_us,
|
uint64_t throttle_us,
|
||||||
uint32_t quirks,
|
|
||||||
struct drm_vmw_fence_rep __user *user_fence_rep,
|
struct drm_vmw_fence_rep __user *user_fence_rep,
|
||||||
struct vmw_fence_obj **out_fence)
|
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->fp = vmw_fpriv(file_priv);
|
||||||
sw_context->cur_reloc = 0;
|
sw_context->cur_reloc = 0;
|
||||||
sw_context->cur_val_buf = 0;
|
sw_context->cur_val_buf = 0;
|
||||||
sw_context->quirks = quirks;
|
|
||||||
INIT_LIST_HEAD(&sw_context->resource_list);
|
INIT_LIST_HEAD(&sw_context->resource_list);
|
||||||
sw_context->cur_query_bo = dev_priv->pinned_bo;
|
sw_context->cur_query_bo = dev_priv->pinned_bo;
|
||||||
sw_context->last_query_ctx = NULL;
|
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,
|
ret = vmw_execbuf_process(file_priv, dev_priv,
|
||||||
(void __user *)(unsigned long)arg->commands,
|
(void __user *)(unsigned long)arg->commands,
|
||||||
NULL, arg->command_size, arg->throttle_us,
|
NULL, arg->command_size, arg->throttle_us,
|
||||||
0,
|
|
||||||
(void __user *)(unsigned long)arg->fence_rep,
|
(void __user *)(unsigned long)arg->fence_rep,
|
||||||
NULL);
|
NULL);
|
||||||
ttm_read_unlock(&dev_priv->reservation_sem);
|
ttm_read_unlock(&dev_priv->reservation_sem);
|
||||||
|
|
|
@ -427,10 +427,9 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
|
||||||
clips, NULL, NULL, 0, 0,
|
clips, NULL, NULL, 0, 0,
|
||||||
num_clips, inc, NULL);
|
num_clips, inc, NULL);
|
||||||
else
|
else
|
||||||
ret = vmw_kms_stdu_do_surface_dirty(dev_priv, file_priv,
|
ret = vmw_kms_stdu_surface_dirty(dev_priv, &vfbs->base,
|
||||||
&vfbs->base,
|
clips, NULL, NULL, 0, 0,
|
||||||
clips, num_clips,
|
num_clips, inc, NULL);
|
||||||
inc);
|
|
||||||
|
|
||||||
vmw_fifo_flush(dev_priv, false);
|
vmw_fifo_flush(dev_priv, false);
|
||||||
ttm_read_unlock(&dev_priv->reservation_sem);
|
ttm_read_unlock(&dev_priv->reservation_sem);
|
||||||
|
@ -467,10 +466,14 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
|
||||||
case vmw_du_screen_object:
|
case vmw_du_screen_object:
|
||||||
return vmw_kms_sou_readback(dev_priv, file_priv, vfb,
|
return vmw_kms_sou_readback(dev_priv, file_priv, vfb,
|
||||||
user_fence_rep, vclips, num_clips);
|
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:
|
default:
|
||||||
WARN_ONCE(true,
|
WARN_ONCE(true,
|
||||||
"Readback called with invalid display system.\n");
|
"Readback called with invalid display system.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
@ -632,20 +635,23 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
|
||||||
increment = 2;
|
increment = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev_priv->ldu_priv) {
|
switch (dev_priv->active_display_unit) {
|
||||||
ret = vmw_kms_ldu_do_dmabuf_dirty(dev_priv, &vfbd->base,
|
case vmw_du_screen_target:
|
||||||
flags, color,
|
ret = vmw_kms_stdu_dma(dev_priv, NULL, &vfbd->base, NULL,
|
||||||
clips, num_clips, increment);
|
clips, NULL, num_clips, increment,
|
||||||
} else if (dev_priv->active_display_unit == vmw_du_screen_object) {
|
true, true);
|
||||||
|
break;
|
||||||
|
case vmw_du_screen_object:
|
||||||
ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, &vfbd->base,
|
ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, &vfbd->base,
|
||||||
clips, num_clips, increment,
|
clips, num_clips, increment,
|
||||||
true,
|
true,
|
||||||
NULL);
|
NULL);
|
||||||
} else {
|
break;
|
||||||
ret = vmw_kms_stdu_do_surface_dirty(dev_priv, file_priv,
|
default:
|
||||||
&vfbd->base,
|
ret = -ENOSYS;
|
||||||
clips, num_clips,
|
WARN_ONCE(true,
|
||||||
increment);
|
"Dirty called with invalid display system.\n");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
vmw_fifo_flush(dev_priv, false);
|
vmw_fifo_flush(dev_priv, false);
|
||||||
|
@ -721,9 +727,9 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev,
|
||||||
{
|
{
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
struct drm_vmw_size content_base_size;
|
struct drm_vmw_size content_base_size;
|
||||||
|
struct vmw_resource *res;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
switch (mode_cmd->depth) {
|
switch (mode_cmd->depth) {
|
||||||
case 32:
|
case 32:
|
||||||
case 24:
|
case 24:
|
||||||
|
@ -762,15 +768,18 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the same MOB backing for surface */
|
res = &(*srf_out)->res;
|
||||||
vmw_dmabuf_reference(dmabuf_mob);
|
|
||||||
|
|
||||||
(*srf_out)->res.backup = dmabuf_mob;
|
/* 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);
|
||||||
|
|
||||||
/* FIXME: Waiting for fbdev rework to do a proper reserve/pin */
|
return 0;
|
||||||
ret = vmw_resource_validate(&(*srf_out)->res);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -987,6 +996,7 @@ int vmw_kms_generic_present(struct vmw_private *dev_priv,
|
||||||
num_clips, 1, NULL);
|
num_clips, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int vmw_kms_present(struct vmw_private *dev_priv,
|
int vmw_kms_present(struct vmw_private *dev_priv,
|
||||||
struct drm_file *file_priv,
|
struct drm_file *file_priv,
|
||||||
struct vmw_framebuffer *vfb,
|
struct vmw_framebuffer *vfb,
|
||||||
|
@ -998,13 +1008,23 @@ int vmw_kms_present(struct vmw_private *dev_priv,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (dev_priv->active_display_unit == vmw_du_screen_target)
|
switch (dev_priv->active_display_unit) {
|
||||||
ret = vmw_kms_stdu_present(dev_priv, file_priv, vfb, sid,
|
case vmw_du_screen_target:
|
||||||
destX, destY, clips, num_clips);
|
ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, clips,
|
||||||
else
|
&surface->res, destX, destY,
|
||||||
ret = vmw_kms_generic_present(dev_priv, file_priv, vfb,
|
num_clips, 1, NULL);
|
||||||
surface, sid, destX, destY,
|
break;
|
||||||
clips, num_clips);
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -1882,3 +1902,72 @@ void vmw_kms_helper_resource_finish(struct vmw_resource *res,
|
||||||
vmw_resource_unreserve(res, NULL, 0);
|
vmw_resource_unreserve(res, NULL, 0);
|
||||||
mutex_unlock(&res->dev_priv->cmdbuf_mutex);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -239,6 +239,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
|
||||||
struct drm_vmw_rect *vclips,
|
struct drm_vmw_rect *vclips,
|
||||||
uint32_t num_clips);
|
uint32_t num_clips);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Legacy display unit functions - vmwgfx_ldu.c
|
* 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,
|
unsigned flags, unsigned color,
|
||||||
struct drm_clip_rect *clips,
|
struct drm_clip_rect *clips,
|
||||||
unsigned num_clips, int increment);
|
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
|
* 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_init_display(struct vmw_private *dev_priv);
|
||||||
int vmw_kms_stdu_close_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,
|
int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
|
||||||
struct drm_file *file_priv,
|
struct vmw_framebuffer *framebuffer,
|
||||||
struct vmw_framebuffer *framebuffer,
|
struct drm_clip_rect *clips,
|
||||||
struct drm_clip_rect *clips,
|
struct drm_vmw_rect *vclips,
|
||||||
unsigned num_clips, int increment);
|
struct vmw_resource *srf,
|
||||||
int vmw_kms_stdu_present(struct vmw_private *dev_priv,
|
s32 dest_x,
|
||||||
struct drm_file *file_priv,
|
s32 dest_y,
|
||||||
struct vmw_framebuffer *vfb,
|
unsigned num_clips, int inc,
|
||||||
uint32_t user_handle,
|
struct vmw_fence_obj **out_fence);
|
||||||
int32_t dest_x, int32_t dest_y,
|
int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
|
||||||
struct drm_vmw_rect *clips,
|
struct drm_file *file_priv,
|
||||||
uint32_t num_clips);
|
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
|
#endif
|
||||||
|
|
|
@ -497,7 +497,7 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
|
||||||
|
|
||||||
ret = vmw_dmabuf_init(dev_priv, &user_bo->dma, size,
|
ret = vmw_dmabuf_init(dev_priv, &user_bo->dma, size,
|
||||||
(dev_priv->has_mob) ?
|
(dev_priv->has_mob) ?
|
||||||
&vmw_mob_placement :
|
&vmw_sys_placement :
|
||||||
&vmw_vram_sys_placement, true,
|
&vmw_vram_sys_placement, true,
|
||||||
&vmw_user_dmabuf_destroy);
|
&vmw_user_dmabuf_destroy);
|
||||||
if (unlikely(ret != 0))
|
if (unlikely(ret != 0))
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue