All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH v2 09/26] video: Add support for copying to a hardware framebuffer
Date: Sun, 24 May 2020 19:48:46 -0600	[thread overview]
Message-ID: <20200524194852.v2.9.I27c41308a73654764c8980faf799b37138c1e4b3@changeid> (raw)
In-Reply-To: <20200525014904.115621-1-sjg@chromium.org>

Some architectures use a cached framebuffer and flush the cache as needed
so that changes are visible. This is supported by U-Boot.

However x86 uses an uncached framebuffer with a 'write-combining' feature
to speed up writes.  Reads are permitted but they are extremely expensive.

Unfortunately, reading from the frame buffer is quite common, e.g. to
scroll it. This makes scrolling very slow.

Add a new feature which supports copying modified parts of the frame
buffer to the uncached hardware buffer. This speeds up scrolling by at
least 10x on x86 so the extra complexity cost seems worth it.

As a starting point, add the Kconfig, update the video structures to keep
track of the buffer and add a function to do the copy.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Anatolij Gustschin <agust@denx.de>
---

Changes in v2: None

 drivers/video/Kconfig        | 12 ++++++++
 drivers/video/video-uclass.c | 54 ++++++++++++++++++++++++++++++++++++
 include/video.h              | 29 +++++++++++++++++++
 3 files changed, 95 insertions(+)

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 38123543a5..1cf63efd48 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -14,6 +14,18 @@ config DM_VIDEO
 	  option compiles in the video uclass and routes all LCD/video access
 	  through this.
 
+config VIDEO_COPY
+	bool "Enable copying the frame buffer to a hardware copy"
+	depends on DM_VIDEO
+	help
+	  On some machines (e.g. x86), reading from the frame buffer is very
+	  slow because it is uncached. To improve performance, this feature
+	  allows the frame buffer to be kept in cached memory (allocated by
+	  U-Boot) and then copied to the hardware frame-buffer as needed.
+
+	  To use this, your video driver must set @copy_base in
+	  struct video_uc_platdata.
+
 config BACKLIGHT_PWM
 	bool "Generic PWM based Backlight Driver"
 	depends on DM_VIDEO && DM_PWM
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index bf396d1091..9fbaa8db10 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -4,6 +4,7 @@
  */
 
 #include <common.h>
+#include <console.h>
 #include <cpu_func.h>
 #include <dm.h>
 #include <log.h>
@@ -200,6 +201,59 @@ int video_get_ysize(struct udevice *dev)
 	return priv->ysize;
 }
 
