From: Jakob Bornecrantz <ja...@vmware.com>

Signed-off-by: Jakob Bornecrantz <jakob at vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom at vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |   64 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |    8 ++++
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c |   34 ++++++++++++++++++
 3 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 24efcae..2286d47 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1681,6 +1681,70 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, 
unsigned num,
        return 0;
 }

+int vmw_du_page_flip(struct drm_crtc *crtc,
+                    struct drm_framebuffer *fb,
+                    struct drm_pending_vblank_event *event)
+{
+       struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+       struct drm_framebuffer *old_fb = crtc->fb;
+       struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
+       struct drm_file *file_priv = event->base.file_priv;
+       struct vmw_fence_obj *fence = NULL;
+       struct drm_clip_rect clips;
+       int ret;
+
+       /* require ScreenObject support for page flipping */
+       if (!dev_priv->sou_priv)
+               return -ENOSYS;
+
+       if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
+               return -EINVAL;
+
+       crtc->fb = fb;
+
+       /* do a full screen dirty update */
+       clips.x1 = clips.y1 = 0;
+       clips.x2 = fb->width;
+       clips.y2 = fb->height;
+
+       if (vfb->dmabuf)
+               ret = do_dmabuf_dirty_sou(file_priv, dev_priv, vfb,
+                                         0, 0, &clips, 1, 1, &fence);
+       else
+               ret = do_surface_dirty_sou(dev_priv, file_priv, vfb,
+                                          0, 0, &clips, 1, 1, &fence);
+
+
+       if (ret != 0)
+               goto out_no_fence;
+       if (!fence) {
+               ret = -EINVAL;
+               goto out_no_fence;
+       }
+
+       ret = vmw_event_fence_action_queue(file_priv, fence,
+                                          &event->base,
+                                          &event->event.tv_sec,
+                                          &event->event.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_screen_object_update_implicit_fb(dev_priv, crtc);
+
+       return ret;
+
+out_no_fence:
+       crtc->fb = old_fb;
+       return ret;
+}
+
+
 void vmw_du_crtc_save(struct drm_crtc *crtc)
 {
 }
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index a4f7f03..8184bc5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -121,6 +121,9 @@ struct vmw_display_unit {
  * Shared display unit functions - vmwgfx_kms.c
  */
 void vmw_display_unit_cleanup(struct vmw_display_unit *du);
+int vmw_du_page_flip(struct drm_crtc *crtc,
+                    struct drm_framebuffer *fb,
+                    struct drm_pending_vblank_event *event);
 void vmw_du_crtc_save(struct drm_crtc *crtc);
 void vmw_du_crtc_restore(struct drm_crtc *crtc);
 void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
@@ -154,5 +157,10 @@ int vmw_kms_init_screen_object_display(struct vmw_private 
*dev_priv);
 int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv);
 int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num,
                              struct drm_vmw_rect *rects);
+bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv,
+                                    struct drm_crtc *crtc);
+void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
+                                             struct drm_crtc *crtc);
+

 #endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 4defdcf..97aca0b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -394,6 +394,7 @@ static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = 
{
        .gamma_set = vmw_du_crtc_gamma_set,
        .destroy = vmw_sou_crtc_destroy,
        .set_config = vmw_sou_crtc_set_config,
+       .page_flip = vmw_du_page_flip,
 };

 /*
@@ -535,3 +536,36 @@ int vmw_kms_close_screen_object_display(struct vmw_private 
*dev_priv)

        return 0;
 }
+
+/**
+ * Returns if this unit can be page flipped.
+ * Must be called with the mode_config mutex held.
+ */
+bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv,
+                                    struct drm_crtc *crtc)
+{
+       struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
+
+       if (!sou->base.is_implicit)
+               return true;
+
+       if (dev_priv->sou_priv->num_implicit != 1)
+               return false;
+
+       return true;
+}
+
+/**
+ * Update the implicit fb to the current fb of this crtc.
+ * Must be called with the mode_config mutex held.
+ */
+void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
+                                             struct drm_crtc *crtc)
+{
+       struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
+
+       BUG_ON(!sou->base.is_implicit);
+
+       dev_priv->sou_priv->implicit_fb =
+               vmw_framebuffer_to_vfb(sou->base.crtc.fb);
+}
-- 
1.7.4.4

Reply via email to