[RFC 3/7] drm/fb-helper: Support shadow buffer with deferred io

Noralf Trønnes noralf at tronnes.org
Wed Jul 12 13:46:01 UTC 2017


This adds support for using a shadow buffer for fbdev that is
copied to the real buffer during dirty flushing.
shmem buffers doesn't work with the fbdev deferred io functions,
because it touches page->mapping and page->lru.

Signed-off-by: Noralf Trønnes <noralf at tronnes.org>
---
 drivers/gpu/drm/drm_fb_helper.c | 21 +++++++++++++++++++--
 include/drm/drm_fb_helper.h     |  8 ++++++++
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 721511d..d8b2690 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -739,8 +739,25 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)
 	spin_unlock_irqrestore(&helper->dirty_lock, flags);
 
 	/* call dirty callback only when it has been really touched */
-	if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2)
-		helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
+	if (clip_copy.x1 > clip_copy.x2 || clip_copy.y1 > clip_copy.y2)
+		return;
+
+	/* using shadow buffer? */
+	if (helper->defio_vaddr) {
+		unsigned int pitch = helper->fb->pitches[0];
+		u8 cpp = helper->fb->format->cpp[0];
+		unsigned int y;
+
+		for (y = clip_copy.y1; y < clip_copy.y2; y++) {
+			size_t offset = (y * pitch) + (clip_copy.x1 * cpp);
+
+			memcpy(helper->defio_vaddr + offset,
+			       helper->fbdev->screen_buffer + offset,
+			       (clip_copy.x2 - clip_copy.x1) * cpp);
+		}
+	}
+
+	helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
 }
 
 /**
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index ea170b9..159d5dd 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -203,6 +203,14 @@ struct drm_fb_helper {
 	struct drm_clip_rect dirty_clip;
 	spinlock_t dirty_lock;
 	struct work_struct dirty_work;
+	/**
+	 * @defio_vaddr:
+	 *
+	 * Destination address for shadowed and deferred framebuffer. If this
+	 * is set, the dirty area is copied from &fb_info->screen_buffer to
+	 * this address before calling &drm_framebuffer_funcs->dirty.
+	 */
+	void *defio_vaddr;
 	struct work_struct resume_work;
 
 	/**
-- 
2.7.4



More information about the dri-devel mailing list