From: Daniel Vetter <daniel@ffwll.ch> To: "Noralf Trønnes" <noralf@tronnes.org> Cc: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org, daniel@ffwll.ch, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ti.com, linux-kernel@vger.kernel.org Subject: Re: [PATCH v2 7/8] drm/qxl: Use drm_fb_helper deferred_io support Date: Mon, 25 Apr 2016 11:16:15 +0200 [thread overview] Message-ID: <20160425091615.GT2510@phenom.ffwll.local> (raw) In-Reply-To: <1461530942-22485-8-git-send-email-noralf@tronnes.org> On Sun, Apr 24, 2016 at 10:49:01PM +0200, Noralf Trønnes wrote: > Use the fbdev deferred io support in drm_fb_helper which mirrors the > one qxl has had. > This patch has only been compile tested. > > Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Yay for deleting code. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > --- > > Changes since v1: > - Add FIXME about special dirty() callback for fbdev > - Remove note in commit message about deferred worker, drm_fb_helper > is similar to qxl now. > > drivers/gpu/drm/qxl/qxl_display.c | 9 +- > drivers/gpu/drm/qxl/qxl_drv.h | 7 +- > drivers/gpu/drm/qxl/qxl_fb.c | 224 ++++++++++---------------------------- > drivers/gpu/drm/qxl/qxl_kms.c | 4 - > 4 files changed, 66 insertions(+), 178 deletions(-) > > diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c > index 030409a..9a03524 100644 > --- a/drivers/gpu/drm/qxl/qxl_display.c > +++ b/drivers/gpu/drm/qxl/qxl_display.c > @@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { > .page_flip = qxl_crtc_page_flip, > }; > > -static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) > +void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) > { > struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); > > @@ -527,12 +527,13 @@ int > qxl_framebuffer_init(struct drm_device *dev, > struct qxl_framebuffer *qfb, > const struct drm_mode_fb_cmd2 *mode_cmd, > - struct drm_gem_object *obj) > + struct drm_gem_object *obj, > + const struct drm_framebuffer_funcs *funcs) > { > int ret; > > qfb->obj = obj; > - ret = drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs); > + ret = drm_framebuffer_init(dev, &qfb->base, funcs); > if (ret) { > qfb->obj = NULL; > return ret; > @@ -999,7 +1000,7 @@ qxl_user_framebuffer_create(struct drm_device *dev, > if (qxl_fb == NULL) > return NULL; > > - ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj); > + ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs); > if (ret) { > kfree(qxl_fb); > drm_gem_object_unreference_unlocked(obj); > diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h > index 3f3897e..3ad6604 100644 > --- a/drivers/gpu/drm/qxl/qxl_drv.h > +++ b/drivers/gpu/drm/qxl/qxl_drv.h > @@ -324,8 +324,6 @@ struct qxl_device { > struct workqueue_struct *gc_queue; > struct work_struct gc_work; > > - struct work_struct fb_work; > - > struct drm_property *hotplug_mode_update_property; > int monitors_config_width; > int monitors_config_height; > @@ -389,11 +387,13 @@ int qxl_get_handle_for_primary_fb(struct qxl_device *qdev, > void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state); > > /* qxl_display.c */ > +void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb); > int > qxl_framebuffer_init(struct drm_device *dev, > struct qxl_framebuffer *rfb, > const struct drm_mode_fb_cmd2 *mode_cmd, > - struct drm_gem_object *obj); > + struct drm_gem_object *obj, > + const struct drm_framebuffer_funcs *funcs); > void qxl_display_read_client_monitors_config(struct qxl_device *qdev); > void qxl_send_monitors_config(struct qxl_device *qdev); > int qxl_create_monitors_object(struct qxl_device *qdev); > @@ -553,7 +553,6 @@ int qxl_irq_init(struct qxl_device *qdev); > irqreturn_t qxl_irq_handler(int irq, void *arg); > > /* qxl_fb.c */ > -int qxl_fb_init(struct qxl_device *qdev); > bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj); > > int qxl_debugfs_add_files(struct qxl_device *qdev, > diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c > index 06f032d..e316973 100644 > --- a/drivers/gpu/drm/qxl/qxl_fb.c > +++ b/drivers/gpu/drm/qxl/qxl_fb.c > @@ -30,6 +30,7 @@ > #include "drm/drm.h" > #include "drm/drm_crtc.h" > #include "drm/drm_crtc_helper.h" > +#include "drm/drm_rect.h" > #include "qxl_drv.h" > > #include "qxl_object.h" > @@ -46,15 +47,6 @@ struct qxl_fbdev { > struct list_head delayed_ops; > void *shadow; > int size; > - > - /* dirty memory logging */ > - struct { > - spinlock_t lock; > - unsigned x1; > - unsigned y1; > - unsigned x2; > - unsigned y2; > - } dirty; > }; > > static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, > @@ -82,169 +74,18 @@ static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, > } > } > > -static void qxl_fb_dirty_flush(struct fb_info *info) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - struct qxl_device *qdev = qfbdev->qdev; > - struct qxl_fb_image qxl_fb_image; > - struct fb_image *image = &qxl_fb_image.fb_image; > - unsigned long flags; > - u32 x1, x2, y1, y2; > - > - /* TODO: hard coding 32 bpp */ > - int stride = qfbdev->qfb.base.pitches[0]; > - > - spin_lock_irqsave(&qfbdev->dirty.lock, flags); > - > - x1 = qfbdev->dirty.x1; > - x2 = qfbdev->dirty.x2; > - y1 = qfbdev->dirty.y1; > - y2 = qfbdev->dirty.y2; > - qfbdev->dirty.x1 = 0; > - qfbdev->dirty.x2 = 0; > - qfbdev->dirty.y1 = 0; > - qfbdev->dirty.y2 = 0; > - > - spin_unlock_irqrestore(&qfbdev->dirty.lock, flags); > - > - /* > - * we are using a shadow draw buffer, at qdev->surface0_shadow > - */ > - qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", x1, x2, y1, y2); > - image->dx = x1; > - image->dy = y1; > - image->width = x2 - x1 + 1; > - image->height = y2 - y1 + 1; > - image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized > - warnings */ > - image->bg_color = 0; > - image->depth = 32; /* TODO: take from somewhere? */ > - image->cmap.start = 0; > - image->cmap.len = 0; > - image->cmap.red = NULL; > - image->cmap.green = NULL; > - image->cmap.blue = NULL; > - image->cmap.transp = NULL; > - image->data = qfbdev->shadow + (x1 * 4) + (stride * y1); > - > - qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > - qxl_draw_opaque_fb(&qxl_fb_image, stride); > -} > - > -static void qxl_dirty_update(struct qxl_fbdev *qfbdev, > - int x, int y, int width, int height) > -{ > - struct qxl_device *qdev = qfbdev->qdev; > - unsigned long flags; > - int x2, y2; > - > - x2 = x + width - 1; > - y2 = y + height - 1; > - > - spin_lock_irqsave(&qfbdev->dirty.lock, flags); > - > - if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) && > - (qfbdev->dirty.x2 - qfbdev->dirty.x1)) { > - if (qfbdev->dirty.y1 < y) > - y = qfbdev->dirty.y1; > - if (qfbdev->dirty.y2 > y2) > - y2 = qfbdev->dirty.y2; > - if (qfbdev->dirty.x1 < x) > - x = qfbdev->dirty.x1; > - if (qfbdev->dirty.x2 > x2) > - x2 = qfbdev->dirty.x2; > - } > - > - qfbdev->dirty.x1 = x; > - qfbdev->dirty.x2 = x2; > - qfbdev->dirty.y1 = y; > - qfbdev->dirty.y2 = y2; > - > - spin_unlock_irqrestore(&qfbdev->dirty.lock, flags); > - > - schedule_work(&qdev->fb_work); > -} > - > -static void qxl_deferred_io(struct fb_info *info, > - struct list_head *pagelist) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - unsigned long start, end, min, max; > - struct page *page; > - int y1, y2; > - > - min = ULONG_MAX; > - max = 0; > - list_for_each_entry(page, pagelist, lru) { > - start = page->index << PAGE_SHIFT; > - end = start + PAGE_SIZE - 1; > - min = min(min, start); > - max = max(max, end); > - } > - > - if (min < max) { > - y1 = min / info->fix.line_length; > - y2 = (max / info->fix.line_length) + 1; > - qxl_dirty_update(qfbdev, 0, y1, info->var.xres, y2 - y1); > - } > -}; > - > static struct fb_deferred_io qxl_defio = { > .delay = QXL_DIRTY_DELAY, > - .deferred_io = qxl_deferred_io, > + .deferred_io = drm_fb_helper_deferred_io, > }; > > -static void qxl_fb_fillrect(struct fb_info *info, > - const struct fb_fillrect *rect) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - > - sys_fillrect(info, rect); > - qxl_dirty_update(qfbdev, rect->dx, rect->dy, rect->width, > - rect->height); > -} > - > -static void qxl_fb_copyarea(struct fb_info *info, > - const struct fb_copyarea *area) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - > - sys_copyarea(info, area); > - qxl_dirty_update(qfbdev, area->dx, area->dy, area->width, > - area->height); > -} > - > -static void qxl_fb_imageblit(struct fb_info *info, > - const struct fb_image *image) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - > - sys_imageblit(info, image); > - qxl_dirty_update(qfbdev, image->dx, image->dy, image->width, > - image->height); > -} > - > -static void qxl_fb_work(struct work_struct *work) > -{ > - struct qxl_device *qdev = container_of(work, struct qxl_device, fb_work); > - struct qxl_fbdev *qfbdev = qdev->mode_info.qfbdev; > - > - qxl_fb_dirty_flush(qfbdev->helper.fbdev); > -} > - > -int qxl_fb_init(struct qxl_device *qdev) > -{ > - INIT_WORK(&qdev->fb_work, qxl_fb_work); > - return 0; > -} > - > static struct fb_ops qxlfb_ops = { > .owner = THIS_MODULE, > .fb_check_var = drm_fb_helper_check_var, > .fb_set_par = drm_fb_helper_set_par, /* TODO: copy vmwgfx */ > - .fb_fillrect = qxl_fb_fillrect, > - .fb_copyarea = qxl_fb_copyarea, > - .fb_imageblit = qxl_fb_imageblit, > + .fb_fillrect = drm_fb_helper_sys_fillrect, > + .fb_copyarea = drm_fb_helper_sys_copyarea, > + .fb_imageblit = drm_fb_helper_sys_imageblit, > .fb_pan_display = drm_fb_helper_pan_display, > .fb_blank = drm_fb_helper_blank, > .fb_setcmap = drm_fb_helper_setcmap, > @@ -338,6 +179,57 @@ out_unref: > return ret; > } > > +/* > + * FIXME > + * It should not be necessary to have a special dirty() callback for fbdev. > + */ > +static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb, > + struct drm_file *file_priv, > + unsigned flags, unsigned color, > + struct drm_clip_rect *clips, > + unsigned num_clips) > +{ > + struct qxl_device *qdev = fb->dev->dev_private; > + struct fb_info *info = qdev->fbdev_info; > + struct qxl_fbdev *qfbdev = info->par; > + struct qxl_fb_image qxl_fb_image; > + struct fb_image *image = &qxl_fb_image.fb_image; > + > + /* TODO: hard coding 32 bpp */ > + int stride = qfbdev->qfb.base.pitches[0]; > + > + /* > + * we are using a shadow draw buffer, at qdev->surface0_shadow > + */ > + qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", clips->x1, clips->x2, > + clips->y1, clips->y2); > + image->dx = clips->x1; > + image->dy = clips->y1; > + image->width = drm_clip_rect_width(clips); > + image->height = drm_clip_rect_height(clips); > + image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized > + warnings */ > + image->bg_color = 0; > + image->depth = 32; /* TODO: take from somewhere? */ > + image->cmap.start = 0; > + image->cmap.len = 0; > + image->cmap.red = NULL; > + image->cmap.green = NULL; > + image->cmap.blue = NULL; > + image->cmap.transp = NULL; > + image->data = qfbdev->shadow + (clips->x1 * 4) + (stride * clips->y1); > + > + qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > + qxl_draw_opaque_fb(&qxl_fb_image, stride); > + > + return 0; > +} > + > +static const struct drm_framebuffer_funcs qxlfb_fb_funcs = { > + .destroy = qxl_user_framebuffer_destroy, > + .dirty = qxlfb_framebuffer_dirty, > +}; > + > static int qxlfb_create(struct qxl_fbdev *qfbdev, > struct drm_fb_helper_surface_size *sizes) > { > @@ -383,7 +275,8 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, > > info->par = qfbdev; > > - qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj); > + qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj, > + &qxlfb_fb_funcs); > > fb = &qfbdev->qfb.base; > > @@ -504,7 +397,6 @@ int qxl_fbdev_init(struct qxl_device *qdev) > qfbdev->qdev = qdev; > qdev->mode_info.qfbdev = qfbdev; > spin_lock_init(&qfbdev->delayed_ops_lock); > - spin_lock_init(&qfbdev->dirty.lock); > INIT_LIST_HEAD(&qfbdev->delayed_ops); > > drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper, > diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c > index b2977a1..2319800 100644 > --- a/drivers/gpu/drm/qxl/qxl_kms.c > +++ b/drivers/gpu/drm/qxl/qxl_kms.c > @@ -261,10 +261,6 @@ static int qxl_device_init(struct qxl_device *qdev, > qdev->gc_queue = create_singlethread_workqueue("qxl_gc"); > INIT_WORK(&qdev->gc_work, qxl_gc_work); > > - r = qxl_fb_init(qdev); > - if (r) > - return r; > - > return 0; > } > > -- > 2.2.2 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
WARNING: multiple messages have this Message-ID (diff)
From: Daniel Vetter <daniel@ffwll.ch> To: "Noralf Trønnes" <noralf@tronnes.org> Cc: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org, daniel@ffwll.ch, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ti.com, linux-kernel@vger.kernel.org Subject: Re: [PATCH v2 7/8] drm/qxl: Use drm_fb_helper deferred_io support Date: Mon, 25 Apr 2016 09:16:15 +0000 [thread overview] Message-ID: <20160425091615.GT2510@phenom.ffwll.local> (raw) In-Reply-To: <1461530942-22485-8-git-send-email-noralf@tronnes.org> On Sun, Apr 24, 2016 at 10:49:01PM +0200, Noralf Trønnes wrote: > Use the fbdev deferred io support in drm_fb_helper which mirrors the > one qxl has had. > This patch has only been compile tested. > > Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Yay for deleting code. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > --- > > Changes since v1: > - Add FIXME about special dirty() callback for fbdev > - Remove note in commit message about deferred worker, drm_fb_helper > is similar to qxl now. > > drivers/gpu/drm/qxl/qxl_display.c | 9 +- > drivers/gpu/drm/qxl/qxl_drv.h | 7 +- > drivers/gpu/drm/qxl/qxl_fb.c | 224 ++++++++++---------------------------- > drivers/gpu/drm/qxl/qxl_kms.c | 4 - > 4 files changed, 66 insertions(+), 178 deletions(-) > > diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c > index 030409a..9a03524 100644 > --- a/drivers/gpu/drm/qxl/qxl_display.c > +++ b/drivers/gpu/drm/qxl/qxl_display.c > @@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { > .page_flip = qxl_crtc_page_flip, > }; > > -static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) > +void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) > { > struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); > > @@ -527,12 +527,13 @@ int > qxl_framebuffer_init(struct drm_device *dev, > struct qxl_framebuffer *qfb, > const struct drm_mode_fb_cmd2 *mode_cmd, > - struct drm_gem_object *obj) > + struct drm_gem_object *obj, > + const struct drm_framebuffer_funcs *funcs) > { > int ret; > > qfb->obj = obj; > - ret = drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs); > + ret = drm_framebuffer_init(dev, &qfb->base, funcs); > if (ret) { > qfb->obj = NULL; > return ret; > @@ -999,7 +1000,7 @@ qxl_user_framebuffer_create(struct drm_device *dev, > if (qxl_fb = NULL) > return NULL; > > - ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj); > + ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs); > if (ret) { > kfree(qxl_fb); > drm_gem_object_unreference_unlocked(obj); > diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h > index 3f3897e..3ad6604 100644 > --- a/drivers/gpu/drm/qxl/qxl_drv.h > +++ b/drivers/gpu/drm/qxl/qxl_drv.h > @@ -324,8 +324,6 @@ struct qxl_device { > struct workqueue_struct *gc_queue; > struct work_struct gc_work; > > - struct work_struct fb_work; > - > struct drm_property *hotplug_mode_update_property; > int monitors_config_width; > int monitors_config_height; > @@ -389,11 +387,13 @@ int qxl_get_handle_for_primary_fb(struct qxl_device *qdev, > void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state); > > /* qxl_display.c */ > +void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb); > int > qxl_framebuffer_init(struct drm_device *dev, > struct qxl_framebuffer *rfb, > const struct drm_mode_fb_cmd2 *mode_cmd, > - struct drm_gem_object *obj); > + struct drm_gem_object *obj, > + const struct drm_framebuffer_funcs *funcs); > void qxl_display_read_client_monitors_config(struct qxl_device *qdev); > void qxl_send_monitors_config(struct qxl_device *qdev); > int qxl_create_monitors_object(struct qxl_device *qdev); > @@ -553,7 +553,6 @@ int qxl_irq_init(struct qxl_device *qdev); > irqreturn_t qxl_irq_handler(int irq, void *arg); > > /* qxl_fb.c */ > -int qxl_fb_init(struct qxl_device *qdev); > bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj); > > int qxl_debugfs_add_files(struct qxl_device *qdev, > diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c > index 06f032d..e316973 100644 > --- a/drivers/gpu/drm/qxl/qxl_fb.c > +++ b/drivers/gpu/drm/qxl/qxl_fb.c > @@ -30,6 +30,7 @@ > #include "drm/drm.h" > #include "drm/drm_crtc.h" > #include "drm/drm_crtc_helper.h" > +#include "drm/drm_rect.h" > #include "qxl_drv.h" > > #include "qxl_object.h" > @@ -46,15 +47,6 @@ struct qxl_fbdev { > struct list_head delayed_ops; > void *shadow; > int size; > - > - /* dirty memory logging */ > - struct { > - spinlock_t lock; > - unsigned x1; > - unsigned y1; > - unsigned x2; > - unsigned y2; > - } dirty; > }; > > static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, > @@ -82,169 +74,18 @@ static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, > } > } > > -static void qxl_fb_dirty_flush(struct fb_info *info) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - struct qxl_device *qdev = qfbdev->qdev; > - struct qxl_fb_image qxl_fb_image; > - struct fb_image *image = &qxl_fb_image.fb_image; > - unsigned long flags; > - u32 x1, x2, y1, y2; > - > - /* TODO: hard coding 32 bpp */ > - int stride = qfbdev->qfb.base.pitches[0]; > - > - spin_lock_irqsave(&qfbdev->dirty.lock, flags); > - > - x1 = qfbdev->dirty.x1; > - x2 = qfbdev->dirty.x2; > - y1 = qfbdev->dirty.y1; > - y2 = qfbdev->dirty.y2; > - qfbdev->dirty.x1 = 0; > - qfbdev->dirty.x2 = 0; > - qfbdev->dirty.y1 = 0; > - qfbdev->dirty.y2 = 0; > - > - spin_unlock_irqrestore(&qfbdev->dirty.lock, flags); > - > - /* > - * we are using a shadow draw buffer, at qdev->surface0_shadow > - */ > - qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", x1, x2, y1, y2); > - image->dx = x1; > - image->dy = y1; > - image->width = x2 - x1 + 1; > - image->height = y2 - y1 + 1; > - image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized > - warnings */ > - image->bg_color = 0; > - image->depth = 32; /* TODO: take from somewhere? */ > - image->cmap.start = 0; > - image->cmap.len = 0; > - image->cmap.red = NULL; > - image->cmap.green = NULL; > - image->cmap.blue = NULL; > - image->cmap.transp = NULL; > - image->data = qfbdev->shadow + (x1 * 4) + (stride * y1); > - > - qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > - qxl_draw_opaque_fb(&qxl_fb_image, stride); > -} > - > -static void qxl_dirty_update(struct qxl_fbdev *qfbdev, > - int x, int y, int width, int height) > -{ > - struct qxl_device *qdev = qfbdev->qdev; > - unsigned long flags; > - int x2, y2; > - > - x2 = x + width - 1; > - y2 = y + height - 1; > - > - spin_lock_irqsave(&qfbdev->dirty.lock, flags); > - > - if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) && > - (qfbdev->dirty.x2 - qfbdev->dirty.x1)) { > - if (qfbdev->dirty.y1 < y) > - y = qfbdev->dirty.y1; > - if (qfbdev->dirty.y2 > y2) > - y2 = qfbdev->dirty.y2; > - if (qfbdev->dirty.x1 < x) > - x = qfbdev->dirty.x1; > - if (qfbdev->dirty.x2 > x2) > - x2 = qfbdev->dirty.x2; > - } > - > - qfbdev->dirty.x1 = x; > - qfbdev->dirty.x2 = x2; > - qfbdev->dirty.y1 = y; > - qfbdev->dirty.y2 = y2; > - > - spin_unlock_irqrestore(&qfbdev->dirty.lock, flags); > - > - schedule_work(&qdev->fb_work); > -} > - > -static void qxl_deferred_io(struct fb_info *info, > - struct list_head *pagelist) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - unsigned long start, end, min, max; > - struct page *page; > - int y1, y2; > - > - min = ULONG_MAX; > - max = 0; > - list_for_each_entry(page, pagelist, lru) { > - start = page->index << PAGE_SHIFT; > - end = start + PAGE_SIZE - 1; > - min = min(min, start); > - max = max(max, end); > - } > - > - if (min < max) { > - y1 = min / info->fix.line_length; > - y2 = (max / info->fix.line_length) + 1; > - qxl_dirty_update(qfbdev, 0, y1, info->var.xres, y2 - y1); > - } > -}; > - > static struct fb_deferred_io qxl_defio = { > .delay = QXL_DIRTY_DELAY, > - .deferred_io = qxl_deferred_io, > + .deferred_io = drm_fb_helper_deferred_io, > }; > > -static void qxl_fb_fillrect(struct fb_info *info, > - const struct fb_fillrect *rect) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - > - sys_fillrect(info, rect); > - qxl_dirty_update(qfbdev, rect->dx, rect->dy, rect->width, > - rect->height); > -} > - > -static void qxl_fb_copyarea(struct fb_info *info, > - const struct fb_copyarea *area) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - > - sys_copyarea(info, area); > - qxl_dirty_update(qfbdev, area->dx, area->dy, area->width, > - area->height); > -} > - > -static void qxl_fb_imageblit(struct fb_info *info, > - const struct fb_image *image) > -{ > - struct qxl_fbdev *qfbdev = info->par; > - > - sys_imageblit(info, image); > - qxl_dirty_update(qfbdev, image->dx, image->dy, image->width, > - image->height); > -} > - > -static void qxl_fb_work(struct work_struct *work) > -{ > - struct qxl_device *qdev = container_of(work, struct qxl_device, fb_work); > - struct qxl_fbdev *qfbdev = qdev->mode_info.qfbdev; > - > - qxl_fb_dirty_flush(qfbdev->helper.fbdev); > -} > - > -int qxl_fb_init(struct qxl_device *qdev) > -{ > - INIT_WORK(&qdev->fb_work, qxl_fb_work); > - return 0; > -} > - > static struct fb_ops qxlfb_ops = { > .owner = THIS_MODULE, > .fb_check_var = drm_fb_helper_check_var, > .fb_set_par = drm_fb_helper_set_par, /* TODO: copy vmwgfx */ > - .fb_fillrect = qxl_fb_fillrect, > - .fb_copyarea = qxl_fb_copyarea, > - .fb_imageblit = qxl_fb_imageblit, > + .fb_fillrect = drm_fb_helper_sys_fillrect, > + .fb_copyarea = drm_fb_helper_sys_copyarea, > + .fb_imageblit = drm_fb_helper_sys_imageblit, > .fb_pan_display = drm_fb_helper_pan_display, > .fb_blank = drm_fb_helper_blank, > .fb_setcmap = drm_fb_helper_setcmap, > @@ -338,6 +179,57 @@ out_unref: > return ret; > } > > +/* > + * FIXME > + * It should not be necessary to have a special dirty() callback for fbdev. > + */ > +static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb, > + struct drm_file *file_priv, > + unsigned flags, unsigned color, > + struct drm_clip_rect *clips, > + unsigned num_clips) > +{ > + struct qxl_device *qdev = fb->dev->dev_private; > + struct fb_info *info = qdev->fbdev_info; > + struct qxl_fbdev *qfbdev = info->par; > + struct qxl_fb_image qxl_fb_image; > + struct fb_image *image = &qxl_fb_image.fb_image; > + > + /* TODO: hard coding 32 bpp */ > + int stride = qfbdev->qfb.base.pitches[0]; > + > + /* > + * we are using a shadow draw buffer, at qdev->surface0_shadow > + */ > + qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", clips->x1, clips->x2, > + clips->y1, clips->y2); > + image->dx = clips->x1; > + image->dy = clips->y1; > + image->width = drm_clip_rect_width(clips); > + image->height = drm_clip_rect_height(clips); > + image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized > + warnings */ > + image->bg_color = 0; > + image->depth = 32; /* TODO: take from somewhere? */ > + image->cmap.start = 0; > + image->cmap.len = 0; > + image->cmap.red = NULL; > + image->cmap.green = NULL; > + image->cmap.blue = NULL; > + image->cmap.transp = NULL; > + image->data = qfbdev->shadow + (clips->x1 * 4) + (stride * clips->y1); > + > + qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > + qxl_draw_opaque_fb(&qxl_fb_image, stride); > + > + return 0; > +} > + > +static const struct drm_framebuffer_funcs qxlfb_fb_funcs = { > + .destroy = qxl_user_framebuffer_destroy, > + .dirty = qxlfb_framebuffer_dirty, > +}; > + > static int qxlfb_create(struct qxl_fbdev *qfbdev, > struct drm_fb_helper_surface_size *sizes) > { > @@ -383,7 +275,8 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, > > info->par = qfbdev; > > - qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj); > + qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj, > + &qxlfb_fb_funcs); > > fb = &qfbdev->qfb.base; > > @@ -504,7 +397,6 @@ int qxl_fbdev_init(struct qxl_device *qdev) > qfbdev->qdev = qdev; > qdev->mode_info.qfbdev = qfbdev; > spin_lock_init(&qfbdev->delayed_ops_lock); > - spin_lock_init(&qfbdev->dirty.lock); > INIT_LIST_HEAD(&qfbdev->delayed_ops); > > drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper, > diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c > index b2977a1..2319800 100644 > --- a/drivers/gpu/drm/qxl/qxl_kms.c > +++ b/drivers/gpu/drm/qxl/qxl_kms.c > @@ -261,10 +261,6 @@ static int qxl_device_init(struct qxl_device *qdev, > qdev->gc_queue = create_singlethread_workqueue("qxl_gc"); > INIT_WORK(&qdev->gc_work, qxl_gc_work); > > - r = qxl_fb_init(qdev); > - if (r) > - return r; > - > return 0; > } > > -- > 2.2.2 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
next prev parent reply other threads:[~2016-04-25 9:16 UTC|newest] Thread overview: 87+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-04-24 20:48 [PATCH v2 0/8] drm: Add fbdev deferred io support to helpers Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-24 20:48 ` [PATCH v2 1/8] drm/rect: Add some drm_clip_rect utility functions Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-25 9:02 ` Daniel Vetter 2016-04-25 9:02 ` Daniel Vetter 2016-04-25 9:02 ` Daniel Vetter 2016-04-25 12:39 ` Ville Syrjälä 2016-04-25 12:39 ` Ville Syrjälä 2016-04-25 12:39 ` Ville Syrjälä 2016-04-25 12:55 ` Noralf Trønnes 2016-04-25 12:55 ` Noralf Trønnes 2016-04-25 12:55 ` Noralf Trønnes 2016-04-25 13:02 ` Ville Syrjälä 2016-04-25 13:02 ` Ville Syrjälä 2016-04-25 14:03 ` Noralf Trønnes 2016-04-25 14:03 ` Noralf Trønnes 2016-04-25 14:03 ` Noralf Trønnes 2016-04-25 15:09 ` Ville Syrjälä 2016-04-25 15:09 ` Ville Syrjälä 2016-04-25 15:09 ` Ville Syrjälä 2016-04-25 16:05 ` Daniel Vetter 2016-04-25 16:05 ` Daniel Vetter 2016-04-25 16:05 ` Daniel Vetter 2016-04-25 16:38 ` Ville Syrjälä 2016-04-25 16:38 ` Ville Syrjälä 2016-04-25 16:38 ` Ville Syrjälä 2016-04-25 18:35 ` Noralf Trønnes 2016-04-25 18:35 ` Noralf Trønnes 2016-04-25 18:35 ` Noralf Trønnes 2016-04-25 19:03 ` Daniel Vetter 2016-04-25 19:03 ` Daniel Vetter 2016-04-25 19:03 ` Daniel Vetter 2016-04-25 21:13 ` Laurent Pinchart 2016-04-25 21:13 ` Laurent Pinchart 2016-04-26 16:26 ` Noralf Trønnes 2016-04-26 16:26 ` Noralf Trønnes 2016-04-24 20:48 ` [PATCH v2 2/8] drm/udl: Change drm_fb_helper_sys_*() calls to sys_*() Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-24 20:48 ` [PATCH v2 3/8] drm/qxl: " Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-25 9:03 ` Daniel Vetter 2016-04-25 9:03 ` Daniel Vetter 2016-04-25 9:03 ` Daniel Vetter 2016-04-24 20:48 ` [PATCH v2 4/8] drm/fb-helper: Add fb_deferred_io support Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-25 9:09 ` Daniel Vetter 2016-04-25 9:09 ` Daniel Vetter 2016-04-26 16:24 ` Noralf Trønnes 2016-04-26 16:24 ` Noralf Trønnes 2016-04-26 16:24 ` Noralf Trønnes 2016-04-26 17:19 ` Daniel Vetter 2016-04-26 17:19 ` Daniel Vetter 2016-04-26 17:19 ` Daniel Vetter 2016-04-27 9:45 ` Noralf Trønnes 2016-04-27 9:45 ` Noralf Trønnes 2016-04-27 9:45 ` Noralf Trønnes 2016-04-27 11:14 ` Daniel Vetter 2016-04-27 11:14 ` Daniel Vetter 2016-04-27 11:14 ` Daniel Vetter 2016-04-24 20:48 ` [PATCH v2 5/8] fbdev: fb_defio: Export fb_deferred_io_mmap Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-24 20:48 ` Noralf Trønnes 2016-04-25 9:11 ` Daniel Vetter 2016-04-25 9:11 ` Daniel Vetter 2016-04-25 9:11 ` Daniel Vetter 2016-04-24 20:49 ` [PATCH v2 6/8] drm/fb-cma-helper: Add fb_deferred_io support Noralf Trønnes 2016-04-24 20:49 ` Noralf Trønnes 2016-04-24 20:49 ` Noralf Trønnes 2016-04-25 9:15 ` Daniel Vetter 2016-04-25 9:15 ` Daniel Vetter 2016-04-25 9:15 ` Daniel Vetter 2016-04-24 20:49 ` [PATCH v2 7/8] drm/qxl: Use drm_fb_helper deferred_io support Noralf Trønnes 2016-04-24 20:49 ` Noralf Trønnes 2016-04-24 20:49 ` Noralf Trønnes 2016-04-25 9:16 ` Daniel Vetter [this message] 2016-04-25 9:16 ` Daniel Vetter 2016-04-24 20:49 ` [PATCH v2 8/8] drm/udl: " Noralf Trønnes 2016-04-24 20:49 ` Noralf Trønnes 2016-04-24 20:49 ` Noralf Trønnes 2016-04-25 9:17 ` Daniel Vetter 2016-04-25 9:17 ` Daniel Vetter 2016-04-25 9:17 ` Daniel Vetter
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20160425091615.GT2510@phenom.ffwll.local \ --to=daniel@ffwll.ch \ --cc=dri-devel@lists.freedesktop.org \ --cc=laurent.pinchart@ideasonboard.com \ --cc=linux-fbdev@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=noralf@tronnes.org \ --cc=tomi.valkeinen@ti.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.