mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
drm/vmwgfx: Fix Legacy Display Unit atomic drm support
Legacy Display Unit (LDU) fb dirty support used a custom fb dirty callback. Latter
handled only the DIRTYFB IOCTL presentation path but not the ADDFB2/PAGE_FLIP/RMFB
IOCTL path, common for Wayland compositors.
Get rid of the custom callback in favor of drm_atomic_helper_dirtyfb and unify the
handling of the presentation paths inside of vmw_ldu_primary_plane_atomic_update.
This also homogenizes the fb dirty callbacks across all DUs: LDU, SOU and STDU.
Signed-off-by: Martin Krastev <krastevm@vmware.com>
Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com>
Fixes: 2f5544ff03 ("drm/vmwgfx: Use atomic helper function for dirty fb IOCTL")
Cc: <stable@vger.kernel.org> # v5.0+
Signed-off-by: Zack Rusin <zackr@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230321020949.335012-3-zack@kde.org
This commit is contained in:
committed by
Zack Rusin
parent
35d86fb626
commit
a37a512db3
@@ -1396,70 +1396,10 @@ static void vmw_framebuffer_bo_destroy(struct drm_framebuffer *framebuffer)
|
|||||||
kfree(vfbd);
|
kfree(vfbd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vmw_framebuffer_bo_dirty(struct drm_framebuffer *framebuffer,
|
|
||||||
struct drm_file *file_priv,
|
|
||||||
unsigned int flags, unsigned int color,
|
|
||||||
struct drm_clip_rect *clips,
|
|
||||||
unsigned int num_clips)
|
|
||||||
{
|
|
||||||
struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
|
|
||||||
struct vmw_framebuffer_bo *vfbd =
|
|
||||||
vmw_framebuffer_to_vfbd(framebuffer);
|
|
||||||
struct drm_clip_rect norect;
|
|
||||||
int ret, increment = 1;
|
|
||||||
|
|
||||||
drm_modeset_lock_all(&dev_priv->drm);
|
|
||||||
|
|
||||||
if (!num_clips) {
|
|
||||||
num_clips = 1;
|
|
||||||
clips = &norect;
|
|
||||||
norect.x1 = norect.y1 = 0;
|
|
||||||
norect.x2 = framebuffer->width;
|
|
||||||
norect.y2 = framebuffer->height;
|
|
||||||
} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
|
|
||||||
num_clips /= 2;
|
|
||||||
increment = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (dev_priv->active_display_unit) {
|
|
||||||
case vmw_du_legacy:
|
|
||||||
ret = vmw_kms_ldu_do_bo_dirty(dev_priv, &vfbd->base, 0, 0,
|
|
||||||
clips, num_clips, increment);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -EINVAL;
|
|
||||||
WARN_ONCE(true, "Dirty called with invalid display system.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
vmw_cmd_flush(dev_priv, false);
|
|
||||||
|
|
||||||
drm_modeset_unlock_all(&dev_priv->drm);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vmw_framebuffer_bo_dirty_ext(struct drm_framebuffer *framebuffer,
|
|
||||||
struct drm_file *file_priv,
|
|
||||||
unsigned int flags, unsigned int color,
|
|
||||||
struct drm_clip_rect *clips,
|
|
||||||
unsigned int num_clips)
|
|
||||||
{
|
|
||||||
struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
|
|
||||||
|
|
||||||
if (dev_priv->active_display_unit == vmw_du_legacy &&
|
|
||||||
vmw_cmd_supported(dev_priv))
|
|
||||||
return vmw_framebuffer_bo_dirty(framebuffer, file_priv, flags,
|
|
||||||
color, clips, num_clips);
|
|
||||||
|
|
||||||
return drm_atomic_helper_dirtyfb(framebuffer, file_priv, flags, color,
|
|
||||||
clips, num_clips);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct drm_framebuffer_funcs vmw_framebuffer_bo_funcs = {
|
static const struct drm_framebuffer_funcs vmw_framebuffer_bo_funcs = {
|
||||||
.create_handle = vmw_framebuffer_bo_create_handle,
|
.create_handle = vmw_framebuffer_bo_create_handle,
|
||||||
.destroy = vmw_framebuffer_bo_destroy,
|
.destroy = vmw_framebuffer_bo_destroy,
|
||||||
.dirty = vmw_framebuffer_bo_dirty_ext,
|
.dirty = drm_atomic_helper_dirtyfb,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -507,11 +507,6 @@ void vmw_du_connector_destroy_state(struct drm_connector *connector,
|
|||||||
*/
|
*/
|
||||||
int vmw_kms_ldu_init_display(struct vmw_private *dev_priv);
|
int vmw_kms_ldu_init_display(struct vmw_private *dev_priv);
|
||||||
int vmw_kms_ldu_close_display(struct vmw_private *dev_priv);
|
int vmw_kms_ldu_close_display(struct vmw_private *dev_priv);
|
||||||
int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
|
|
||||||
struct vmw_framebuffer *framebuffer,
|
|
||||||
unsigned int flags, unsigned int color,
|
|
||||||
struct drm_clip_rect *clips,
|
|
||||||
unsigned int num_clips, int increment);
|
|
||||||
int vmw_kms_update_proxy(struct vmw_resource *res,
|
int vmw_kms_update_proxy(struct vmw_resource *res,
|
||||||
const struct drm_clip_rect *clips,
|
const struct drm_clip_rect *clips,
|
||||||
unsigned num_clips,
|
unsigned num_clips,
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
|
|||||||
.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
|
.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
|
||||||
.atomic_destroy_state = vmw_du_crtc_destroy_state,
|
.atomic_destroy_state = vmw_du_crtc_destroy_state,
|
||||||
.set_config = drm_atomic_helper_set_config,
|
.set_config = drm_atomic_helper_set_config,
|
||||||
|
.page_flip = drm_atomic_helper_page_flip,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -314,6 +315,12 @@ static const struct
|
|||||||
drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
|
drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
|
||||||
|
struct vmw_framebuffer *framebuffer,
|
||||||
|
unsigned int flags, unsigned int color,
|
||||||
|
struct drm_mode_rect *clips,
|
||||||
|
unsigned int num_clips);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Legacy Display Plane Functions
|
* Legacy Display Plane Functions
|
||||||
*/
|
*/
|
||||||
@@ -332,7 +339,6 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
|
|||||||
struct drm_framebuffer *fb;
|
struct drm_framebuffer *fb;
|
||||||
struct drm_crtc *crtc = new_state->crtc ?: old_state->crtc;
|
struct drm_crtc *crtc = new_state->crtc ?: old_state->crtc;
|
||||||
|
|
||||||
|
|
||||||
ldu = vmw_crtc_to_ldu(crtc);
|
ldu = vmw_crtc_to_ldu(crtc);
|
||||||
dev_priv = vmw_priv(plane->dev);
|
dev_priv = vmw_priv(plane->dev);
|
||||||
fb = new_state->fb;
|
fb = new_state->fb;
|
||||||
@@ -345,8 +351,31 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
|
|||||||
vmw_ldu_del_active(dev_priv, ldu);
|
vmw_ldu_del_active(dev_priv, ldu);
|
||||||
|
|
||||||
vmw_ldu_commit_list(dev_priv);
|
vmw_ldu_commit_list(dev_priv);
|
||||||
}
|
|
||||||
|
|
||||||
|
if (vfb && vmw_cmd_supported(dev_priv)) {
|
||||||
|
struct drm_mode_rect fb_rect = {
|
||||||
|
.x1 = 0,
|
||||||
|
.y1 = 0,
|
||||||
|
.x2 = vfb->base.width,
|
||||||
|
.y2 = vfb->base.height
|
||||||
|
};
|
||||||
|
struct drm_mode_rect *damage_rects = drm_plane_get_damage_clips(new_state);
|
||||||
|
u32 rect_count = drm_plane_get_damage_clips_count(new_state);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!damage_rects) {
|
||||||
|
damage_rects = &fb_rect;
|
||||||
|
rect_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vmw_kms_ldu_do_bo_dirty(dev_priv, vfb, 0, 0, damage_rects, rect_count);
|
||||||
|
|
||||||
|
drm_WARN_ONCE(plane->dev, ret,
|
||||||
|
"vmw_kms_ldu_do_bo_dirty failed with: ret=%d\n", ret);
|
||||||
|
|
||||||
|
vmw_cmd_flush(dev_priv, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
|
static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
|
||||||
.update_plane = drm_atomic_helper_update_plane,
|
.update_plane = drm_atomic_helper_update_plane,
|
||||||
@@ -577,11 +606,11 @@ int vmw_kms_ldu_close_display(struct vmw_private *dev_priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
|
static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
|
||||||
struct vmw_framebuffer *framebuffer,
|
struct vmw_framebuffer *framebuffer,
|
||||||
unsigned int flags, unsigned int color,
|
unsigned int flags, unsigned int color,
|
||||||
struct drm_clip_rect *clips,
|
struct drm_mode_rect *clips,
|
||||||
unsigned int num_clips, int increment)
|
unsigned int num_clips)
|
||||||
{
|
{
|
||||||
size_t fifo_size;
|
size_t fifo_size;
|
||||||
int i;
|
int i;
|
||||||
@@ -597,7 +626,7 @@ int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
memset(cmd, 0, fifo_size);
|
memset(cmd, 0, fifo_size);
|
||||||
for (i = 0; i < num_clips; i++, clips += increment) {
|
for (i = 0; i < num_clips; i++, clips++) {
|
||||||
cmd[i].header = SVGA_CMD_UPDATE;
|
cmd[i].header = SVGA_CMD_UPDATE;
|
||||||
cmd[i].body.x = clips->x1;
|
cmd[i].body.x = clips->x1;
|
||||||
cmd[i].body.y = clips->y1;
|
cmd[i].body.y = clips->y1;
|
||||||
|
|||||||
Reference in New Issue
Block a user