aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@vmware.com>2012-02-09 10:56:45 -0500
committerDave Airlie <airlied@redhat.com>2012-02-13 07:01:35 -0500
commitb5ec427e8d8c66ea1bb9a3bf09663c1361ecf0b6 (patch)
treee6b3c60a0b77cff4b1eb62c3010c83cefd17929e /drivers/gpu
parentbd49ae46f8a24c088dbca12064a846399e2da631 (diff)
vmwgfx: Add page flip support
Signed-off-by: Jakob Bornecrantz <jakob@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c64
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c34
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 24efcae3e2f5..2286d47e5022 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,
1681 return 0; 1681 return 0;
1682} 1682}
1683 1683
1684int vmw_du_page_flip(struct drm_crtc *crtc,
1685 struct drm_framebuffer *fb,
1686 struct drm_pending_vblank_event *event)
1687{
1688 struct vmw_private *dev_priv = vmw_priv(crtc->dev);
1689 struct drm_framebuffer *old_fb = crtc->fb;
1690 struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
1691 struct drm_file *file_priv = event->base.file_priv;
1692 struct vmw_fence_obj *fence = NULL;
1693 struct drm_clip_rect clips;
1694 int ret;
1695
1696 /* require ScreenObject support for page flipping */
1697 if (!dev_priv->sou_priv)
1698 return -ENOSYS;
1699
1700 if (!vmw_kms_screen_object_flippable(dev_priv, crtc))
1701 return -EINVAL;
1702
1703 crtc->fb = fb;
1704
1705 /* do a full screen dirty update */
1706 clips.x1 = clips.y1 = 0;
1707 clips.x2 = fb->width;
1708 clips.y2 = fb->height;
1709
1710 if (vfb->dmabuf)
1711 ret = do_dmabuf_dirty_sou(file_priv, dev_priv, vfb,
1712 0, 0, &clips, 1, 1, &fence);
1713 else
1714 ret = do_surface_dirty_sou(dev_priv, file_priv, vfb,
1715 0, 0, &clips, 1, 1, &fence);
1716
1717
1718 if (ret != 0)
1719 goto out_no_fence;
1720 if (!fence) {
1721 ret = -EINVAL;
1722 goto out_no_fence;
1723 }
1724
1725 ret = vmw_event_fence_action_queue(file_priv, fence,
1726 &event->base,
1727 &event->event.tv_sec,
1728 &event->event.tv_usec,
1729 true);
1730
1731 /*
1732 * No need to hold on to this now. The only cleanup
1733 * we need to do if we fail is unref the fence.
1734 */
1735 vmw_fence_obj_unreference(&fence);
1736
1737 if (vmw_crtc_to_du(crtc)->is_implicit)
1738 vmw_kms_screen_object_update_implicit_fb(dev_priv, crtc);
1739
1740 return ret;
1741
1742out_no_fence:
1743 crtc->fb = old_fb;
1744 return ret;
1745}
1746
1747
1684void vmw_du_crtc_save(struct drm_crtc *crtc) 1748void vmw_du_crtc_save(struct drm_crtc *crtc)
1685{ 1749{
1686} 1750}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index a4f7f034996a..8184bc5b1730 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 {
121 * Shared display unit functions - vmwgfx_kms.c 121 * Shared display unit functions - vmwgfx_kms.c
122 */ 122 */
123void vmw_display_unit_cleanup(struct vmw_display_unit *du); 123void vmw_display_unit_cleanup(struct vmw_display_unit *du);
124int vmw_du_page_flip(struct drm_crtc *crtc,
125 struct drm_framebuffer *fb,
126 struct drm_pending_vblank_event *event);
124void vmw_du_crtc_save(struct drm_crtc *crtc); 127void vmw_du_crtc_save(struct drm_crtc *crtc);
125void vmw_du_crtc_restore(struct drm_crtc *crtc); 128void vmw_du_crtc_restore(struct drm_crtc *crtc);
126void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, 129void 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);
154int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv); 157int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv);
155int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num, 158int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num,
156 struct drm_vmw_rect *rects); 159 struct drm_vmw_rect *rects);
160bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv,
161 struct drm_crtc *crtc);
162void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
163 struct drm_crtc *crtc);
164
157 165
158#endif 166#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 4defdcf1c72e..97aca0bf94d0 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 = {
394 .gamma_set = vmw_du_crtc_gamma_set, 394 .gamma_set = vmw_du_crtc_gamma_set,
395 .destroy = vmw_sou_crtc_destroy, 395 .destroy = vmw_sou_crtc_destroy,
396 .set_config = vmw_sou_crtc_set_config, 396 .set_config = vmw_sou_crtc_set_config,
397 .page_flip = vmw_du_page_flip,
397}; 398};
398 399
399/* 400/*
@@ -535,3 +536,36 @@ int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv)
535 536
536 return 0; 537 return 0;
537} 538}
539
540/**
541 * Returns if this unit can be page flipped.
542 * Must be called with the mode_config mutex held.
543 */
544bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv,
545 struct drm_crtc *crtc)
546{
547 struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
548
549 if (!sou->base.is_implicit)
550 return true;
551
552 if (dev_priv->sou_priv->num_implicit != 1)
553 return false;
554
555 return true;
556}
557
558/**
559 * Update the implicit fb to the current fb of this crtc.
560 * Must be called with the mode_config mutex held.
561 */
562void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv,
563 struct drm_crtc *crtc)
564{
565 struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
566
567 BUG_ON(!sou->base.is_implicit);
568
569 dev_priv->sou_priv->implicit_fb =
570 vmw_framebuffer_to_vfb(sou->base.crtc.fb);
571}