diff options
author | Jakob Bornecrantz <jakob@vmware.com> | 2012-02-09 10:56:45 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-02-13 07:01:35 -0500 |
commit | b5ec427e8d8c66ea1bb9a3bf09663c1361ecf0b6 (patch) | |
tree | e6b3c60a0b77cff4b1eb62c3010c83cefd17929e /drivers | |
parent | bd49ae46f8a24c088dbca12064a846399e2da631 (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')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 64 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 8 | ||||
-rw-r--r-- | 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 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 | ||
1684 | int 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 | |||
1742 | out_no_fence: | ||
1743 | crtc->fb = old_fb; | ||
1744 | return ret; | ||
1745 | } | ||
1746 | |||
1747 | |||
1684 | void vmw_du_crtc_save(struct drm_crtc *crtc) | 1748 | void 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 | */ |
123 | void vmw_display_unit_cleanup(struct vmw_display_unit *du); | 123 | void vmw_display_unit_cleanup(struct vmw_display_unit *du); |
124 | int vmw_du_page_flip(struct drm_crtc *crtc, | ||
125 | struct drm_framebuffer *fb, | ||
126 | struct drm_pending_vblank_event *event); | ||
124 | void vmw_du_crtc_save(struct drm_crtc *crtc); | 127 | void vmw_du_crtc_save(struct drm_crtc *crtc); |
125 | void vmw_du_crtc_restore(struct drm_crtc *crtc); | 128 | void vmw_du_crtc_restore(struct drm_crtc *crtc); |
126 | void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, | 129 | 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); | |||
154 | int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv); | 157 | int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv); |
155 | int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num, | 158 | int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num, |
156 | struct drm_vmw_rect *rects); | 159 | struct drm_vmw_rect *rects); |
160 | bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv, | ||
161 | struct drm_crtc *crtc); | ||
162 | void 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 | */ | ||
544 | bool 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 | */ | ||
562 | void 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 | } | ||