+#ifdef CONFIG_VIDEO_COPY
+int video_sync_copy(struct udevice *dev, void *from, void *to)
+{
+	struct video_priv *priv = dev_get_uclass_priv(dev);
+
+	if (priv->copy_fb) {
+		long offset, size;
+
+		/* Find the offset of the first byte to copy */
+		if ((ulong)to > (ulong)from) {
+			size = to - from;
+			offset = from - priv->fb;
+		} else {
+			size = from - to;
+			offset = to - priv->fb;
+		}
+
+		/*
+		 * Allow a bit of leeway for valid requests somewhere near the
+		 * frame buffer
+		 */
+		if (offset < -priv->fb_size || offset > 2 * priv->fb_size) {
+#ifdef DEBUG
+			char str[80];
+
+			snprintf(str, sizeof(str),
+				 "[sync_copy fb=%p, from=%p, to=%p, offset=%lx]",
+				 priv->fb, from, to, offset);
+			console_puts_select_stderr(true, str);
+#endif
+			return -EFAULT;
+		}
+
+		/*
+		 * Silently crop the memcpy. This allows callers to avoid doing
+		 * this themselves. It is common for the end pointer to go a
+		 * few lines after the end of the frame buffer, since most of
+		 * the update algorithms terminate a line after their last write
+		 */
+		if (offset + size > priv->fb_size) {
+			size = priv->fb_size - offset;
+		} else if (offset < 0) {
+			size += offset;
+			offset = 0;
+		}
+
+		memcpy(priv->copy_fb + offset, priv->fb + offset, size);
+	}
+
+	return 0;
+}
+#endif
+
 /* Set up the colour map */
 static int video_pre_probe(struct udevice *dev)
 {
diff --git a/include/video.h b/include/video.h
index 813b5653b0..1a0ffd8037 100644
--- a/include/video.h
+++ b/include/video.h
@@ -30,11 +30,14 @@ struct udevice;
  *	buffer should start on. If 0, 1MB is assumed
  * @size: Frame-buffer size, in bytes
  * @base: Base address of frame buffer, 0 if not yet known
+ * @copy_base: Base address of a hardware copy of the frame buffer. See
+ *	CONFIG_VIDEO_COPY.
  */
 struct video_uc_platdata {
 	uint align;
 	uint size;
 	ulong base;
+	ulong copy_base;
 };
 
 enum video_polarity {
@@ -75,6 +78,8 @@ enum video_log2_bpp {
  * @font_size:	Font size in pixels (0 to use a default value)
  * @fb:		Frame buffer
  * @fb_size:	Frame buffer size
+ * @copy_fb:	Copy of the frame buffer to keep up to date; see struct
+ *		video_uc_platdata
  * @line_length:	Length of each frame buffer line, in bytes. This can be
  *		set by the driver, but if not, the uclass will set it after
  *		probing
@@ -101,6 +106,7 @@ struct video_priv {
 	 */
 	void *fb;
 	int fb_size;
+	void *copy_fb;
 	int line_length;
 	u32 colour_fg;
 	u32 colour_bg;
@@ -214,6 +220,29 @@ void video_set_flush_dcache(struct udevice *dev, bool flush);
  */
 void video_set_default_colors(struct udevice *dev, bool invert);
 
+#ifdef CONFIG_VIDEO_COPY
+/**
+ * vidconsole_sync_copy() - Sync back to the copy framebuffer
+ *
+ * This ensures that the copy framebuffer has the same data as the framebuffer
+ * for a particular region. It should be called after the framebuffer is updated
+ *
+ * @from and @to can be in either order. The region between them is synced.
+ *
+ * @dev: Vidconsole device being updated
+ * @from: Start/end address within the framebuffer (->fb)
+ * @to: Other address within the frame buffer
+ * @return 0 if OK, -EFAULT if the start address is before the start of the
+ *	frame buffer start
+ */
+int video_sync_copy(struct udevice *dev, void *from, void *to);
+#else
+static inline int video_sync_copy(struct udevice *dev, void *from, void *to)
+{
+	return 0;
+}
+#endif
+
 #endif /* CONFIG_DM_VIDEO */
 
 #ifndef CONFIG_DM_VIDEO
-- 
2.27.0.rc0.183.gde8f92d652-goog

  parent reply	other threads:[~2020-05-25  1:48 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-25  1:48 [PATCH v2 00/26] x86: video: Speed up the framebuffer Simon Glass
2020-05-25  1:48 ` [PATCH v2 01/26] x86: fsp: Reinit the FPU after FSP meminit Simon Glass
2020-05-25  1:48 ` [PATCH v2 02/26] console: Add a way to output to serial only Simon Glass
2020-05-25  1:48 ` [PATCH v2 03/26] video: Show an error when a vidconsole function fails Simon Glass
2020-05-25  1:48 ` [PATCH v2 04/26] sandbox: video: Allow selection of rotated console Simon Glass
2020-05-25  1:48 ` [PATCH v2 05/26] video: Split out expression parts into variables Simon Glass
2020-05-25  1:48 ` [PATCH v2 06/26] video: Adjust rotated console to start at right edge Simon Glass
2020-05-25  1:48 ` [PATCH v2 07/26] video: Drop unnecessary #ifdef around vid_console_color() Simon Glass
2020-05-25  1:48 ` [PATCH v2 08/26] video: Add a comment for struct video_uc_platdata Simon Glass
2020-05-25  1:48 ` Simon Glass [this message]
2020-05-25  1:48 ` [PATCH v2 10/26] video: Set up the copy framebuffer when enabled Simon Glass
2020-05-25  1:48 ` [PATCH v2 11/26] video: Clear the copy framebuffer when clearing the screen Simon Glass
2020-05-25  1:48 ` [PATCH v2 12/26] video: Add helpers for vidconsole for the copy framebuffer Simon Glass
2020-05-25  1:48 ` [PATCH v2 13/26] video: Update normal console to support copy buffer Simon Glass
2020-05-25  1:48 ` [PATCH v2 14/26] video: Update truetype " Simon Glass
2020-05-25  1:48 ` [PATCH v2 15/26] video: Update rotated " Simon Glass
2020-05-25  1:48 ` [PATCH v2 16/26] video: Update the copy framebuffer when writing bitmaps Simon Glass
2020-05-25  1:48 ` [PATCH v2 17/26] video: Add comments to struct sandbox_sdl_plat Simon Glass
2020-05-25  1:48 ` [PATCH v2 18/26] video: sandbox: Add support for the copy framebuffer Simon Glass
2020-05-25  1:48 ` [PATCH v2 19/26] video: pci: Set up " Simon Glass
2020-05-25  1:48 ` [PATCH v2 20/26] x86: fsp: video: Allocate a frame buffer when needed Simon Glass
2020-05-25  1:48 ` [PATCH v2 21/26] video: Correctly handle multiple framebuffers Simon Glass
2020-05-25  1:48 ` [PATCH v2 22/26] x86: video: Support copy framebuffer with probed devices Simon Glass
2020-05-25  1:49 ` [PATCH v2 23/26] chromebook_samus: Enable the copy framebuffer Simon Glass
2020-05-25  1:49 ` [PATCH v2 24/26] chromebook_link: " Simon Glass
2020-05-25  1:49 ` [PATCH v2 25/26] minnowmax: " Simon Glass
2020-05-25  1:49 ` [PATCH v2 26/26] x86: minnowmax: Drop screen resolution to 1024x768 Simon Glass

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=20200524194852.v2.9.I27c41308a73654764c8980faf799b37138c1e4b3@changeid \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /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: link
Be 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.