[PATCH v2 3/6] drm/fb-helper: Instanciate shadow FB if configured in device's mode_config

Thomas Zimmermann
Fri, 05 Jul 2019 09:26:10 -0000

Generic framebuffer emulation uses a shadow buffer for framebuffers with
dirty() function. If drivers want to use the shadow FB without such a
function, they can now set prefer_shadow or prefer_shadow_fbdev in their
mode_config structures. The former flag is exported to userspace, the latter
flag is fbdev-only.

Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
---
 drivers/gpu/drm/drm_fb_helper.c | 19 ++++++++++++++-----
 include/drm/drm_mode_config.h   |  5 +++++
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 7ba6a0255821..56ef169e1814 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -421,7 +421,9 @@ static void drm_fb_helper_dirty_work(struct work_struct
*work)
 				return;
 			drm_fb_helper_dirty_blit_real(helper, &clip_copy);
 		}
-		helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy,
1);
+		if (helper->fb->funcs->dirty)
+			helper->fb->funcs->dirty(helper->fb, NULL, 0, 0,
+						 &clip_copy, 1);

 		if (helper->buffer)
 			drm_client_buffer_vunmap(helper->buffer);
@@ -620,9 +622,6 @@ static void drm_fb_helper_dirty(struct fb_info *info, u32 x,
u32 y,
 	struct drm_clip_rect *clip = &helper->dirty_clip;
 	unsigned long flags;

-	if (!helper->fb->funcs->dirty)
-		return;
-
 	spin_lock_irqsave(&helper->dirty_lock, flags);
 	clip->x1 = min_t(u32, clip->x1, x);
 	clip->y1 = min_t(u32, clip->y1, y);
@@ -2166,6 +2165,16 @@ static struct fb_deferred_io drm_fbdev_defio = {
 	.deferred_io	= drm_fb_helper_deferred_io,
 };

+static bool drm_fbdev_use_shadow_fb(struct drm_fb_helper *fb_helper)
+{
+	struct drm_device *dev = fb_helper->dev;
+	struct drm_framebuffer *fb = fb_helper->fb;
+
+	return dev->mode_config.prefer_shadow_fbdev |
+	       dev->mode_config.prefer_shadow |
+	       !!fb->funcs->dirty;
+}
+
 /**
  * drm_fb_helper_generic_probe - Generic fbdev emulation probe helper
  * @fb_helper: fbdev helper structure
@@ -2213,7 +2222,7 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper
*fb_helper,

 	drm_fb_helper_fill_info(fbi, fb_helper, sizes);

-	if (fb->funcs->dirty) {
+	if (drm_fbdev_use_shadow_fb(fb_helper)) {
 		struct fb_ops *fbops;
 		void *shadow;

diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 759d462d028b..e1c751aca353 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -347,6 +347,8 @@ struct drm_mode_config_funcs {
  * @output_poll_work: delayed work for polling in process context
  * @preferred_depth: preferred RBG pixel depth, used by fb helpers
  * @prefer_shadow: hint to userspace to prefer shadow-fb rendering
+ * @prefer_shadow_fbdev: hint to framebuffer emulation to prefer shadow-fb \
+	rendering
  * @cursor_width: hint to userspace for max cursor width
  * @cursor_height: hint to userspace for max cursor height
  * @helper_private: mid-layer private data
@@ -852,6 +854,9 @@ struct drm_mode_config {
 	/* dumb ioctl parameters */
 	uint32_t preferred_depth, prefer_shadow;

+	/* fbdev parameters */
+	uint32_t prefer_shadow_fbdev;
+
 	/**
 	 * @quirk_addfb_prefer_xbgr_30bpp:
 	 *
--
2.21.0