summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx
diff options
context:
space:
mode:
authorDeepak Rawat2018-01-16 08:31:04 +0100
committerThomas Hellstrom2018-03-22 10:57:04 +0100
commitaa64b3f18aeb2cc4b74e69115df434147f1ed96c (patch)
tree0972977d464761bb1513bd5566a4e6bd7fc7ec93 /drivers/gpu/drm/vmwgfx
parentdrm/vmwgfx: Remove drm_crtc_arm_vblank_event from atomic flush (diff)
downloadkernel-qcow2-linux-aa64b3f18aeb2cc4b74e69115df434147f1ed96c.tar.gz
kernel-qcow2-linux-aa64b3f18aeb2cc4b74e69115df434147f1ed96c.tar.xz
kernel-qcow2-linux-aa64b3f18aeb2cc4b74e69115df434147f1ed96c.zip
drm/vmwgfx: Move screen object page flip to atomic function
The dmabuf_dirty/surface_dirty in case of screen object is moved to plane atomic update, so that page flip in atomic ioctl also works. vmwgfx does not support DRM_MODE_PAGE_FLIP_ASYNC, so this flag is never expected. Signed-off-by: Deepak Rawat <drawat@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c114
1 files changed, 64 insertions, 50 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index a17f6c70fc38..9f6deced4244 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -316,69 +316,21 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
struct drm_modeset_acquire_ctx *ctx)
{
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
- struct drm_framebuffer *old_fb = crtc->primary->fb;
- struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
- struct vmw_fence_obj *fence = NULL;
- struct drm_vmw_rect vclips;
int ret;
if (!vmw_kms_crtc_flippable(dev_priv, crtc))
return -EINVAL;
- flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
- ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx);
+ ret = drm_atomic_helper_page_flip(crtc, new_fb, event, flags, ctx);
if (ret) {
DRM_ERROR("Page flip error %d.\n", ret);
return ret;
}
- /* do a full screen dirty update */
- vclips.x = crtc->x;
- vclips.y = crtc->y;
- vclips.w = crtc->mode.hdisplay;
- vclips.h = crtc->mode.vdisplay;
-
- if (vfb->dmabuf)
- ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb,
- NULL, &vclips, 1, 1,
- true, &fence, crtc);
- else
- ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb,
- NULL, &vclips, NULL,
- 0, 0, 1, 1, &fence, crtc);
-
-
- if (ret != 0)
- goto out_no_fence;
- if (!fence) {
- ret = -EINVAL;
- goto out_no_fence;
- }
-
- if (event) {
- struct drm_file *file_priv = event->base.file_priv;
-
- ret = vmw_event_fence_action_queue(file_priv, fence,
- &event->base,
- &event->event.vbl.tv_sec,
- &event->event.vbl.tv_usec,
- true);
- }
-
- /*
- * No need to hold on to this now. The only cleanup
- * we need to do if we fail is unref the fence.
- */
- vmw_fence_obj_unreference(&fence);
-
if (vmw_crtc_to_du(crtc)->is_implicit)
vmw_kms_update_implicit_fb(dev_priv, crtc);
return ret;
-
-out_no_fence:
- drm_atomic_set_fb_for_plane(crtc->primary->state, old_fb);
- return ret;
}
static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
@@ -530,9 +482,71 @@ vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct drm_crtc *crtc = plane->state->crtc;
+ struct drm_pending_vblank_event *event = NULL;
+ struct vmw_fence_obj *fence = NULL;
+ int ret;
+
+ if (crtc && plane->state->fb) {
+ struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+ struct vmw_framebuffer *vfb =
+ vmw_framebuffer_to_vfb(plane->state->fb);
+ struct drm_vmw_rect vclips;
+
+ vclips.x = crtc->x;
+ vclips.y = crtc->y;
+ vclips.w = crtc->mode.hdisplay;
+ vclips.h = crtc->mode.vdisplay;
+
+ if (vfb->dmabuf)
+ ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb, NULL,
+ &vclips, 1, 1, true,
+ &fence, crtc);
+ else
+ ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb, NULL,
+ &vclips, NULL, 0, 0,
+ 1, 1, &fence, crtc);
+
+ /*
+ * We cannot really fail this function, so if we do, then output
+ * an error and maintain consistent atomic state.
+ */
+ if (ret != 0)
+ DRM_ERROR("Failed to update screen.\n");
- if (crtc)
crtc->primary->fb = plane->state->fb;
+ } else {
+ /*
+ * When disabling a plane, CRTC and FB should always be NULL
+ * together, otherwise it's an error.
+ * Here primary plane is being disable so should really blank
+ * the screen object display unit, if not already done.
+ */
+ return;
+ }
+
+ event = crtc->state->event;
+ /*
+ * In case of failure and other cases, vblank event will be sent in
+ * vmw_du_crtc_atomic_flush.
+ */
+ if (event && fence) {
+ struct drm_file *file_priv = event->base.file_priv;
+
+ ret = vmw_event_fence_action_queue(file_priv,
+ fence,
+ &event->base,
+ &event->event.vbl.tv_sec,
+ &event->event.vbl.tv_usec,
+ true);
+
+ if (unlikely(ret != 0))
+ DRM_ERROR("Failed to queue event on fence.\n");
+ else
+ crtc->state->event = NULL;
+ }
+
+ if (fence)
+ vmw_fence_obj_unreference(&fence);
}