On Mon, Jun 29, 2015 at 01:44:44PM -0700, Rodrigo Vivi wrote: > There are cases we need to mark dirty/damaged areas, specially with > operations that touches frontbuffer directly. To cover these cases > this patch introduces the optional fb_dirty operation. > > Signed-off-by: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> The problem is that drm ->dirty() hook must be called from process context, and iirc some of these callbacks can be called from softirq context (for cursor updates). Since this is a special drm requirement I think it'd be better to implement this in the drm fbdev emulation (by wrapping the various cfb_* functions). We'd also need to do the actual ->dirty() call in an async worker. And that needs to check whether fbdev is still in charge or whether the work item raced with a kms client. For the async worker you can look into qxl_fb.c. Essentially you could copy all these functions into drm_fb_helper.c, give them suitable prefixes and in qxl_fb_work instead of calling qxl_fb_dirty_flush directly we'd call ->dirty() on the fbdev fb through the generic vfunc hook. That one is already implement and hooked up as qxl_framebuffer_surface_dirty. We don't even need to grab any locks in the worker since the normal DIRTYFB ioctl is also lockless. -Daniel > --- > drivers/video/fbdev/core/cfbcopyarea.c | 3 +++ > drivers/video/fbdev/core/cfbfillrect.c | 3 +++ > drivers/video/fbdev/core/cfbimgblt.c | 4 ++++ > drivers/video/fbdev/core/syscopyarea.c | 3 +++ > drivers/video/fbdev/core/sysfillrect.c | 3 +++ > drivers/video/fbdev/core/sysimgblt.c | 4 ++++ > include/linux/fb.h | 3 +++ > 7 files changed, 23 insertions(+) > > diff --git a/drivers/video/fbdev/core/cfbcopyarea.c b/drivers/video/fbdev/core/cfbcopyarea.c > index 6d4bfee..2e5b69f 100644 > --- a/drivers/video/fbdev/core/cfbcopyarea.c > +++ b/drivers/video/fbdev/core/cfbcopyarea.c > @@ -427,6 +427,9 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) > src_idx += bits_per_line; > } > } > + > + if (p->fbops->fb_dirty) > + p->fbops->fb_dirty(p, dx, dy, width, height); > } > > EXPORT_SYMBOL(cfb_copyarea); > diff --git a/drivers/video/fbdev/core/cfbfillrect.c b/drivers/video/fbdev/core/cfbfillrect.c > index ba9f58b..c8732d5 100644 > --- a/drivers/video/fbdev/core/cfbfillrect.c > +++ b/drivers/video/fbdev/core/cfbfillrect.c > @@ -362,6 +362,9 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) > dst_idx += p->fix.line_length*8; > } > } > + > + if (p->fbops->fb_dirty) > + p->fbops->fb_dirty(p, rect->dx, rect->dy, width, height); > } > > EXPORT_SYMBOL(cfb_fillrect); > diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c > index a2bb276..09c2dbe 100644 > --- a/drivers/video/fbdev/core/cfbimgblt.c > +++ b/drivers/video/fbdev/core/cfbimgblt.c > @@ -267,6 +267,7 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) > u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; > u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; > u32 width = image->width; > + u32 height = image->height; > u32 dx = image->dx, dy = image->dy; > u8 __iomem *dst1; > > @@ -303,6 +304,9 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) > start_index, pitch_index); > } else > color_imageblit(image, p, dst1, start_index, pitch_index); > + > + if (p->fbops->fb_dirty) > + p->fbops->fb_dirty(p, dx, dy, width, height); > } > > EXPORT_SYMBOL(cfb_imageblit); > diff --git a/drivers/video/fbdev/core/syscopyarea.c b/drivers/video/fbdev/core/syscopyarea.c > index c1eda31..3f74683 100644 > --- a/drivers/video/fbdev/core/syscopyarea.c > +++ b/drivers/video/fbdev/core/syscopyarea.c > @@ -360,6 +360,9 @@ void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area) > src_idx += bits_per_line; > } > } > + > + if (p->fbops->fb_dirty) > + p->fbops->fb_dirty(p, dx, dy, width, height); > } > > EXPORT_SYMBOL(sys_copyarea); > diff --git a/drivers/video/fbdev/core/sysfillrect.c b/drivers/video/fbdev/core/sysfillrect.c > index 33ee3d3..f2c3efa 100644 > --- a/drivers/video/fbdev/core/sysfillrect.c > +++ b/drivers/video/fbdev/core/sysfillrect.c > @@ -326,6 +326,9 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) > dst_idx += p->fix.line_length*8; > } > } > + > + if (p->fbops->fb_dirty) > + p->fbops->fb_dirty(p, rect->dx, rect->dy, width, height); > } > > EXPORT_SYMBOL(sys_fillrect); > diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c > index a4d05b1..d690fb5 100644 > --- a/drivers/video/fbdev/core/sysimgblt.c > +++ b/drivers/video/fbdev/core/sysimgblt.c > @@ -243,6 +243,7 @@ void sys_imageblit(struct fb_info *p, const struct fb_image *image) > u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; > u32 width = image->width; > u32 dx = image->dx, dy = image->dy; > + u32 height = image->height; > void *dst1; > > if (p->state != FBINFO_STATE_RUNNING) > @@ -278,6 +279,9 @@ void sys_imageblit(struct fb_info *p, const struct fb_image *image) > start_index, pitch_index); > } else > color_imageblit(image, p, dst1, start_index, pitch_index); > + > + if (p->fbops->fb_dirty) > + p->fbops->fb_dirty(p, dx, dy, width, height); > } > > EXPORT_SYMBOL(sys_imageblit); > diff --git a/include/linux/fb.h b/include/linux/fb.h > index 043f328..e17e4b7 100644 > --- a/include/linux/fb.h > +++ b/include/linux/fb.h > @@ -284,6 +284,9 @@ struct fb_ops { > /* wait for blit idle, optional */ > int (*fb_sync)(struct fb_info *info); > > + /* Mark rect as dirty (optional) */ > + void (*fb_dirty)(struct fb_info *info, u32 x1, u32 y1, u32 x2, u32 y2); > + > /* perform fb specific ioctl (optional) */ > int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, > unsigned long arg); > -- > 2.1.0 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx