diff options
author | Dave Airlie <airlied@redhat.com> | 2013-08-26 10:52:10 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-09-03 15:11:33 +1000 |
commit | 9e33d19b2aa864857266c3159a5f59c0844cc995 (patch) | |
tree | 65ea00645139d610db4ff57da7844a0a3b758641 | |
parent | 7039f6f4a80d50eeb98a9170a76c40054c0c0b10 (diff) |
virgl: tie fb update to a timer for now
this speeds up booting when you want to use fbcon, though I expect
it might be a bit laggy.
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_fb.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/gpu/drm/virgl/virgl_fb.c b/drivers/gpu/drm/virgl/virgl_fb.c index 05c6dbc12dc9..6ded45b68b43 100644 --- a/drivers/gpu/drm/virgl/virgl_fb.c +++ b/drivers/gpu/drm/virgl/virgl_fb.c @@ -36,17 +36,20 @@ #include "virgl_object.h" #include "drm_fb_helper.h" +#define VIRGL_FBCON_POLL_PERIOD (HZ / 60) + struct virgl_fbdev { struct drm_fb_helper helper; struct virgl_framebuffer qfb; struct list_head fbdev_list; struct virgl_device *qdev; + struct delayed_work work; }; #define DL_ALIGN_UP(x, a) ALIGN(x, a) #define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a) -static int virgl_dirty_update(struct virgl_framebuffer *fb, +static int virgl_dirty_update(struct virgl_framebuffer *fb, bool store, int x, int y, int width, int height) { struct drm_device *dev = fb->base.dev; @@ -71,7 +74,7 @@ static int virgl_dirty_update(struct virgl_framebuffer *fb, /* if we are in atomic just store the info can't test inside spin lock */ - if (in_atomic()) + if (in_atomic() || store) store_for_later = true; x2 = x + width - 1; @@ -175,7 +178,7 @@ int virgl_3d_surface_dirty(struct virgl_framebuffer *qfb, struct drm_clip_rect * if (qfb->obj) { struct virgl_bo *qobj = gem_to_virgl_bo(qfb->obj); if (qobj->dumb) - return virgl_dirty_update(qfb, left, top, right - left, bottom - top); + return virgl_dirty_update(qfb, false, left, top, right - left, bottom - top); } virgl_3d_dirty_front(qdev, qfb, left, top, right - left, bottom - top); @@ -207,13 +210,23 @@ int virgl_create_3d_fb_res(struct virgl_device *qdev, int width, int height, uin return 0; } +static void virgl_fb_dirty_work(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct virgl_fbdev *vfbdev = container_of(delayed_work, struct virgl_fbdev, work); + struct virgl_framebuffer *vfb = &vfbdev->qfb; + + virgl_dirty_update(&vfbdev->qfb, false, vfb->x1, vfb->y1, vfb->x2 - vfb->x1, vfb->y2 - vfb->y1); +} + static void virgl_3d_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct virgl_fbdev *qfbdev = info->par; sys_fillrect(info, rect); - virgl_dirty_update(&qfbdev->qfb, rect->dx, rect->dy, rect->width, + virgl_dirty_update(&qfbdev->qfb, true, rect->dx, rect->dy, rect->width, rect->height); + schedule_delayed_work(&qfbdev->work, VIRGL_FBCON_POLL_PERIOD); } static void virgl_3d_copyarea(struct fb_info *info, @@ -221,8 +234,9 @@ static void virgl_3d_copyarea(struct fb_info *info, { struct virgl_fbdev *qfbdev = info->par; sys_copyarea(info, area); - virgl_dirty_update(&qfbdev->qfb, area->dx, area->dy, - area->width, area->height); + virgl_dirty_update(&qfbdev->qfb, true, area->dx, area->dy, + area->width, area->height); + schedule_delayed_work(&qfbdev->work, VIRGL_FBCON_POLL_PERIOD); } static void virgl_3d_imageblit(struct fb_info *info, @@ -230,8 +244,9 @@ static void virgl_3d_imageblit(struct fb_info *info, { struct virgl_fbdev *qfbdev = info->par; sys_imageblit(info, image); - virgl_dirty_update(&qfbdev->qfb, image->dx, image->dy, + virgl_dirty_update(&qfbdev->qfb, true, image->dx, image->dy, image->width, image->height); + schedule_delayed_work(&qfbdev->work, VIRGL_FBCON_POLL_PERIOD); } int virgl_fb_init(struct virgl_device *qdev) @@ -371,7 +386,7 @@ static int virglfb_create(struct virgl_fbdev *qfbdev, drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); - info->flags = FBINFO_DEFAULT; + info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST; info->fbops = &virglfb_ops; /* @@ -480,6 +495,7 @@ int virgl_fbdev_init(struct virgl_device *qdev) qfbdev->qdev = qdev; qdev->mode_info.qfbdev = qfbdev; qfbdev->helper.funcs = &virgl_fb_helper_funcs; + INIT_DELAYED_WORK(&qfbdev->work, virgl_fb_dirty_work); ret = drm_fb_helper_init(qdev->ddev, &qfbdev->helper, 1 /* num_crtc - VIRGL supports just 1 */, |