diff options
author | Andreas Pokorny <andreas.pokorny@canonical.com> | 2014-08-08 10:40:55 +0200 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-09-03 15:35:27 +1000 |
commit | 058e9f5c8236ad740ab984588b507758e5feee6d (patch) | |
tree | 21a2b80796bbc325069625cdb121dc92122165a1 | |
parent | 6ba59f3b5c977af2df3f9446f030f71e29d77dc1 (diff) |
drm/qxl: simple crtc page flipping emulated using buffer copy
Signed-off-by: Andreas Pokorny <andreas.pokorny@canonical.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_display.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_kms.c | 16 |
3 files changed, 79 insertions, 4 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index b8ced08b6291..af9e78546688 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -187,6 +187,54 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc) kfree(qxl_crtc); } +static int qxl_crtc_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags) +{ + struct drm_device *dev = crtc->dev; + struct qxl_device *qdev = dev->dev_private; + struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); + struct qxl_framebuffer *qfb_src = to_qxl_framebuffer(fb); + struct qxl_framebuffer *qfb_old = to_qxl_framebuffer(crtc->primary->fb); + struct qxl_bo *bo_old = gem_to_qxl_bo(qfb_old->obj); + struct qxl_bo *bo = gem_to_qxl_bo(qfb_src->obj); + unsigned long flags; + struct drm_clip_rect norect = { + .x1 = 0, + .y1 = 0, + .x2 = fb->width, + .y2 = fb->height + }; + int inc = 1; + int one_clip_rect = 1; + int ret = 0; + + crtc->primary->fb = fb; + bo_old->is_primary = false; + bo->is_primary = true; + + ret = qxl_bo_reserve(bo, false); + if (ret) + return ret; + + qxl_draw_dirty_fb(qdev, qfb_src, bo, 0, 0, + &norect, one_clip_rect, inc); + + drm_vblank_get(dev, qcrtc->index); + + if (event) { + spin_lock_irqsave(&dev->event_lock, flags); + drm_send_vblank_event(dev, qcrtc->index, event); + spin_unlock_irqrestore(&dev->event_lock, flags); + } + drm_vblank_put(dev, qcrtc->index); + + qxl_bo_unreserve(bo); + + return 0; +} + static int qxl_hide_cursor(struct qxl_device *qdev) { @@ -374,6 +422,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { .cursor_move = qxl_crtc_cursor_move, .set_config = drm_crtc_helper_set_config, .destroy = qxl_crtc_destroy, + .page_flip = qxl_crtc_page_flip, }; static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index a3fd92029a14..b8a3eae4b1b1 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -84,6 +84,7 @@ static const struct file_operations qxl_fops = { .release = drm_release, .unlocked_ioctl = drm_ioctl, .poll = drm_poll, + .read = drm_read, .mmap = qxl_mmap, }; @@ -195,6 +196,20 @@ static int qxl_pm_restore(struct device *dev) return qxl_drm_resume(drm_dev, false); } +static u32 qxl_noop_get_vblank_counter(struct drm_device *dev, int crtc) +{ + return dev->vblank[crtc].count.counter; +} + +static int qxl_noop_enable_vblank(struct drm_device *dev, int crtc) +{ + return 0; +} + +static void qxl_noop_disable_vblank(struct drm_device *dev, int crtc) +{ +} + static const struct dev_pm_ops qxl_pm_ops = { .suspend = qxl_pm_suspend, .resume = qxl_pm_resume, @@ -216,6 +231,9 @@ static struct drm_driver qxl_driver = { DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .load = qxl_driver_load, .unload = qxl_driver_unload, + .get_vblank_counter = qxl_noop_get_vblank_counter, + .enable_vblank = qxl_noop_enable_vblank, + .disable_vblank = qxl_noop_disable_vblank, .dumb_create = qxl_mode_dumb_create, .dumb_map_offset = qxl_mode_dumb_mmap, diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index 7234561e09d9..b2977a181935 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -298,6 +298,9 @@ int qxl_driver_unload(struct drm_device *dev) if (qdev == NULL) return 0; + + drm_vblank_cleanup(dev); + qxl_modeset_fini(qdev); qxl_device_fini(qdev); @@ -325,15 +328,20 @@ int qxl_driver_load(struct drm_device *dev, unsigned long flags) if (r) goto out; + r = drm_vblank_init(dev, 1); + if (r) + goto unload; + r = qxl_modeset_init(qdev); - if (r) { - qxl_driver_unload(dev); - goto out; - } + if (r) + goto unload; drm_kms_helper_poll_init(qdev->ddev); return 0; +unload: + qxl_driver_unload(dev); + out: kfree(qdev); return r; |