video: Use VIDEO_DAMAGE for VIDEO_COPY
CONFIG_VIDEO_COPY implemented a range-based copying mechanism: If we
print a single character, it will always copy the full range of bytes
from the top left corner of the character to the lower right onto the
uncached frame buffer. This includes pretty much the full line contents
of the printed character.
Since we now have proper damage tracking, let's make use of that to reduce
the amount of data we need to copy. With this patch applied, we will only
copy the tiny rectangle surrounding characters when we print them,
speeding up the video console.
After this, changes to the main frame buffer are not immediately copied
to the copy frame buffer, but postponed until the next video device
sync. So issue an explicit sync before inspecting the copy frame buffer
contents for the video tests.
Signed-off-by: Alexander Graf <agraf@csgraf.de>
[Alper: Rebase for fontdata->height/w, fill_part(), fix memmove(dev),
drop from defconfig, use damage.xstart/yend, use IS_ENABLED(),
call video_sync() before copy_fb check, update video_copy test]
Co-developed-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Link: https://lore.kernel.org/u-boot/20230821135111.3558478-12-alpernebiyasak@gmail.com/
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 8fb3b22..0d582e7 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -171,7 +171,7 @@
struct video_priv *priv = dev_get_uclass_priv(dev);
void *start, *line;
int pixels = xend - xstart;
- int row, i, ret;
+ int row, i;
start = priv->fb + ystart * priv->line_length;
start += xstart * VNBYTES(priv->bpix);
@@ -210,9 +210,6 @@
}
line += priv->line_length;
}
- ret = video_sync_copy(dev, start, line);
- if (ret)
- return ret;
video_damage(dev, xstart, ystart, xend - xstart, yend - ystart);
@@ -235,7 +232,6 @@
int video_fill(struct udevice *dev, u32 colour)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
- int ret;
switch (priv->bpix) {
case VIDEO_BPP16:
@@ -262,9 +258,6 @@
memset(priv->fb, colour, priv->fb_size);
break;
}
- ret = video_sync_copy(dev, priv->fb, priv->fb + priv->fb_size);
- if (ret)
- return ret;
video_damage(dev, 0, 0, priv->xsize, priv->ysize);
@@ -435,6 +428,27 @@
}
#endif
+static void video_flush_copy(struct udevice *vid)
+{
+ struct video_priv *priv = dev_get_uclass_priv(vid);
+
+ if (!priv->copy_fb)
+ return;
+
+ if (priv->damage.xend && priv->damage.yend) {
+ int lstart = priv->damage.xstart * VNBYTES(priv->bpix);
+ int lend = priv->damage.xend * VNBYTES(priv->bpix);
+ int y;
+
+ for (y = priv->damage.ystart; y < priv->damage.yend; y++) {
+ ulong offset = (y * priv->line_length) + lstart;
+ ulong len = lend - lstart;
+
+ memcpy(priv->copy_fb + offset, priv->fb + offset, len);
+ }
+ }
+}
+
/* Flush video activity to the caches */
int video_sync(struct udevice *vid, bool force)
{
@@ -442,6 +456,9 @@
struct video_ops *ops = video_get_ops(vid);
int ret;
+ if (IS_ENABLED(CONFIG_VIDEO_COPY))
+ video_flush_copy(vid);
+
if (ops && ops->video_sync) {
ret = ops->video_sync(vid);
if (ret)
@@ -525,69 +542,6 @@
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[120];
-
- snprintf(str, sizeof(str),
- "[** FAULT 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;
-}
-
-int video_sync_copy_all(struct udevice *dev)
-{
- struct video_priv *priv = dev_get_uclass_priv(dev);
-
- video_sync_copy(dev, priv->fb, priv->fb + priv->fb_size);
-
- return 0;
-}
-
-#endif
-
#define SPLASH_DECL(_name) \
extern u8 __splash_ ## _name ## _begin[]; \
extern u8 __splash_ ## _name ## _end[]